Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

lustrec / myocamlbuild.ml @ 719f9992

History | View | Annotate | Download (16.2 KB)

1
(* OASIS_START *)
2
(* DO NOT EDIT (digest: 5a9a2168dcb86db37476d58b8c0e25b3) *)
3
module OASISGettext = struct
4
(* # 22 "src/oasis/OASISGettext.ml" *)
5

    
6

    
7
  let ns_ str =
8
    str
9

    
10

    
11
  let s_ str =
12
    str
13

    
14

    
15
  let f_ (str: ('a, 'b, 'c, 'd) format4) =
16
    str
17

    
18

    
19
  let fn_ fmt1 fmt2 n =
20
    if n = 1 then
21
      fmt1^^""
22
    else
23
      fmt2^^""
24

    
25

    
26
  let init =
27
    []
28

    
29

    
30
end
31

    
32
module OASISExpr = struct
33
(* # 22 "src/oasis/OASISExpr.ml" *)
34

    
35

    
36

    
37

    
38

    
39
  open OASISGettext
40

    
41

    
42
  type test = string
43

    
44

    
45
  type flag = string
46

    
47

    
48
  type t =
49
    | EBool of bool
50
    | ENot of t
51
    | EAnd of t * t
52
    | EOr of t * t
53
    | EFlag of flag
54
    | ETest of test * string
55

    
56

    
57

    
58
  type 'a choices = (t * 'a) list
59

    
60

    
61
  let eval var_get t =
62
    let rec eval' =
63
      function
64
        | EBool b ->
65
            b
66

    
67
        | ENot e ->
68
            not (eval' e)
69

    
70
        | EAnd (e1, e2) ->
71
            (eval' e1) && (eval' e2)
72

    
73
        | EOr (e1, e2) ->
74
            (eval' e1) || (eval' e2)
75

    
76
        | EFlag nm ->
77
            let v =
78
              var_get nm
79
            in
80
              assert(v = "true" || v = "false");
81
              (v = "true")
82

    
83
        | ETest (nm, vl) ->
84
            let v =
85
              var_get nm
86
            in
87
              (v = vl)
88
    in
89
      eval' t
90

    
91

    
92
  let choose ?printer ?name var_get lst =
93
    let rec choose_aux =
94
      function
95
        | (cond, vl) :: tl ->
96
            if eval var_get cond then
97
              vl
98
            else
99
              choose_aux tl
100
        | [] ->
101
            let str_lst =
102
              if lst = [] then
103
                s_ "<empty>"
104
              else
105
                String.concat
106
                  (s_ ", ")
107
                  (List.map
108
                     (fun (cond, vl) ->
109
                        match printer with
110
                          | Some p -> p vl
111
                          | None -> s_ "<no printer>")
112
                     lst)
113
            in
114
              match name with
115
                | Some nm ->
116
                    failwith
117
                      (Printf.sprintf
118
                         (f_ "No result for the choice list '%s': %s")
119
                         nm str_lst)
120
                | None ->
121
                    failwith
122
                      (Printf.sprintf
123
                         (f_ "No result for a choice list: %s")
124
                         str_lst)
125
    in
126
      choose_aux (List.rev lst)
127

    
128

    
129
end
130

    
131

    
132
# 132 "myocamlbuild.ml"
133
module BaseEnvLight = struct
134
(* # 22 "src/base/BaseEnvLight.ml" *)
135

    
136

    
137
  module MapString = Map.Make(String)
138

    
139

    
140
  type t = string MapString.t
141

    
142

    
143
  let default_filename =
144
    Filename.concat
145
      (Sys.getcwd ())
146
      "setup.data"
147

    
148

    
149
  let load ?(allow_empty=false) ?(filename=default_filename) () =
150
    if Sys.file_exists filename then
151
      begin
152
        let chn =
153
          open_in_bin filename
154
        in
155
        let st =
156
          Stream.of_channel chn
157
        in
158
        let line =
159
          ref 1
160
        in
161
        let st_line =
162
          Stream.from
163
            (fun _ ->
164
               try
165
                 match Stream.next st with
166
                   | '\n' -> incr line; Some '\n'
167
                   | c -> Some c
168
               with Stream.Failure -> None)
169
        in
170
        let lexer =
171
          Genlex.make_lexer ["="] st_line
172
        in
173
        let rec read_file mp =
174
          match Stream.npeek 3 lexer with
175
            | [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] ->
176
                Stream.junk lexer;
177
                Stream.junk lexer;
178
                Stream.junk lexer;
179
                read_file (MapString.add nm value mp)
180
            | [] ->
181
                mp
182
            | _ ->
183
                failwith
184
                  (Printf.sprintf
185
                     "Malformed data file '%s' line %d"
186
                     filename !line)
187
        in
188
        let mp =
189
          read_file MapString.empty
190
        in
191
          close_in chn;
192
          mp
193
      end
194
    else if allow_empty then
195
      begin
196
        MapString.empty
197
      end
198
    else
199
      begin
200
        failwith
201
          (Printf.sprintf
202
             "Unable to load environment, the file '%s' doesn't exist."
203
             filename)
204
      end
205

    
206

    
207
  let rec var_expand str env =
208
    let buff =
209
      Buffer.create ((String.length str) * 2)
210
    in
211
      Buffer.add_substitute
212
        buff
213
        (fun var ->
214
           try
215
             var_expand (MapString.find var env) env
216
           with Not_found ->
217
             failwith
218
               (Printf.sprintf
219
                  "No variable %s defined when trying to expand %S."
220
                  var
221
                  str))
222
        str;
223
      Buffer.contents buff
224

    
225

    
226
  let var_get name env =
227
    var_expand (MapString.find name env) env
228

    
229

    
230
  let var_choose lst env =
231
    OASISExpr.choose
232
      (fun nm -> var_get nm env)
233
      lst
234
end
235

    
236

    
237
# 237 "myocamlbuild.ml"
238
module MyOCamlbuildFindlib = struct
239
(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
240

    
241

    
242
  (** OCamlbuild extension, copied from
243
    * http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild
244
    * by N. Pouillard and others
245
    *
246
    * Updated on 2009/02/28
247
    *
248
    * Modified by Sylvain Le Gall
249
    *)
250
  open Ocamlbuild_plugin
251

    
252

    
253
  (* these functions are not really officially exported *)
254
  let run_and_read =
255
    Ocamlbuild_pack.My_unix.run_and_read
256

    
257

    
258
  let blank_sep_strings =
259
    Ocamlbuild_pack.Lexers.blank_sep_strings
260

    
261

    
262
  let exec_from_conf exec =
263
    let exec =
264
      let env_filename = Pathname.basename BaseEnvLight.default_filename in
265
      let env = BaseEnvLight.load ~filename:env_filename ~allow_empty:true () in
266
      try
267
        BaseEnvLight.var_get exec env
268
      with Not_found ->
269
        Printf.eprintf "W: Cannot get variable %s\n" exec;
270
        exec
271
    in
272
    let fix_win32 str =
273
      if Sys.os_type = "Win32" then begin
274
        let buff = Buffer.create (String.length str) in
275
        (* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'.
276
         *)
277
        String.iter
278
          (fun c -> Buffer.add_char buff (if c = '\\' then '/' else c))
279
          str;
280
        Buffer.contents buff
281
      end else begin
282
        str
283
      end
284
    in
285
      fix_win32 exec
286

    
287
  let split s ch =
288
    let buf = Buffer.create 13 in
289
    let x = ref [] in
290
    let flush () =
291
      x := (Buffer.contents buf) :: !x;
292
      Buffer.clear buf
293
    in
294
      String.iter
295
        (fun c ->
296
           if c = ch then
297
             flush ()
298
           else
299
             Buffer.add_char buf c)
300
        s;
301
      flush ();
302
      List.rev !x
303

    
304

    
305
  let split_nl s = split s '\n'
306

    
307

    
308
  let before_space s =
309
    try
310
      String.before s (String.index s ' ')
311
    with Not_found -> s
312

    
313
  (* ocamlfind command *)
314
  let ocamlfind x = S[Sh (exec_from_conf "ocamlfind"); x]
315

    
316
  (* This lists all supported packages. *)
317
  let find_packages () =
318
    List.map before_space (split_nl & run_and_read "ocamlfind list")
319

    
320

    
321
  (* Mock to list available syntaxes. *)
322
  let find_syntaxes () = ["camlp4o"; "camlp4r"]
323

    
324

    
325
  let well_known_syntax = [
326
    "camlp4.quotations.o";
327
    "camlp4.quotations.r";
328
    "camlp4.exceptiontracer";
329
    "camlp4.extend";
330
    "camlp4.foldgenerator";
331
    "camlp4.listcomprehension";
332
    "camlp4.locationstripper";
333
    "camlp4.macro";
334
    "camlp4.mapgenerator";
335
    "camlp4.metagenerator";
336
    "camlp4.profiler";
337
    "camlp4.tracer"
338
  ]
339

    
340

    
341
  let dispatch =
342
    function
343
      | After_options ->
344
          (* By using Before_options one let command line options have an higher
345
           * priority on the contrary using After_options will guarantee to have
346
           * the higher priority override default commands by ocamlfind ones *)
347
          Options.ocamlc     := ocamlfind & A"ocamlc";
348
          Options.ocamlopt   := ocamlfind & A"ocamlopt";
349
          Options.ocamldep   := ocamlfind & A"ocamldep";
350
          Options.ocamldoc   := ocamlfind & A"ocamldoc";
351
          Options.ocamlmktop := ocamlfind & A"ocamlmktop";
352
          Options.ocamlmklib := ocamlfind & A"ocamlmklib"
353

    
354
      | After_rules ->
355

    
356
          (* When one link an OCaml library/binary/package, one should use
357
           * -linkpkg *)
358
          flag ["ocaml"; "link"; "program"] & A"-linkpkg";
359

    
360
          (* For each ocamlfind package one inject the -package option when
361
           * compiling, computing dependencies, generating documentation and
362
           * linking. *)
363
          List.iter
364
            begin fun pkg ->
365
              let base_args = [A"-package"; A pkg] in
366
              (* TODO: consider how to really choose camlp4o or camlp4r. *)
367
              let syn_args = [A"-syntax"; A "camlp4o"] in
368
              let args =
369
              (* Heuristic to identify syntax extensions: whether they end in
370
                 ".syntax"; some might not.
371
               *)
372
                if Filename.check_suffix pkg "syntax" ||
373
                   List.mem pkg well_known_syntax then
374
                  syn_args @ base_args
375
                else
376
                  base_args
377
              in
378
              flag ["ocaml"; "compile";  "pkg_"^pkg] & S args;
379
              flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
380
              flag ["ocaml"; "doc";      "pkg_"^pkg] & S args;
381
              flag ["ocaml"; "link";     "pkg_"^pkg] & S base_args;
382
              flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
383
            end
384
            (find_packages ());
385

    
386
          (* Like -package but for extensions syntax. Morover -syntax is useless
387
           * when linking. *)
388
          List.iter begin fun syntax ->
389
          flag ["ocaml"; "compile";  "syntax_"^syntax] & S[A"-syntax"; A syntax];
390
          flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
391
          flag ["ocaml"; "doc";      "syntax_"^syntax] & S[A"-syntax"; A syntax];
392
          flag ["ocaml"; "infer_interface"; "syntax_"^syntax] &
393
                S[A"-syntax"; A syntax];
394
          end (find_syntaxes ());
395

    
396
          (* The default "thread" tag is not compatible with ocamlfind.
397
           * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
398
           * options when using this tag. When using the "-linkpkg" option with
399
           * ocamlfind, this module will then be added twice on the command line.
400
           *
401
           * To solve this, one approach is to add the "-thread" option when using
402
           * the "threads" package using the previous plugin.
403
           *)
404
          flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
405
          flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
406
          flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
407
          flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]);
408
          flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]);
