myocamlbuild.ml 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. (* OASIS_START *)
  2. (* DO NOT EDIT (digest: ef1a54452f0cead733c1a9a890b617ad) *)
  3. module OASISGettext = struct
  4. (* # 22 "src/oasis/OASISGettext.ml" *)
  5. let ns_ str = str
  6. let s_ str = str
  7. let f_ (str: ('a, 'b, 'c, 'd) format4) = str
  8. let fn_ fmt1 fmt2 n =
  9. if n = 1 then
  10. fmt1^^""
  11. else
  12. fmt2^^""
  13. let init = []
  14. end
  15. module OASISString = struct
  16. (* # 22 "src/oasis/OASISString.ml" *)
  17. (** Various string utilities.
  18. Mostly inspired by extlib and batteries ExtString and BatString libraries.
  19. @author Sylvain Le Gall
  20. *)
  21. let nsplitf str f =
  22. if str = "" then
  23. []
  24. else
  25. let buf = Buffer.create 13 in
  26. let lst = ref [] in
  27. let push () =
  28. lst := Buffer.contents buf :: !lst;
  29. Buffer.clear buf
  30. in
  31. let str_len = String.length str in
  32. for i = 0 to str_len - 1 do
  33. if f str.[i] then
  34. push ()
  35. else
  36. Buffer.add_char buf str.[i]
  37. done;
  38. push ();
  39. List.rev !lst
  40. (** [nsplit c s] Split the string [s] at char [c]. It doesn't include the
  41. separator.
  42. *)
  43. let nsplit str c =
  44. nsplitf str ((=) c)
  45. let find ~what ?(offset=0) str =
  46. let what_idx = ref 0 in
  47. let str_idx = ref offset in
  48. while !str_idx < String.length str &&
  49. !what_idx < String.length what do
  50. if str.[!str_idx] = what.[!what_idx] then
  51. incr what_idx
  52. else
  53. what_idx := 0;
  54. incr str_idx
  55. done;
  56. if !what_idx <> String.length what then
  57. raise Not_found
  58. else
  59. !str_idx - !what_idx
  60. let sub_start str len =
  61. let str_len = String.length str in
  62. if len >= str_len then
  63. ""
  64. else
  65. String.sub str len (str_len - len)
  66. let sub_end ?(offset=0) str len =
  67. let str_len = String.length str in
  68. if len >= str_len then
  69. ""
  70. else
  71. String.sub str 0 (str_len - len)
  72. let starts_with ~what ?(offset=0) str =
  73. let what_idx = ref 0 in
  74. let str_idx = ref offset in
  75. let ok = ref true in
  76. while !ok &&
  77. !str_idx < String.length str &&
  78. !what_idx < String.length what do
  79. if str.[!str_idx] = what.[!what_idx] then
  80. incr what_idx
  81. else
  82. ok := false;
  83. incr str_idx
  84. done;
  85. if !what_idx = String.length what then
  86. true
  87. else
  88. false
  89. let strip_starts_with ~what str =
  90. if starts_with ~what str then
  91. sub_start str (String.length what)
  92. else
  93. raise Not_found
  94. let ends_with ~what ?(offset=0) str =
  95. let what_idx = ref ((String.length what) - 1) in
  96. let str_idx = ref ((String.length str) - 1) in
  97. let ok = ref true in
  98. while !ok &&
  99. offset <= !str_idx &&
  100. 0 <= !what_idx do
  101. if str.[!str_idx] = what.[!what_idx] then
  102. decr what_idx
  103. else
  104. ok := false;
  105. decr str_idx
  106. done;
  107. if !what_idx = -1 then
  108. true
  109. else
  110. false
  111. let strip_ends_with ~what str =
  112. if ends_with ~what str then
  113. sub_end str (String.length what)
  114. else
  115. raise Not_found
  116. let replace_chars f s =
  117. let buf = Buffer.create (String.length s) in
  118. String.iter (fun c -> Buffer.add_char buf (f c)) s;
  119. Buffer.contents buf
  120. let lowercase_ascii =
  121. replace_chars
  122. (fun c ->
  123. if (c >= 'A' && c <= 'Z') then
  124. Char.chr (Char.code c + 32)
  125. else
  126. c)
  127. let uncapitalize_ascii s =
  128. if s <> "" then
  129. (lowercase_ascii (String.sub s 0 1)) ^ (String.sub s 1 ((String.length s) - 1))
  130. else
  131. s
  132. let uppercase_ascii =
  133. replace_chars
  134. (fun c ->
  135. if (c >= 'a' && c <= 'z') then
  136. Char.chr (Char.code c - 32)
  137. else
  138. c)
  139. let capitalize_ascii s =
  140. if s <> "" then
  141. (uppercase_ascii (String.sub s 0 1)) ^ (String.sub s 1 ((String.length s) - 1))
  142. else
  143. s
  144. end
  145. module OASISUtils = struct
  146. (* # 22 "src/oasis/OASISUtils.ml" *)
  147. open OASISGettext
  148. module MapExt =
  149. struct
  150. module type S =
  151. sig
  152. include Map.S
  153. val add_list: 'a t -> (key * 'a) list -> 'a t
  154. val of_list: (key * 'a) list -> 'a t
  155. val to_list: 'a t -> (key * 'a) list
  156. end
  157. module Make (Ord: Map.OrderedType) =
  158. struct
  159. include Map.Make(Ord)
  160. let rec add_list t =
  161. function
  162. | (k, v) :: tl -> add_list (add k v t) tl
  163. | [] -> t
  164. let of_list lst = add_list empty lst
  165. let to_list t = fold (fun k v acc -> (k, v) :: acc) t []
  166. end
  167. end
  168. module MapString = MapExt.Make(String)
  169. module SetExt =
  170. struct
  171. module type S =
  172. sig
  173. include Set.S
  174. val add_list: t -> elt list -> t
  175. val of_list: elt list -> t
  176. val to_list: t -> elt list
  177. end
  178. module Make (Ord: Set.OrderedType) =
  179. struct
  180. include Set.Make(Ord)
  181. let rec add_list t =
  182. function
  183. | e :: tl -> add_list (add e t) tl
  184. | [] -> t
  185. let of_list lst = add_list empty lst
  186. let to_list = elements
  187. end
  188. end
  189. module SetString = SetExt.Make(String)
  190. let compare_csl s1 s2 =
  191. String.compare (OASISString.lowercase_ascii s1) (OASISString.lowercase_ascii s2)
  192. module HashStringCsl =
  193. Hashtbl.Make
  194. (struct
  195. type t = string
  196. let equal s1 s2 = (compare_csl s1 s2) = 0
  197. let hash s = Hashtbl.hash (OASISString.lowercase_ascii s)
  198. end)
  199. module SetStringCsl =
  200. SetExt.Make
  201. (struct
  202. type t = string
  203. let compare = compare_csl
  204. end)
  205. let varname_of_string ?(hyphen='_') s =
  206. if String.length s = 0 then
  207. begin
  208. invalid_arg "varname_of_string"
  209. end
  210. else
  211. begin
  212. let buf =
  213. OASISString.replace_chars
  214. (fun c ->
  215. if ('a' <= c && c <= 'z')
  216. ||
  217. ('A' <= c && c <= 'Z')
  218. ||
  219. ('0' <= c && c <= '9') then
  220. c
  221. else
  222. hyphen)
  223. s;
  224. in
  225. let buf =
  226. (* Start with a _ if digit *)
  227. if '0' <= s.[0] && s.[0] <= '9' then
  228. "_"^buf
  229. else
  230. buf
  231. in
  232. OASISString.lowercase_ascii buf
  233. end
  234. let varname_concat ?(hyphen='_') p s =
  235. let what = String.make 1 hyphen in
  236. let p =
  237. try
  238. OASISString.strip_ends_with ~what p
  239. with Not_found ->
  240. p
  241. in
  242. let s =
  243. try
  244. OASISString.strip_starts_with ~what s
  245. with Not_found ->
  246. s
  247. in
  248. p^what^s
  249. let is_varname str =
  250. str = varname_of_string str
  251. let failwithf fmt = Printf.ksprintf failwith fmt
  252. let rec file_location ?pos1 ?pos2 ?lexbuf () =
  253. match pos1, pos2, lexbuf with
  254. | Some p, None, _ | None, Some p, _ ->
  255. file_location ~pos1:p ~pos2:p ?lexbuf ()
  256. | Some p1, Some p2, _ ->
  257. let open Lexing in
  258. let fn, lineno = p1.pos_fname, p1.pos_lnum in
  259. let c1 = p1.pos_cnum - p1.pos_bol in
  260. let c2 = c1 + (p2.pos_cnum - p1.pos_cnum) in
  261. Printf.sprintf (f_ "file %S, line %d, characters %d-%d") fn lineno c1 c2
  262. | _, _, Some lexbuf ->
  263. file_location
  264. ~pos1:(Lexing.lexeme_start_p lexbuf)
  265. ~pos2:(Lexing.lexeme_end_p lexbuf)
  266. ()
  267. | None, None, None ->
  268. s_ "<position undefined>"
  269. let failwithpf ?pos1 ?pos2 ?lexbuf fmt =
  270. let loc = file_location ?pos1 ?pos2 ?lexbuf () in
  271. Printf.ksprintf (fun s -> failwith (Printf.sprintf "%s: %s" loc s)) fmt
  272. end
  273. module OASISExpr = struct
  274. (* # 22 "src/oasis/OASISExpr.ml" *)
  275. open OASISGettext
  276. open OASISUtils
  277. type test = string
  278. type flag = string
  279. type t =
  280. | EBool of bool
  281. | ENot of t
  282. | EAnd of t * t
  283. | EOr of t * t
  284. | EFlag of flag
  285. | ETest of test * string
  286. type 'a choices = (t * 'a) list
  287. let eval var_get t =
  288. let rec eval' =
  289. function
  290. | EBool b ->
  291. b
  292. | ENot e ->
  293. not (eval' e)
  294. | EAnd (e1, e2) ->
  295. (eval' e1) && (eval' e2)
  296. | EOr (e1, e2) ->
  297. (eval' e1) || (eval' e2)
  298. | EFlag nm ->
  299. let v =
  300. var_get nm
  301. in
  302. assert(v = "true" || v = "false");
  303. (v = "true")
  304. | ETest (nm, vl) ->
  305. let v =
  306. var_get nm
  307. in
  308. (v = vl)
  309. in
  310. eval' t
  311. let choose ?printer ?name var_get lst =
  312. let rec choose_aux =
  313. function
  314. | (cond, vl) :: tl ->
  315. if eval var_get cond then
  316. vl
  317. else
  318. choose_aux tl
  319. | [] ->
  320. let str_lst =
  321. if lst = [] then
  322. s_ "<empty>"
  323. else
  324. String.concat
  325. (s_ ", ")
  326. (List.map
  327. (fun (cond, vl) ->
  328. match printer with
  329. | Some p -> p vl
  330. | None -> s_ "<no printer>")
  331. lst)
  332. in
  333. match name with
  334. | Some nm ->
  335. failwith
  336. (Printf.sprintf
  337. (f_ "No result for the choice list '%s': %s")
  338. nm str_lst)
  339. | None ->
  340. failwith
  341. (Printf.sprintf
  342. (f_ "No result for a choice list: %s")
  343. str_lst)
  344. in
  345. choose_aux (List.rev lst)
  346. end
  347. # 443 "myocamlbuild.ml"
  348. module BaseEnvLight = struct
  349. (* # 22 "src/base/BaseEnvLight.ml" *)
  350. module MapString = Map.Make(String)
  351. type t = string MapString.t
  352. let default_filename = Filename.concat (Sys.getcwd ()) "setup.data"
  353. let load ?(allow_empty=false) ?(filename=default_filename) ?stream () =
  354. let line = ref 1 in
  355. let lexer st =
  356. let st_line =
  357. Stream.from
  358. (fun _ ->
  359. try
  360. match Stream.next st with
  361. | '\n' -> incr line; Some '\n'
  362. | c -> Some c
  363. with Stream.Failure -> None)
  364. in
  365. Genlex.make_lexer ["="] st_line
  366. in
  367. let rec read_file lxr mp =
  368. match Stream.npeek 3 lxr with
  369. | [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] ->
  370. Stream.junk lxr; Stream.junk lxr; Stream.junk lxr;
  371. read_file lxr (MapString.add nm value mp)
  372. | [] -> mp
  373. | _ ->
  374. failwith
  375. (Printf.sprintf "Malformed data file '%s' line %d" filename !line)
  376. in
  377. match stream with
  378. | Some st -> read_file (lexer st) MapString.empty
  379. | None ->
  380. if Sys.file_exists filename then begin
  381. let chn = open_in_bin filename in
  382. let st = Stream.of_channel chn in
  383. try
  384. let mp = read_file (lexer st) MapString.empty in
  385. close_in chn; mp
  386. with e ->
  387. close_in chn; raise e
  388. end else if allow_empty then begin
  389. MapString.empty
  390. end else begin
  391. failwith
  392. (Printf.sprintf
  393. "Unable to load environment, the file '%s' doesn't exist."
  394. filename)
  395. end
  396. let rec var_expand str env =
  397. let buff = Buffer.create ((String.length str) * 2) in
  398. Buffer.add_substitute
  399. buff
  400. (fun var ->
  401. try
  402. var_expand (MapString.find var env) env
  403. with Not_found ->
  404. failwith
  405. (Printf.sprintf
  406. "No variable %s defined when trying to expand %S."
  407. var
  408. str))
  409. str;
  410. Buffer.contents buff
  411. let var_get name env = var_expand (MapString.find name env) env
  412. let var_choose lst env = OASISExpr.choose (fun nm -> var_get nm env) lst
  413. end
  414. # 523 "myocamlbuild.ml"
  415. module MyOCamlbuildFindlib = struct
  416. (* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
  417. (** OCamlbuild extension, copied from
  418. * https://ocaml.org/learn/tutorials/ocamlbuild/Using_ocamlfind_with_ocamlbuild.html
  419. * by N. Pouillard and others
  420. *
  421. * Updated on 2016-06-02
  422. *
  423. * Modified by Sylvain Le Gall
  424. *)
  425. open Ocamlbuild_plugin
  426. type conf = {no_automatic_syntax: bool}
  427. let run_and_read = Ocamlbuild_pack.My_unix.run_and_read
  428. let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings
  429. let exec_from_conf exec =
  430. let exec =
  431. let env = BaseEnvLight.load ~allow_empty:true () in
  432. try
  433. BaseEnvLight.var_get exec env
  434. with Not_found ->
  435. Printf.eprintf "W: Cannot get variable %s\n" exec;
  436. exec
  437. in
  438. let fix_win32 str =
  439. if Sys.os_type = "Win32" then begin
  440. let buff = Buffer.create (String.length str) in
  441. (* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'.
  442. *)
  443. String.iter
  444. (fun c -> Buffer.add_char buff (if c = '\\' then '/' else c))
  445. str;
  446. Buffer.contents buff
  447. end else begin
  448. str
  449. end
  450. in
  451. fix_win32 exec
  452. let split s ch =
  453. let buf = Buffer.create 13 in
  454. let x = ref [] in
  455. let flush () =
  456. x := (Buffer.contents buf) :: !x;
  457. Buffer.clear buf
  458. in
  459. String.iter
  460. (fun c ->
  461. if c = ch then
  462. flush ()
  463. else
  464. Buffer.add_char buf c)
  465. s;
  466. flush ();
  467. List.rev !x
  468. let split_nl s = split s '\n'
  469. let before_space s =
  470. try
  471. String.before s (String.index s ' ')
  472. with Not_found -> s
  473. (* ocamlfind command *)
  474. let ocamlfind x = S[Sh (exec_from_conf "ocamlfind"); x]
  475. (* This lists all supported packages. *)
  476. let find_packages () =
  477. List.map before_space (split_nl & run_and_read (exec_from_conf "ocamlfind" ^ " list"))
  478. (* Mock to list available syntaxes. *)
  479. let find_syntaxes () = ["camlp4o"; "camlp4r"]
  480. let well_known_syntax = [
  481. "camlp4.quotations.o";
  482. "camlp4.quotations.r";
  483. "camlp4.exceptiontracer";
  484. "camlp4.extend";
  485. "camlp4.foldgenerator";
  486. "camlp4.listcomprehension";
  487. "camlp4.locationstripper";
  488. "camlp4.macro";
  489. "camlp4.mapgenerator";
  490. "camlp4.metagenerator";
  491. "camlp4.profiler";
  492. "camlp4.tracer"
  493. ]
  494. let dispatch conf =
  495. function
  496. | After_options ->
  497. (* By using Before_options one let command line options have an higher
  498. * priority on the contrary using After_options will guarantee to have
  499. * the higher priority override default commands by ocamlfind ones *)
  500. Options.ocamlc := ocamlfind & A"ocamlc";
  501. Options.ocamlopt := ocamlfind & A"ocamlopt";
  502. Options.ocamldep := ocamlfind & A"ocamldep";
  503. Options.ocamldoc := ocamlfind & A"ocamldoc";
  504. Options.ocamlmktop := ocamlfind & A"ocamlmktop";
  505. Options.ocamlmklib := ocamlfind & A"ocamlmklib"
  506. | After_rules ->
  507. (* Avoid warnings for unused tag *)
  508. flag ["tests"] N;
  509. (* When one link an OCaml library/binary/package, one should use
  510. * -linkpkg *)
  511. flag ["ocaml"; "link"; "program"] & A"-linkpkg";
  512. (* For each ocamlfind package one inject the -package option when
  513. * compiling, computing dependencies, generating documentation and
  514. * linking. *)
  515. List.iter
  516. begin fun pkg ->
  517. let base_args = [A"-package"; A pkg] in
  518. (* TODO: consider how to really choose camlp4o or camlp4r. *)
  519. let syn_args = [A"-syntax"; A "camlp4o"] in
  520. let (args, pargs) =
  521. (* Heuristic to identify syntax extensions: whether they end in
  522. ".syntax"; some might not.
  523. *)
  524. if not (conf.no_automatic_syntax) &&
  525. (Filename.check_suffix pkg "syntax" ||
  526. List.mem pkg well_known_syntax) then
  527. (syn_args @ base_args, syn_args)
  528. else
  529. (base_args, [])
  530. in
  531. flag ["ocaml"; "compile"; "pkg_"^pkg] & S args;
  532. flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
  533. flag ["ocaml"; "doc"; "pkg_"^pkg] & S args;
  534. flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args;
  535. flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
  536. (* TODO: Check if this is allowed for OCaml < 3.12.1 *)
  537. flag ["ocaml"; "compile"; "package("^pkg^")"] & S pargs;
  538. flag ["ocaml"; "ocamldep"; "package("^pkg^")"] & S pargs;
  539. flag ["ocaml"; "doc"; "package("^pkg^")"] & S pargs;
  540. flag ["ocaml"; "infer_interface"; "package("^pkg^")"] & S pargs;
  541. end
  542. (find_packages ());
  543. (* Like -package but for extensions syntax. Morover -syntax is useless
  544. * when linking. *)
  545. List.iter begin fun syntax ->
  546. flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  547. flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  548. flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  549. flag ["ocaml"; "infer_interface"; "syntax_"^syntax] &
  550. S[A"-syntax"; A syntax];
  551. end (find_syntaxes ());
  552. (* The default "thread" tag is not compatible with ocamlfind.
  553. * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
  554. * options when using this tag. When using the "-linkpkg" option with
  555. * ocamlfind, this module will then be added twice on the command line.
  556. *
  557. * To solve this, one approach is to add the "-thread" option when using
  558. * the "threads" package using the previous plugin.
  559. *)
  560. flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
  561. flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
  562. flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
  563. flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]);
  564. flag ["c"; "pkg_threads"; "compile"] (S[A "-thread"]);
  565. flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]);
  566. flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]);
  567. flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]);
  568. flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]);
  569. flag ["c"; "package(threads)"; "compile"] (S[A "-thread"]);
  570. | _ ->
  571. ()
  572. end
  573. module MyOCamlbuildBase = struct
  574. (* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
  575. (** Base functions for writing myocamlbuild.ml
  576. @author Sylvain Le Gall
  577. *)
  578. open Ocamlbuild_plugin
  579. module OC = Ocamlbuild_pack.Ocaml_compiler
  580. type dir = string
  581. type file = string
  582. type name = string
  583. type tag = string
  584. type t =
  585. {
  586. lib_ocaml: (name * dir list * string list) list;
  587. lib_c: (name * dir * file list) list;
  588. flags: (tag list * (spec OASISExpr.choices)) list;
  589. (* Replace the 'dir: include' from _tags by a precise interdepends in
  590. * directory.
  591. *)
  592. includes: (dir * dir list) list;
  593. }
  594. (* # 110 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
  595. let env_filename = Pathname.basename BaseEnvLight.default_filename
  596. let dispatch_combine lst =
  597. fun e ->
  598. List.iter
  599. (fun dispatch -> dispatch e)
  600. lst
  601. let tag_libstubs nm =
  602. "use_lib"^nm^"_stubs"
  603. let nm_libstubs nm =
  604. nm^"_stubs"
  605. let dispatch t e =
  606. let env = BaseEnvLight.load ~allow_empty:true () in
  607. match e with
  608. | Before_options ->
  609. let no_trailing_dot s =
  610. if String.length s >= 1 && s.[0] = '.' then
  611. String.sub s 1 ((String.length s) - 1)
  612. else
  613. s
  614. in
  615. List.iter
  616. (fun (opt, var) ->
  617. try
  618. opt := no_trailing_dot (BaseEnvLight.var_get var env)
  619. with Not_found ->
  620. Printf.eprintf "W: Cannot get variable %s\n" var)
  621. [
  622. Options.ext_obj, "ext_obj";
  623. Options.ext_lib, "ext_lib";
  624. Options.ext_dll, "ext_dll";
  625. ]
  626. | After_rules ->
  627. (* Declare OCaml libraries *)
  628. List.iter
  629. (function
  630. | nm, [], intf_modules ->
  631. ocaml_lib nm;
  632. let cmis =
  633. List.map (fun m -> (OASISString.uncapitalize_ascii m) ^ ".cmi")
  634. intf_modules in
  635. dep ["ocaml"; "link"; "library"; "file:"^nm^".cma"] cmis
  636. | nm, dir :: tl, intf_modules ->
  637. ocaml_lib ~dir:dir (dir^"/"^nm);
  638. List.iter
  639. (fun dir ->
  640. List.iter
  641. (fun str ->
  642. flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir]))
  643. ["compile"; "infer_interface"; "doc"])
  644. tl;
  645. let cmis =
  646. List.map (fun m -> dir^"/"^(OASISString.uncapitalize_ascii m)^".cmi")
  647. intf_modules in
  648. dep ["ocaml"; "link"; "library"; "file:"^dir^"/"^nm^".cma"]
  649. cmis)
  650. t.lib_ocaml;
  651. (* Declare directories dependencies, replace "include" in _tags. *)
  652. List.iter
  653. (fun (dir, include_dirs) ->
  654. Pathname.define_context dir include_dirs)
  655. t.includes;
  656. (* Declare C libraries *)
  657. List.iter
  658. (fun (lib, dir, headers) ->
  659. (* Handle C part of library *)
  660. flag ["link"; "library"; "ocaml"; "byte"; tag_libstubs lib]
  661. (S[A"-dllib"; A("-l"^(nm_libstubs lib)); A"-cclib";
  662. A("-l"^(nm_libstubs lib))]);
  663. flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
  664. (S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
  665. if bool_of_string (BaseEnvLight.var_get "native_dynlink" env) then
  666. flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
  667. (S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
  668. (* When ocaml link something that use the C library, then one
  669. need that file to be up to date.
  670. This holds both for programs and for libraries.
  671. *)
  672. dep ["link"; "ocaml"; tag_libstubs lib]
  673. [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
  674. dep ["compile"; "ocaml"; tag_libstubs lib]
  675. [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
  676. (* TODO: be more specific about what depends on headers *)
  677. (* Depends on .h files *)
  678. dep ["compile"; "c"]
  679. headers;
  680. (* Setup search path for lib *)
  681. flag ["link"; "ocaml"; "use_"^lib]
  682. (S[A"-I"; P(dir)]);
  683. )
  684. t.lib_c;
  685. (* Add flags *)
  686. List.iter
  687. (fun (tags, cond_specs) ->
  688. let spec = BaseEnvLight.var_choose cond_specs env in
  689. let rec eval_specs =
  690. function
  691. | S lst -> S (List.map eval_specs lst)
  692. | A str -> A (BaseEnvLight.var_expand str env)
  693. | spec -> spec
  694. in
  695. flag tags & (eval_specs spec))
  696. t.flags
  697. | _ ->
  698. ()
  699. let dispatch_default conf t =
  700. dispatch_combine
  701. [
  702. dispatch t;
  703. MyOCamlbuildFindlib.dispatch conf;
  704. ]
  705. end
  706. # 884 "myocamlbuild.ml"
  707. open Ocamlbuild_plugin;;
  708. let package_default =
  709. {
  710. MyOCamlbuildBase.lib_ocaml = [];
  711. lib_c = [];
  712. flags = [];
  713. includes = [("src/test", ["src"]); ("src", ["src/test"])]
  714. }
  715. ;;
  716. let conf = {MyOCamlbuildFindlib.no_automatic_syntax = false}
  717. let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;;
  718. # 900 "myocamlbuild.ml"
  719. (* OASIS_STOP *)
  720. Ocamlbuild_plugin.dispatch dispatch_default;;