2 (* DO NOT EDIT (digest: a9256c48d09d8920f4249d0b08175f1b) *)
3 module OASISGettext
= struct
4 (* # 22 "src/oasis/OASISGettext.ml" *)
9 let f_ (str
: ('a
, 'b
, 'c
, 'd
) format4
) = str
22 module OASISString
= struct
23 (* # 22 "src/oasis/OASISString.ml" *)
26 (** Various string utilities.
28 Mostly inspired by extlib and batteries ExtString and BatString libraries.
30 @author Sylvain Le Gall
38 let buf = Buffer.create
13 in
41 lst := Buffer.contents
buf :: !lst;
44 let str_len = String.length str
in
45 for i
= 0 to str_len - 1 do
49 Buffer.add_char
buf str
.[i
]
55 (** [nsplit c s] Split the string [s] at char [c]. It doesn't include the
62 let find ~what ?
(offset
=0) str
=
63 let what_idx = ref 0 in
64 let str_idx = ref offset
in
65 while !str_idx < String.length str
&&
66 !what_idx < String.length what
do
67 if str
.[!str_idx] = what
.[!what_idx] then
73 if !what_idx <> String.length what
then
79 let sub_start str len
=
80 let str_len = String.length str
in
81 if len
>= str_len then
84 String.sub str len
(str_len - len
)
87 let sub_end ?
(offset
=0) str len
=
88 let str_len = String.length str
in
89 if len
>= str_len then
92 String.sub str
0 (str_len - len
)
95 let starts_with ~what ?
(offset
=0) str
=
96 let what_idx = ref 0 in
97 let str_idx = ref offset
in
100 !str_idx < String.length str
&&
101 !what_idx < String.length what
do
102 if str
.[!str_idx] = what
.[!what_idx] then
108 !what_idx = String.length what
111 let strip_starts_with ~what str
=
112 if starts_with ~what str
then
113 sub_start str
(String.length what
)
118 let ends_with ~what ?
(offset
=0) str
=
119 let what_idx = ref ((String.length what
) - 1) in
120 let str_idx = ref ((String.length str
) - 1) in
123 offset
<= !str_idx &&
125 if str
.[!str_idx] = what
.[!what_idx] then
134 let strip_ends_with ~what str
=
135 if ends_with ~what str
then
136 sub_end str
(String.length what
)
141 let replace_chars f s
=
142 let buf = Buffer.create
(String.length s
) in
143 String.iter
(fun c
-> Buffer.add_char
buf (f c
)) s
;
146 let lowercase_ascii =
149 if (c
>= 'A'
&& c
<= 'Z'
) then
150 Char.chr
(Char.code c
+ 32)
154 let uncapitalize_ascii s
=
156 (lowercase_ascii (String.sub s
0 1)) ^
(String.sub s
1 ((String.length s
) - 1))
160 let uppercase_ascii =
163 if (c
>= 'a'
&& c
<= 'z'
) then
164 Char.chr
(Char.code c
- 32)
168 let capitalize_ascii s
=
170 (uppercase_ascii (String.sub s
0 1)) ^
(String.sub s
1 ((String.length s
) - 1))
176 module OASISUtils
= struct
177 (* # 22 "src/oasis/OASISUtils.ml" *)
188 val add_list
: 'a t
-> (key
* 'a
) list
-> 'a t
189 val of_list
: (key
* 'a
) list
-> 'a t
190 val to_list
: 'a t
-> (key
* 'a
) list
193 module Make
(Ord
: Map.OrderedType
) =
195 include Map.Make
(Ord
)
199 | (k
, v
) :: tl
-> add_list (add k v t
) tl
202 let of_list lst = add_list empty
lst
204 let to_list t
= fold
(fun k v acc
-> (k
, v
) :: acc
) t
[]
209 module MapString
= MapExt.Make
(String
)
217 val add_list: t
-> elt list
-> t
218 val of_list: elt list
-> t
219 val to_list: t
-> elt list
222 module Make
(Ord
: Set.OrderedType
) =
224 include Set.Make
(Ord
)
228 | e
:: tl
-> add_list (add e t
) tl
231 let of_list lst = add_list empty
lst
233 let to_list = elements
238 module SetString
= SetExt.Make
(String
)
241 let compare_csl s1 s2
=
242 String.compare
(OASISString.lowercase_ascii s1
) (OASISString.lowercase_ascii s2
)
245 module HashStringCsl
=
249 let equal s1 s2
= (compare_csl s1 s2
) = 0
250 let hash s
= Hashtbl.hash (OASISString.lowercase_ascii s
)
253 module SetStringCsl
=
257 let compare = compare_csl
261 let varname_of_string ?
(hyphen
='_'
) s
=
262 if String.length s
= 0 then
264 invalid_arg
"varname_of_string"
269 OASISString.replace_chars
271 if ('a'
<= c
&& c
<= 'z'
)
273 ('A'
<= c
&& c
<= 'Z'
)
275 ('
0'
<= c
&& c
<= '
9'
) then
282 (* Start with a _ if digit *)
283 if '
0'
<= s
.[0] && s
.[0] <= '
9'
then
288 OASISString.lowercase_ascii buf
292 let varname_concat ?
(hyphen
='_'
) p s
=
293 let what = String.make
1 hyphen
in
296 OASISString.strip_ends_with ~
what p
302 OASISString.strip_starts_with ~
what s
310 str
= varname_of_string str
313 let failwithf fmt
= Printf.ksprintf failwith fmt
316 let rec file_location ?pos1 ?pos2 ?lexbuf
() =
317 match pos1
, pos2
, lexbuf
with
318 | Some
p, None
, _
| None
, Some
p, _
->
319 file_location ~pos1
:p ~pos2
:p ?lexbuf
()
320 | Some p1
, Some p2
, _
->
322 let fn, lineno
= p1
.pos_fname
, p1
.pos_lnum
in
323 let c1 = p1
.pos_cnum
- p1
.pos_bol
in
324 let c2 = c1 + (p2
.pos_cnum
- p1
.pos_cnum
) in
325 Printf.sprintf
(f_ "file %S, line %d, characters %d-%d") fn lineno
c1 c2
326 | _
, _
, Some lexbuf
->
328 ~pos1
:(Lexing.lexeme_start_p lexbuf
)
329 ~pos2
:(Lexing.lexeme_end_p lexbuf
)
331 | None
, None
, None
->
332 s_ "<position undefined>"
335 let failwithpf ?pos1 ?pos2 ?lexbuf fmt
=
336 let loc = file_location ?pos1 ?pos2 ?lexbuf
() in
337 Printf.ksprintf
(fun s -> failwith
(Printf.sprintf
"%s: %s" loc s)) fmt
342 module OASISExpr
= struct
343 (* # 22 "src/oasis/OASISExpr.ml" *)
360 | ETest
of test
* string
363 type 'a choices
= (t
* 'a
) list
376 (eval' e1
) && (eval' e2
)
379 (eval' e1
) || (eval' e2
)
385 assert(v = "true" || v = "false");
397 let choose ?printer ?name var_get
lst =
400 | (cond
, vl
) :: tl
->
401 if eval var_get cond
then
416 | None
-> s_ "<no printer>")
423 (f_ "No result for the choice list '%s': %s")
428 (f_ "No result for a choice list: %s")
431 choose_aux (List.rev
lst)
437 #
437 "myocamlbuild.ml"
438 module BaseEnvLight
= struct
439 (* # 22 "src/base/BaseEnvLight.ml" *)
442 module MapString
= Map.Make
(String
)
445 type t
= string MapString.t
448 let default_filename = Filename.concat
(Sys.getcwd
()) "setup.data"
451 let load ?
(allow_empty
=false) ?
(filename
=default_filename) ?stream
() =
458 match Stream.next st
with
459 | '
\n'
-> incr
line; Some '
\n'
461 with Stream.Failure
-> None
)
463 Genlex.make_lexer
["="] st_line
465 let rec read_file lxr mp
=
466 match Stream.npeek
3 lxr
with
467 | [Genlex.Ident nm
; Genlex.Kwd
"="; Genlex.String
value] ->
468 Stream.junk lxr
; Stream.junk lxr
; Stream.junk lxr
;
469 read_file lxr
(MapString.add nm
value mp
)
473 (Printf.sprintf
"Malformed data file '%s' line %d" filename
!line)
476 | Some st
-> read_file (lexer st
) MapString.empty
478 if Sys.file_exists filename
then begin
479 let chn = open_in_bin filename
in
480 let st = Stream.of_channel
chn in
482 let mp = read_file (lexer st) MapString.empty
in
485 close_in
chn; raise e
486 end else if allow_empty
then begin
491 "Unable to load environment, the file '%s' doesn't exist."
495 let rec var_expand str env
=
496 let buff = Buffer.create
((String.length str
) * 2) in
497 Buffer.add_substitute
501 var_expand (MapString.find var env
) env
505 "No variable %s defined when trying to expand %S."
512 let var_get name env
= var_expand (MapString.find name env
) env
513 let var_choose lst env
= OASISExpr.choose (fun nm
-> var_get nm env
) lst
517 #
517 "myocamlbuild.ml"
518 module MyOCamlbuildFindlib
= struct
519 (* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
522 (** OCamlbuild extension, copied from
523 * https://ocaml.org/learn/tutorials/ocamlbuild/Using_ocamlfind_with_ocamlbuild.html
524 * by N. Pouillard and others
526 * Updated on 2016-06-02
528 * Modified by Sylvain Le Gall
530 open Ocamlbuild_plugin
533 type conf
= {no_automatic_syntax
: bool}
536 let run_and_read = Ocamlbuild_pack.My_unix.run_and_read
539 let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings
542 let exec_from_conf exec
=
544 let env = BaseEnvLight.load ~allow_empty
:true () in
546 BaseEnvLight.var_get exec env
548 Printf.eprintf
"W: Cannot get variable %s\n" exec;
552 if Sys.os_type
= "Win32" then begin
553 let buff = Buffer.create
(String.length str
) in
554 (* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'.
557 (fun c
-> Buffer.add_char
buff (if c
= '
\\'
then '
/'
else c
))
568 let buf = Buffer.create
13 in
571 x := (Buffer.contents
buf) :: !x;
579 Buffer.add_char
buf c
)
585 let split_nl s = split s '
\n'
590 String.before
s (String.index
s ' '
)
593 (* ocamlfind command *)
594 let ocamlfind x = S
[Sh
(exec_from_conf "ocamlfind"); x]
596 (* This lists all supported packages. *)
597 let find_packages () =
598 List.map
before_space (split_nl & run_and_read (exec_from_conf "ocamlfind" ^
" list"))
601 (* Mock to list available syntaxes. *)
602 let find_syntaxes () = ["camlp4o"; "camlp4r"]
605 let well_known_syntax = [
606 "camlp4.quotations.o";
607 "camlp4.quotations.r";
608 "camlp4.exceptiontracer";
610 "camlp4.foldgenerator";
611 "camlp4.listcomprehension";
612 "camlp4.locationstripper";
614 "camlp4.mapgenerator";
615 "camlp4.metagenerator";
624 (* By using Before_options one let command line options have an higher
625 * priority on the contrary using After_options will guarantee to have
626 * the higher priority override default commands by ocamlfind ones *)
627 Options.ocamlc
:= ocamlfind & A
"ocamlc";
628 Options.ocamlopt
:= ocamlfind & A
"ocamlopt";
629 Options.ocamldep
:= ocamlfind & A
"ocamldep";
630 Options.ocamldoc
:= ocamlfind & A
"ocamldoc";
631 Options.ocamlmktop
:= ocamlfind & A
"ocamlmktop";
632 Options.ocamlmklib
:= ocamlfind & A
"ocamlmklib"
636 (* Avoid warnings for unused tag *)
639 (* When one link an OCaml library/binary/package, one should use
641 flag
["ocaml"; "link"; "program"] & A
"-linkpkg";
643 (* For each ocamlfind package one inject the -package option when
644 * compiling, computing dependencies, generating documentation and
648 let base_args = [A
"-package"; A pkg
] in
649 (* TODO: consider how to really choose camlp4o or camlp4r. *)
650 let syn_args = [A
"-syntax"; A
"camlp4o"] in
652 (* Heuristic to identify syntax extensions: whether they end in
653 ".syntax"; some might not.
655 if not
(conf
.no_automatic_syntax
) &&
656 (Filename.check_suffix pkg
"syntax" ||
657 List.mem pkg
well_known_syntax) then
658 (syn_args @ base_args, syn_args)
662 flag
["ocaml"; "compile"; "pkg_"^pkg
] & S args
;
663 flag
["ocaml"; "ocamldep"; "pkg_"^pkg
] & S args
;
664 flag
["ocaml"; "doc"; "pkg_"^pkg
] & S args
;
665 flag
["ocaml"; "link"; "pkg_"^pkg
] & S
base_args;
666 flag
["ocaml"; "infer_interface"; "pkg_"^pkg
] & S args
;
668 (* TODO: Check if this is allowed for OCaml < 3.12.1 *)
669 flag
["ocaml"; "compile"; "package("^pkg^
")"] & S pargs
;
670 flag
["ocaml"; "ocamldep"; "package("^pkg^
")"] & S pargs
;
671 flag
["ocaml"; "doc"; "package("^pkg^
")"] & S pargs
;
672 flag
["ocaml"; "infer_interface"; "package("^pkg^
")"] & S pargs
;
676 (* Like -package but for extensions syntax. Morover -syntax is useless
678 List.iter
begin fun syntax
->
679 flag
["ocaml"; "compile"; "syntax_"^syntax
] & S
[A
"-syntax"; A syntax
];
680 flag
["ocaml"; "ocamldep"; "syntax_"^syntax
] & S
[A
"-syntax"; A syntax
];
681 flag
["ocaml"; "doc"; "syntax_"^syntax
] & S
[A
"-syntax"; A syntax
];
682 flag
["ocaml"; "infer_interface"; "syntax_"^syntax
] &
683 S
[A
"-syntax"; A syntax
];
684 end (find_syntaxes ());
686 (* The default "thread" tag is not compatible with ocamlfind.
687 * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
688 * options when using this tag. When using the "-linkpkg" option with
689 * ocamlfind, this module will then be added twice on the command line.
691 * To solve this, one approach is to add the "-thread" option when using
692 * the "threads" package using the previous plugin.
694 flag
["ocaml"; "pkg_threads"; "compile"] (S
[A
"-thread"]);
695 flag
["ocaml"; "pkg_threads"; "doc"] (S
[A
"-I"; A
"+threads"]);
696 flag
["ocaml"; "pkg_threads"; "link"] (S
[A
"-thread"]);
697 flag
["ocaml"; "pkg_threads"; "infer_interface"] (S
[A
"-thread"]);
698 flag
["c"; "pkg_threads"; "compile"] (S
[A
"-thread"]);
699 flag
["ocaml"; "package(threads)"; "compile"] (S
[A
"-thread"]);
700 flag
["ocaml"; "package(threads)"; "doc"] (S
[A
"-I"; A
"+threads"]);
701 flag
["ocaml"; "package(threads)"; "link"] (S
[A
"-thread"]);
702 flag
["ocaml"; "package(threads)"; "infer_interface"] (S
[A
"-thread"]);
703 flag
["c"; "package(threads)"; "compile"] (S
[A
"-thread"]);
709 module MyOCamlbuildBase
= struct
710 (* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
713 (** Base functions for writing myocamlbuild.ml
714 @author Sylvain Le Gall
718 open Ocamlbuild_plugin
719 module OC
= Ocamlbuild_pack.Ocaml_compiler
730 lib_ocaml
: (name
* dir list
* string list
) list
;
731 lib_c
: (name
* dir
* file list
) list
;
732 flags
: (tag list
* (spec
OASISExpr.choices
)) list
;
733 (* Replace the 'dir: include' from _tags by a precise interdepends in
736 includes
: (dir
* dir list
) list
;
740 (* # 110 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
743 let env_filename = Pathname.basename
BaseEnvLight.default_filename
746 let dispatch_combine lst =
749 (fun dispatch -> dispatch e
)
753 let tag_libstubs nm
=
754 "use_lib"^nm^
"_stubs"
762 let env = BaseEnvLight.load ~allow_empty
:true () in
765 let no_trailing_dot s =
766 if String.length
s >= 1 && s.[0] = '
.'
then
767 String.sub
s 1 ((String.length
s) - 1)
774 opt
:= no_trailing_dot (BaseEnvLight.var_get var
env)
776 Printf.eprintf
"W: Cannot get variable %s\n" var
)
778 Options.ext_obj
, "ext_obj";
779 Options.ext_lib
, "ext_lib";
780 Options.ext_dll
, "ext_dll";
784 (* Declare OCaml libraries *)
787 | nm
, [], intf_modules
->
790 List.map
(fun m
-> (OASISString.uncapitalize_ascii m
) ^
".cmi")
792 dep
["ocaml"; "link"; "library"; "file:"^nm^
".cma"] cmis
793 | nm
, dir
:: tl
, intf_modules
->
794 ocaml_lib ~dir
:dir
(dir^
"/"^nm
);
799 flag
["ocaml"; "use_"^nm
; str
] (S
[A
"-I"; P dir
]))
800 ["compile"; "infer_interface"; "doc"])
803 List.map
(fun m
-> dir^
"/"^
(OASISString.uncapitalize_ascii m
)^
".cmi")
805 dep
["ocaml"; "link"; "library"; "file:"^dir^
"/"^nm^
".cma"]
809 (* Declare directories dependencies, replace "include" in _tags. *)
811 (fun (dir
, include_dirs
) ->
812 Pathname.define_context dir include_dirs
)
815 (* Declare C libraries *)
817 (fun (lib
, dir
, headers
) ->
818 (* Handle C part of library *)
819 flag
["link"; "library"; "ocaml"; "byte"; tag_libstubs lib
]
820 (S
[A
"-dllib"; A
("-l"^
(nm_libstubs lib
)); A
"-cclib";
821 A
("-l"^
(nm_libstubs lib
))]);
823 flag
["link"; "library"; "ocaml"; "native"; tag_libstubs lib
]
824 (S
[A
"-cclib"; A
("-l"^
(nm_libstubs lib
))]);
826 if bool_of_string
(BaseEnvLight.var_get "native_dynlink" env) then
827 flag
["link"; "program"; "ocaml"; "byte"; tag_libstubs lib
]
828 (S
[A
"-dllib"; A
("dll"^
(nm_libstubs lib
))]);
830 (* When ocaml link something that use the C library, then one
831 need that file to be up to date.
832 This holds both for programs and for libraries.
834 dep
["link"; "ocaml"; tag_libstubs lib
]
835 [dir
/"lib"^
(nm_libstubs lib
)^
"."^
(!Options.ext_lib
)];
837 dep
["compile"; "ocaml"; tag_libstubs lib
]
838 [dir
/"lib"^
(nm_libstubs lib
)^
"."^
(!Options.ext_lib
)];
840 (* TODO: be more specific about what depends on headers *)
841 (* Depends on .h files *)
845 (* Setup search path for lib *)
846 flag
["link"; "ocaml"; "use_"^lib
]
853 (fun (tags
, cond_specs
) ->
854 let spec = BaseEnvLight.var_choose cond_specs
env in
857 | S
lst -> S
(List.map
eval_specs lst)
858 | A str
-> A
(BaseEnvLight.var_expand str
env)
861 flag tags
& (eval_specs spec))
867 let dispatch_default conf t
=
871 MyOCamlbuildFindlib.dispatch conf
;
878 #
878 "myocamlbuild.ml"
879 open Ocamlbuild_plugin
;;
880 let package_default =
882 MyOCamlbuildBase.lib_ocaml
=
884 ("sqlgg", ["lib"], []);
885 ("sqlgg_traits", ["impl/ocaml"], []);
886 ("sqlgg_mariadb", ["impl/ocaml/mariadb"], []);
887 ("sqlgg_mysql", ["impl/ocaml/mysql"], []);
888 ("sqlgg_sqlite3", ["impl/ocaml/sqlite3"], [])
895 ("impl/ocaml/sqlite3", ["impl/ocaml"]);
896 ("impl/ocaml/mysql", ["impl/ocaml"]);
897 ("impl/ocaml/mariadb", ["impl/ocaml"])
902 let conf = {MyOCamlbuildFindlib.no_automatic_syntax
= false}
904 let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;;
906 #
907 "myocamlbuild.ml"
908 Ocamlbuild_plugin.dispatch dispatch_default;;