409
          flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]);
410
          flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]);
411
          flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]);
412

    
413
      | _ ->
414
          ()
415
end
416

    
417
module MyOCamlbuildBase = struct
418
(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
419

    
420

    
421
  (** Base functions for writing myocamlbuild.ml
422
      @author Sylvain Le Gall
423
    *)
424

    
425

    
426

    
427

    
428

    
429
  open Ocamlbuild_plugin
430
  module OC = Ocamlbuild_pack.Ocaml_compiler
431

    
432

    
433
  type dir = string
434
  type file = string
435
  type name = string
436
  type tag = string
437

    
438

    
439
(* # 62 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
440

    
441

    
442
  type t =
443
      {
444
        lib_ocaml: (name * dir list * string list) list;
445
        lib_c:     (name * dir * file list) list;
446
        flags:     (tag list * (spec OASISExpr.choices)) list;
447
        (* Replace the 'dir: include' from _tags by a precise interdepends in
448
         * directory.
449
         *)
450
        includes:  (dir * dir list) list;
451
      }
452

    
453

    
454
  let env_filename =
455
    Pathname.basename
456
      BaseEnvLight.default_filename
457

    
458

    
459
  let dispatch_combine lst =
460
    fun e ->
461
      List.iter
462
        (fun dispatch -> dispatch e)
463
        lst
464

    
465

    
466
  let tag_libstubs nm =
467
    "use_lib"^nm^"_stubs"
468

    
469

    
470
  let nm_libstubs nm =
471
    nm^"_stubs"
472

    
473

    
474
  let dispatch t e =
475
    let env =
476
      BaseEnvLight.load
477
        ~filename:env_filename
478
        ~allow_empty:true
479
        ()
480
    in
481
      match e with
482
        | Before_options ->
483
            let no_trailing_dot s =
484
              if String.length s >= 1 && s.[0] = '.' then
485
                String.sub s 1 ((String.length s) - 1)
486
              else
487
                s
488
            in
489
              List.iter
490
                (fun (opt, var) ->
491
                   try
492
                     opt := no_trailing_dot (BaseEnvLight.var_get var env)
493
                   with Not_found ->
494
                     Printf.eprintf "W: Cannot get variable %s\n" var)
495
                [
496
                  Options.ext_obj, "ext_obj";
497
                  Options.ext_lib, "ext_lib";
498
                  Options.ext_dll, "ext_dll";
499
                ]
500

    
501
        | After_rules ->
502
            (* Declare OCaml libraries *)
503
            List.iter
504
              (function
505
                 | nm, [], intf_modules ->
506
                     ocaml_lib nm;
507
                     let cmis =
508
                       List.map (fun m -> (String.uncapitalize m) ^ ".cmi")
509
                                intf_modules in
510
                     dep ["ocaml"; "link"; "library"; "file:"^nm^".cma"] cmis
511
                 | nm, dir :: tl, intf_modules ->
512
                     ocaml_lib ~dir:dir (dir^"/"^nm);
513
                     List.iter
514
                       (fun dir ->
515
                          List.iter
516
                            (fun str ->
517
                               flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir]))
518
                            ["compile"; "infer_interface"; "doc"])
519
                       tl;
520
                     let cmis =
521
                       List.map (fun m -> dir^"/"^(String.uncapitalize m)^".cmi")
522
                                intf_modules in
523
                     dep ["ocaml"; "link"; "library"; "file:"^dir^"/"^nm^".cma"]
524
                         cmis)
