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;; |