modernize Prelude
[sqlgg.git] / myocamlbuild.ml
blob3472d6bf9d3f560bbcdf890a8a13baa7b95f588d
1 (* OASIS_START *)
2 (* DO NOT EDIT (digest: 5a9a2168dcb86db37476d58b8c0e25b3) *)
3 module OASISGettext = struct
4 (* # 22 "src/oasis/OASISGettext.ml" *)
7 let ns_ str =
8 str
11 let s_ str =
12 str
15 let f_ (str: ('a, 'b, 'c, 'd) format4) =
16 str
19 let fn_ fmt1 fmt2 n =
20 if n = 1 then
21 fmt1^^""
22 else
23 fmt2^^""
26 let init =
30 end
32 module OASISExpr = struct
33 (* # 22 "src/oasis/OASISExpr.ml" *)
39 open OASISGettext
42 type test = string
45 type flag = string
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
58 type 'a choices = (t * 'a) list
61 let eval var_get t =
62 let rec eval' =
63 function
64 | EBool b ->
67 | ENot e ->
68 not (eval' e)
70 | EAnd (e1, e2) ->
71 (eval' e1) && (eval' e2)
73 | EOr (e1, e2) ->
74 (eval' e1) || (eval' e2)
76 | EFlag nm ->
77 let v =
78 var_get nm
80 assert(v = "true" || v = "false");
81 (v = "true")
83 | ETest (nm, vl) ->
84 let v =
85 var_get nm
87 (v = vl)
89 eval' t
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
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)
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)
126 choose_aux (List.rev lst)
132 # 132 "myocamlbuild.ml"
133 module BaseEnvLight = struct
134 (* # 22 "src/base/BaseEnvLight.ml" *)
137 module MapString = Map.Make(String)
140 type t = string MapString.t
143 let default_filename =
144 Filename.concat
145 (Sys.getcwd ())
146 "setup.data"
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
155 let st =
156 Stream.of_channel chn
158 let line =
159 ref 1
161 let st_line =
162 Stream.from
163 (fun _ ->
165 match Stream.next st with
166 | '\n' -> incr line; Some '\n'
167 | c -> Some c
168 with Stream.Failure -> None)
170 let lexer =
171 Genlex.make_lexer ["="] st_line
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 | [] ->
182 | _ ->
183 failwith
184 (Printf.sprintf
185 "Malformed data file '%s' line %d"
186 filename !line)
188 let mp =
189 read_file MapString.empty
191 close_in chn;
194 else if allow_empty then
195 begin
196 MapString.empty
198 else
199 begin
200 failwith
201 (Printf.sprintf
202 "Unable to load environment, the file '%s' doesn't exist."
203 filename)
207 let rec var_expand str env =
208 let buff =
209 Buffer.create ((String.length str) * 2)
211 Buffer.add_substitute
212 buff
213 (fun var ->
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."
221 str))
222 str;
223 Buffer.contents buff
226 let var_get name env =
227 var_expand (MapString.find name env) env
230 let var_choose lst env =
231 OASISExpr.choose
232 (fun nm -> var_get nm env)
237 # 237 "myocamlbuild.ml"
238 module MyOCamlbuildFindlib = struct
239 (* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
242 (** OCamlbuild extension, copied from
243 * http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild
244 * by N. Pouillard and others
246 * Updated on 2009/02/28
248 * Modified by Sylvain Le Gall
250 open Ocamlbuild_plugin
253 (* these functions are not really officially exported *)
254 let run_and_read =
255 Ocamlbuild_pack.My_unix.run_and_read
258 let blank_sep_strings =
259 Ocamlbuild_pack.Lexers.blank_sep_strings
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
267 BaseEnvLight.var_get exec env
268 with Not_found ->
269 Printf.eprintf "W: Cannot get variable %s\n" exec;
270 exec
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 '\\'.
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
285 fix_win32 exec
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
294 String.iter
295 (fun c ->
296 if c = ch then
297 flush ()
298 else
299 Buffer.add_char buf c)
301 flush ();
302 List.rev !x
305 let split_nl s = split s '\n'
308 let before_space s =
310 String.before s (String.index s ' ')
311 with Not_found -> s
313 (* ocamlfind command *)
314 let ocamlfind x = S[Sh (exec_from_conf "ocamlfind"); x]
316 (* This lists all supported packages. *)
317 let find_packages () =
318 List.map before_space (split_nl & run_and_read "ocamlfind list")
321 (* Mock to list available syntaxes. *)
322 let find_syntaxes () = ["camlp4o"; "camlp4r"]
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"
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"
354 | After_rules ->
356 (* When one link an OCaml library/binary/package, one should use
357 * -linkpkg *)
358 flag ["ocaml"; "link"; "program"] & A"-linkpkg";
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.
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
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;
384 (find_packages ());
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 ());
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.
401 * To solve this, one approach is to add the "-thread" option when using
402 * the "threads" package using the previous plugin.
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"]);
413 | _ ->
417 module MyOCamlbuildBase = struct
418 (* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
421 (** Base functions for writing myocamlbuild.ml
422 @author Sylvain Le Gall
429 open Ocamlbuild_plugin
430 module OC = Ocamlbuild_pack.Ocaml_compiler
433 type dir = string
434 type file = string
435 type name = string
436 type tag = string
439 (* # 62 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
442 type t =
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.
450 includes: (dir * dir list) list;
454 let env_filename =
455 Pathname.basename
456 BaseEnvLight.default_filename
459 let dispatch_combine lst =
460 fun e ->
461 List.iter
462 (fun dispatch -> dispatch e)
466 let tag_libstubs nm =
467 "use_lib"^nm^"_stubs"
470 let nm_libstubs nm =
471 nm^"_stubs"
474 let dispatch t e =
475 let env =
476 BaseEnvLight.load
477 ~filename:env_filename
478 ~allow_empty:true
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
489 List.iter
490 (fun (opt, var) ->
492 opt := no_trailing_dot (BaseEnvLight.var_get var env)
493 with Not_found ->
494 Printf.eprintf "W: Cannot get variable %s\n" var)
496 Options.ext_obj, "ext_obj";
497 Options.ext_lib, "ext_lib";
498 Options.ext_dll, "ext_dll";
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"])
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;
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;
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))]);
541 flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
542 (S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
544 flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
545 (S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
547 (* When ocaml link something that use the C library, then one
548 need that file to be up to date.
550 dep ["link"; "ocaml"; "program"; tag_libstubs lib]
551 [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
553 dep ["compile"; "ocaml"; "program"; tag_libstubs lib]
554 [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
556 (* TODO: be more specific about what depends on headers *)
557 (* Depends on .h files *)
558 dep ["compile"; "c"]
559 headers;
561 (* Setup search path for lib *)
562 flag ["link"; "ocaml"; "use_"^lib]
563 (S[A"-I"; P(dir)]);
565 t.lib_c;
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
577 flag tags & (eval_specs spec))
578 t.flags
579 | _ ->
583 let dispatch_default t =
584 dispatch_combine
586 dispatch t;
587 MyOCamlbuildFindlib.dispatch;
594 # 594 "myocamlbuild.ml"
595 open Ocamlbuild_plugin;;
596 let package_default =
597 {MyOCamlbuildBase.lib_ocaml = []; lib_c = []; flags = []; includes = []}
600 let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;;
602 # 603 "myocamlbuild.ml"
603 (* OASIS_STOP *)
605 let () =
606 let bracket res destroy k = let x = (try k res with e -> destroy res; raise e) in destroy res; x in
607 let get_line r d = bracket r d input_line in
609 bracket (open_out "src/version.ml") close_out (fun out ->
611 let revision = get_line (Unix.open_process_in "git describe --always") (Unix.close_process_in) in
612 Printf.fprintf out "let id=%S\n" revision
613 with
614 _ -> Printf.fprintf out "let id = Version_release.id\n"
618 let dispatch = function
619 | After_rules as t ->
620 flag ["compile"; "ocaml"; "warn_no_44"] (S[A"-w";A"-44"]);
621 flag ["ocaml"; "link"; "toplevel"] (A"-linkpkg");
622 dispatch_default t
623 | t -> dispatch_default t
626 Ocamlbuild_plugin.dispatch dispatch;;