525
              t.lib_ocaml;
526

    
527
            (* Declare directories dependencies, replace "include" in _tags. *)
528
            List.iter
529
              (fun (dir, include_dirs) ->
530
                 Pathname.define_context dir include_dirs)
531
              t.includes;
532

    
533
            (* Declare C libraries *)
534
            List.iter
535
              (fun (lib, dir, headers) ->
536
                   (* Handle C part of library *)
537
                   flag ["link"; "library"; "ocaml"; "byte"; tag_libstubs lib]
538
                     (S[A"-dllib"; A("-l"^(nm_libstubs lib)); A"-cclib";
539
                        A("-l"^(nm_libstubs lib))]);
540

    
541
                   flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
542
                     (S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
543

    
544
                   flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
545
                     (S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
546

    
547
                   (* When ocaml link something that use the C library, then one
548
                      need that file to be up to date.
549
                    *)
550
                   dep ["link"; "ocaml"; "program"; tag_libstubs lib]
551
                     [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
552

    
553
                   dep  ["compile"; "ocaml"; "program"; tag_libstubs lib]
554
                     [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
555

    
556
                   (* TODO: be more specific about what depends on headers *)
557
                   (* Depends on .h files *)
558
                   dep ["compile"; "c"]
559
                     headers;
560

    
561
                   (* Setup search path for lib *)
562
                   flag ["link"; "ocaml"; "use_"^lib]
563
                     (S[A"-I"; P(dir)]);
564
              )
565
              t.lib_c;
566

    
567
              (* Add flags *)
568
              List.iter
569
              (fun (tags, cond_specs) ->
570
                 let spec = BaseEnvLight.var_choose cond_specs env in
571
                 let rec eval_specs =
572
                   function
573
                     | S lst -> S (List.map eval_specs lst)
574
                     | A str -> A (BaseEnvLight.var_expand str env)
575
                     | spec -> spec
576
                 in
577
                   flag tags & (eval_specs spec))
578
              t.flags
579
        | _ ->
580
            ()
581

    
582

    
583
  let dispatch_default t =
584
    dispatch_combine
585
      [
586
        dispatch t;
587
        MyOCamlbuildFindlib.dispatch;
588
      ]
589

    
590

    
591
end
592

    
593

    
594
# 594 "myocamlbuild.ml"
595
open Ocamlbuild_plugin;;
596
let package_default =
597
  {MyOCamlbuildBase.lib_ocaml = []; lib_c = []; flags = []; includes = []}
598
  ;;
599

    
600
let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;;
601

    
602
# 603 "myocamlbuild.ml"
603
(* OASIS_STOP *)
604
Ocamlbuild_plugin.dispatch dispatch_default;;