myocamlbuild.ml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. (* OASIS_START *)
  2. (* DO NOT EDIT (digest: 4f240f06ff7a70bb4e3be1240a180aab) *)
  3. module OASISGettext = struct
  4. (* # 22 "/home/lwzukw/.opam/4.01.0/build/oasis.0.4.4/src/oasis/OASISGettext.ml" *)
  5. let ns_ str =
  6. str
  7. let s_ str =
  8. str
  9. let f_ (str: ('a, 'b, 'c, 'd) format4) =
  10. str
  11. let fn_ fmt1 fmt2 n =
  12. if n = 1 then
  13. fmt1^^""
  14. else
  15. fmt2^^""
  16. let init =
  17. []
  18. end
  19. module OASISExpr = struct
  20. (* # 22 "/home/lwzukw/.opam/4.01.0/build/oasis.0.4.4/src/oasis/OASISExpr.ml" *)
  21. open OASISGettext
  22. type test = string
  23. type flag = string
  24. type t =
  25. | EBool of bool
  26. | ENot of t
  27. | EAnd of t * t
  28. | EOr of t * t
  29. | EFlag of flag
  30. | ETest of test * string
  31. type 'a choices = (t * 'a) list
  32. let eval var_get t =
  33. let rec eval' =
  34. function
  35. | EBool b ->
  36. b
  37. | ENot e ->
  38. not (eval' e)
  39. | EAnd (e1, e2) ->
  40. (eval' e1) && (eval' e2)
  41. | EOr (e1, e2) ->
  42. (eval' e1) || (eval' e2)
  43. | EFlag nm ->
  44. let v =
  45. var_get nm
  46. in
  47. assert(v = "true" || v = "false");
  48. (v = "true")
  49. | ETest (nm, vl) ->
  50. let v =
  51. var_get nm
  52. in
  53. (v = vl)
  54. in
  55. eval' t
  56. let choose ?printer ?name var_get lst =
  57. let rec choose_aux =
  58. function
  59. | (cond, vl) :: tl ->
  60. if eval var_get cond then
  61. vl
  62. else
  63. choose_aux tl
  64. | [] ->
  65. let str_lst =
  66. if lst = [] then
  67. s_ "<empty>"
  68. else
  69. String.concat
  70. (s_ ", ")
  71. (List.map
  72. (fun (cond, vl) ->
  73. match printer with
  74. | Some p -> p vl
  75. | None -> s_ "<no printer>")
  76. lst)
  77. in
  78. match name with
  79. | Some nm ->
  80. failwith
  81. (Printf.sprintf
  82. (f_ "No result for the choice list '%s': %s")
  83. nm str_lst)
  84. | None ->
  85. failwith
  86. (Printf.sprintf
  87. (f_ "No result for a choice list: %s")
  88. str_lst)
  89. in
  90. choose_aux (List.rev lst)
  91. end
  92. # 132 "myocamlbuild.ml"
  93. module BaseEnvLight = struct
  94. (* # 22 "/home/lwzukw/.opam/4.01.0/build/oasis.0.4.4/src/base/BaseEnvLight.ml" *)
  95. module MapString = Map.Make(String)
  96. type t = string MapString.t
  97. let default_filename =
  98. Filename.concat
  99. (Sys.getcwd ())
  100. "setup.data"
  101. let load ?(allow_empty=false) ?(filename=default_filename) () =
  102. if Sys.file_exists filename then
  103. begin
  104. let chn =
  105. open_in_bin filename
  106. in
  107. let st =
  108. Stream.of_channel chn
  109. in
  110. let line =
  111. ref 1
  112. in
  113. let st_line =
  114. Stream.from
  115. (fun _ ->
  116. try
  117. match Stream.next st with
  118. | '\n' -> incr line; Some '\n'
  119. | c -> Some c
  120. with Stream.Failure -> None)
  121. in
  122. let lexer =
  123. Genlex.make_lexer ["="] st_line
  124. in
  125. let rec read_file mp =
  126. match Stream.npeek 3 lexer with
  127. | [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] ->
  128. Stream.junk lexer;
  129. Stream.junk lexer;
  130. Stream.junk lexer;
  131. read_file (MapString.add nm value mp)
  132. | [] ->
  133. mp
  134. | _ ->
  135. failwith
  136. (Printf.sprintf
  137. "Malformed data file '%s' line %d"
  138. filename !line)
  139. in
  140. let mp =
  141. read_file MapString.empty
  142. in
  143. close_in chn;
  144. mp
  145. end
  146. else if allow_empty then
  147. begin
  148. MapString.empty
  149. end
  150. else
  151. begin
  152. failwith
  153. (Printf.sprintf
  154. "Unable to load environment, the file '%s' doesn't exist."
  155. filename)
  156. end
  157. let rec var_expand str env =
  158. let buff =
  159. Buffer.create ((String.length str) * 2)
  160. in
  161. Buffer.add_substitute
  162. buff
  163. (fun var ->
  164. try
  165. var_expand (MapString.find var env) env
  166. with Not_found ->
  167. failwith
  168. (Printf.sprintf
  169. "No variable %s defined when trying to expand %S."
  170. var
  171. str))
  172. str;
  173. Buffer.contents buff
  174. let var_get name env =
  175. var_expand (MapString.find name env) env
  176. let var_choose lst env =
  177. OASISExpr.choose
  178. (fun nm -> var_get nm env)
  179. lst
  180. end
  181. # 237 "myocamlbuild.ml"
  182. module MyOCamlbuildFindlib = struct
  183. (* # 22 "/home/lwzukw/.opam/4.01.0/build/oasis.0.4.4/src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
  184. (** OCamlbuild extension, copied from
  185. * http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild
  186. * by N. Pouillard and others
  187. *
  188. * Updated on 2009/02/28
  189. *
  190. * Modified by Sylvain Le Gall
  191. *)
  192. open Ocamlbuild_plugin
  193. (* these functions are not really officially exported *)
  194. let run_and_read =
  195. Ocamlbuild_pack.My_unix.run_and_read
  196. let blank_sep_strings =
  197. Ocamlbuild_pack.Lexers.blank_sep_strings
  198. let exec_from_conf exec =
  199. let exec =
  200. let env_filename = Pathname.basename BaseEnvLight.default_filename in
  201. let env = BaseEnvLight.load ~filename:env_filename ~allow_empty:true () in
  202. try
  203. BaseEnvLight.var_get exec env
  204. with Not_found ->
  205. Printf.eprintf "W: Cannot get variable %s\n" exec;
  206. exec
  207. in
  208. let fix_win32 str =
  209. if Sys.os_type = "Win32" then begin
  210. let buff = Buffer.create (String.length str) in
  211. (* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'.
  212. *)
  213. String.iter
  214. (fun c -> Buffer.add_char buff (if c = '\\' then '/' else c))
  215. str;
  216. Buffer.contents buff
  217. end else begin
  218. str
  219. end
  220. in
  221. fix_win32 exec
  222. let split s ch =
  223. let buf = Buffer.create 13 in
  224. let x = ref [] in
  225. let flush () =
  226. x := (Buffer.contents buf) :: !x;
  227. Buffer.clear buf
  228. in
  229. String.iter
  230. (fun c ->
  231. if c = ch then
  232. flush ()
  233. else
  234. Buffer.add_char buf c)
  235. s;
  236. flush ();
  237. List.rev !x
  238. let split_nl s = split s '\n'
  239. let before_space s =
  240. try
  241. String.before s (String.index s ' ')
  242. with Not_found -> s
  243. (* ocamlfind command *)
  244. let ocamlfind x = S[Sh (exec_from_conf "ocamlfind"); x]
  245. (* This lists all supported packages. *)
  246. let find_packages () =
  247. List.map before_space (split_nl & run_and_read "ocamlfind list")
  248. (* Mock to list available syntaxes. *)
  249. let find_syntaxes () = ["camlp4o"; "camlp4r"]
  250. let well_known_syntax = [
  251. "camlp4.quotations.o";
  252. "camlp4.quotations.r";
  253. "camlp4.exceptiontracer";
  254. "camlp4.extend";
  255. "camlp4.foldgenerator";
  256. "camlp4.listcomprehension";
  257. "camlp4.locationstripper";
  258. "camlp4.macro";
  259. "camlp4.mapgenerator";
  260. "camlp4.metagenerator";
  261. "camlp4.profiler";
  262. "camlp4.tracer"
  263. ]
  264. let dispatch =
  265. function
  266. | After_options ->
  267. (* By using Before_options one let command line options have an higher
  268. * priority on the contrary using After_options will guarantee to have
  269. * the higher priority override default commands by ocamlfind ones *)
  270. Options.ocamlc := ocamlfind & A"ocamlc";
  271. Options.ocamlopt := ocamlfind & A"ocamlopt";
  272. Options.ocamldep := ocamlfind & A"ocamldep";
  273. Options.ocamldoc := ocamlfind & A"ocamldoc";
  274. Options.ocamlmktop := ocamlfind & A"ocamlmktop";
  275. Options.ocamlmklib := ocamlfind & A"ocamlmklib"
  276. | After_rules ->
  277. (* When one link an OCaml library/binary/package, one should use
  278. * -linkpkg *)
  279. flag ["ocaml"; "link"; "program"] & A"-linkpkg";
  280. (* For each ocamlfind package one inject the -package option when
  281. * compiling, computing dependencies, generating documentation and
  282. * linking. *)
  283. List.iter
  284. begin fun pkg ->
  285. let base_args = [A"-package"; A pkg] in
  286. (* TODO: consider how to really choose camlp4o or camlp4r. *)
  287. let syn_args = [A"-syntax"; A "camlp4o"] in
  288. let args =
  289. (* Heuristic to identify syntax extensions: whether they end in
  290. ".syntax"; some might not.
  291. *)
  292. if Filename.check_suffix pkg "syntax" ||
  293. List.mem pkg well_known_syntax then
  294. syn_args @ base_args
  295. else
  296. base_args
  297. in
  298. flag ["ocaml"; "compile"; "pkg_"^pkg] & S args;
  299. flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
  300. flag ["ocaml"; "doc"; "pkg_"^pkg] & S args;
  301. flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args;
  302. flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
  303. end
  304. (find_packages ());
  305. (* Like -package but for extensions syntax. Morover -syntax is useless
  306. * when linking. *)
  307. List.iter begin fun syntax ->
  308. flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  309. flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  310. flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  311. flag ["ocaml"; "infer_interface"; "syntax_"^syntax] &
  312. S[A"-syntax"; A syntax];
  313. end (find_syntaxes ());
  314. (* The default "thread" tag is not compatible with ocamlfind.
  315. * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
  316. * options when using this tag. When using the "-linkpkg" option with
  317. * ocamlfind, this module will then be added twice on the command line.
  318. *
  319. * To solve this, one approach is to add the "-thread" option when using
  320. * the "threads" package using the previous plugin.
  321. *)
  322. flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
  323. flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
  324. flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
  325. flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]);
  326. flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]);
  327. flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]);
  328. flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]);
  329. flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]);
  330. | _ ->
  331. ()
  332. end
  333. module MyOCamlbuildBase = struct
  334. (* # 22 "/home/lwzukw/.opam/4.01.0/build/oasis.0.4.4/src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
  335. (** Base functions for writing myocamlbuild.ml
  336. @author Sylvain Le Gall
  337. *)
  338. open Ocamlbuild_plugin
  339. module OC = Ocamlbuild_pack.Ocaml_compiler
  340. type dir = string
  341. type file = string
  342. type name = string
  343. type tag = string
  344. (* # 62 "/home/lwzukw/.opam/4.01.0/build/oasis.0.4.4/src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
  345. type t =
  346. {
  347. lib_ocaml: (name * dir list * string list) list;
  348. lib_c: (name * dir * file list) list;
  349. flags: (tag list * (spec OASISExpr.choices)) list;
  350. (* Replace the 'dir: include' from _tags by a precise interdepends in
  351. * directory.
  352. *)
  353. includes: (dir * dir list) list;
  354. }
  355. let env_filename =
  356. Pathname.basename
  357. BaseEnvLight.default_filename
  358. let dispatch_combine lst =
  359. fun e ->
  360. List.iter
  361. (fun dispatch -> dispatch e)
  362. lst
  363. let tag_libstubs nm =
  364. "use_lib"^nm^"_stubs"
  365. let nm_libstubs nm =
  366. nm^"_stubs"
  367. let dispatch t e =
  368. let env =
  369. BaseEnvLight.load
  370. ~filename:env_filename
  371. ~allow_empty:true
  372. ()
  373. in
  374. match e with
  375. | Before_options ->
  376. let no_trailing_dot s =
  377. if String.length s >= 1 && s.[0] = '.' then
  378. String.sub s 1 ((String.length s) - 1)
  379. else
  380. s
  381. in
  382. List.iter
  383. (fun (opt, var) ->
  384. try
  385. opt := no_trailing_dot (BaseEnvLight.var_get var env)
  386. with Not_found ->
  387. Printf.eprintf "W: Cannot get variable %s\n" var)
  388. [
  389. Options.ext_obj, "ext_obj";
  390. Options.ext_lib, "ext_lib";
  391. Options.ext_dll, "ext_dll";
  392. ]
  393. | After_rules ->
  394. (* Declare OCaml libraries *)
  395. List.iter
  396. (function
  397. | nm, [], intf_modules ->
  398. ocaml_lib nm;
  399. let cmis =
  400. List.map (fun m -> (String.uncapitalize m) ^ ".cmi")
  401. intf_modules in
  402. dep ["ocaml"; "link"; "library"; "file:"^nm^".cma"] cmis
  403. | nm, dir :: tl, intf_modules ->
  404. ocaml_lib ~dir:dir (dir^"/"^nm);
  405. List.iter
  406. (fun dir ->
  407. List.iter
  408. (fun str ->
  409. flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir]))
  410. ["compile"; "infer_interface"; "doc"])
  411. tl;
  412. let cmis =
  413. List.map (fun m -> dir^"/"^(String.uncapitalize m)^".cmi")
  414. intf_modules in
  415. dep ["ocaml"; "link"; "library"; "file:"^dir^"/"^nm^".cma"]
  416. cmis)
  417. t.lib_ocaml;
  418. (* Declare directories dependencies, replace "include" in _tags. *)
  419. List.iter
  420. (fun (dir, include_dirs) ->
  421. Pathname.define_context dir include_dirs)
  422. t.includes;
  423. (* Declare C libraries *)
  424. List.iter
  425. (fun (lib, dir, headers) ->
  426. (* Handle C part of library *)
  427. flag ["link"; "library"; "ocaml"; "byte"; tag_libstubs lib]
  428. (S[A"-dllib"; A("-l"^(nm_libstubs lib)); A"-cclib";
  429. A("-l"^(nm_libstubs lib))]);
  430. flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
  431. (S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
  432. flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
  433. (S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
  434. (* When ocaml link something that use the C library, then one
  435. need that file to be up to date.
  436. *)
  437. dep ["link"; "ocaml"; "program"; tag_libstubs lib]
  438. [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
  439. dep ["compile"; "ocaml"; "program"; tag_libstubs lib]
  440. [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
  441. (* TODO: be more specific about what depends on headers *)
  442. (* Depends on .h files *)
  443. dep ["compile"; "c"]
  444. headers;
  445. (* Setup search path for lib *)
  446. flag ["link"; "ocaml"; "use_"^lib]
  447. (S[A"-I"; P(dir)]);
  448. )
  449. t.lib_c;
  450. (* Add flags *)
  451. List.iter
  452. (fun (tags, cond_specs) ->
  453. let spec = BaseEnvLight.var_choose cond_specs env in
  454. let rec eval_specs =
  455. function
  456. | S lst -> S (List.map eval_specs lst)
  457. | A str -> A (BaseEnvLight.var_expand str env)
  458. | spec -> spec
  459. in
  460. flag tags & (eval_specs spec))
  461. t.flags
  462. | _ ->
  463. ()
  464. let dispatch_default t =
  465. dispatch_combine
  466. [
  467. dispatch t;
  468. MyOCamlbuildFindlib.dispatch;
  469. ]
  470. end
  471. # 594 "myocamlbuild.ml"
  472. open Ocamlbuild_plugin;;
  473. let package_default =
  474. {MyOCamlbuildBase.lib_ocaml = []; lib_c = []; flags = []; includes = []}
  475. ;;
  476. let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;;
  477. # 603 "myocamlbuild.ml"
  478. (* OASIS_STOP *)
  479. Ocamlbuild_plugin.dispatch dispatch_default;;