PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/myocamlbuild.ml

http://github.com/avsm/ocaml-workflow
OCaml | 478 lines | 358 code | 75 blank | 45 comment | 11 complexity | 1f244a32f526026dabb7fa71bf5a9bf3 MD5 | raw file
  1. (* OASIS_START *)
  2. (* DO NOT EDIT (digest: 3d509b8593bfa52700d4c5a29c88b0f2) *)
  3. module OASISGettext = struct
  4. # 21 "/Users/avsm/src/darcs/oasis/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. # 21 "/Users/avsm/src/darcs/oasis/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. module BaseEnvLight = struct
  93. # 21 "/Users/avsm/src/darcs/oasis/src/base/BaseEnvLight.ml"
  94. module MapString = Map.Make(String)
  95. type t = string MapString.t
  96. let default_filename =
  97. Filename.concat
  98. (Sys.getcwd ())
  99. "setup.data"
  100. let load ?(allow_empty=false) ?(filename=default_filename) () =
  101. if Sys.file_exists filename then
  102. begin
  103. let chn =
  104. open_in_bin filename
  105. in
  106. let st =
  107. Stream.of_channel chn
  108. in
  109. let line =
  110. ref 1
  111. in
  112. let st_line =
  113. Stream.from
  114. (fun _ ->
  115. try
  116. match Stream.next st with
  117. | '\n' -> incr line; Some '\n'
  118. | c -> Some c
  119. with Stream.Failure -> None)
  120. in
  121. let lexer =
  122. Genlex.make_lexer ["="] st_line
  123. in
  124. let rec read_file mp =
  125. match Stream.npeek 3 lexer with
  126. | [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] ->
  127. Stream.junk lexer;
  128. Stream.junk lexer;
  129. Stream.junk lexer;
  130. read_file (MapString.add nm value mp)
  131. | [] ->
  132. mp
  133. | _ ->
  134. failwith
  135. (Printf.sprintf
  136. "Malformed data file '%s' line %d"
  137. filename !line)
  138. in
  139. let mp =
  140. read_file MapString.empty
  141. in
  142. close_in chn;
  143. mp
  144. end
  145. else if allow_empty then
  146. begin
  147. MapString.empty
  148. end
  149. else
  150. begin
  151. failwith
  152. (Printf.sprintf
  153. "Unable to load environment, the file '%s' doesn't exist."
  154. filename)
  155. end
  156. let var_get name env =
  157. let rec var_expand str =
  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)
  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. in
  175. var_expand (MapString.find name env)
  176. let var_choose lst env =
  177. OASISExpr.choose
  178. (fun nm -> var_get nm env)
  179. lst
  180. end
  181. module MyOCamlbuildFindlib = struct
  182. # 21 "/Users/avsm/src/darcs/oasis/src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml"
  183. (** OCamlbuild extension, copied from
  184. * http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild
  185. * by N. Pouillard and others
  186. *
  187. * Updated on 2009/02/28
  188. *
  189. * Modified by Sylvain Le Gall
  190. *)
  191. open Ocamlbuild_plugin
  192. (* these functions are not really officially exported *)
  193. let run_and_read =
  194. Ocamlbuild_pack.My_unix.run_and_read
  195. let blank_sep_strings =
  196. Ocamlbuild_pack.Lexers.blank_sep_strings
  197. let split s ch =
  198. let x =
  199. ref []
  200. in
  201. let rec go s =
  202. let pos =
  203. String.index s ch
  204. in
  205. x := (String.before s pos)::!x;
  206. go (String.after s (pos + 1))
  207. in
  208. try
  209. go s
  210. with Not_found -> !x
  211. let split_nl s = split s '\n'
  212. let before_space s =
  213. try
  214. String.before s (String.index s ' ')
  215. with Not_found -> s
  216. (* this lists all supported packages *)
  217. let find_packages () =
  218. List.map before_space (split_nl & run_and_read "ocamlfind list")
  219. (* this is supposed to list available syntaxes, but I don't know how to do it. *)
  220. let find_syntaxes () = ["camlp4o"; "camlp4r"]
  221. (* ocamlfind command *)
  222. let ocamlfind x = S[A"ocamlfind"; x]
  223. let dispatch =
  224. function
  225. | Before_options ->
  226. (* by using Before_options one let command line options have an higher priority *)
  227. (* on the contrary using After_options will guarantee to have the higher priority *)
  228. (* override default commands by ocamlfind ones *)
  229. Options.ocamlc := ocamlfind & A"ocamlc";
  230. Options.ocamlopt := ocamlfind & A"ocamlopt";
  231. Options.ocamldep := ocamlfind & A"ocamldep";
  232. Options.ocamldoc := ocamlfind & A"ocamldoc";
  233. Options.ocamlmktop := ocamlfind & A"ocamlmktop"
  234. | After_rules ->
  235. (* When one link an OCaml library/binary/package, one should use -linkpkg *)
  236. flag ["ocaml"; "link"; "program"] & A"-linkpkg";
  237. (* For each ocamlfind package one inject the -package option when
  238. * compiling, computing dependencies, generating documentation and
  239. * linking. *)
  240. List.iter
  241. begin fun pkg ->
  242. flag ["ocaml"; "compile"; "pkg_"^pkg] & S[A"-package"; A pkg];
  243. flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg];
  244. flag ["ocaml"; "doc"; "pkg_"^pkg] & S[A"-package"; A pkg];
  245. flag ["ocaml"; "link"; "pkg_"^pkg] & S[A"-package"; A pkg];
  246. flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S[A"-package"; A pkg];
  247. end
  248. (find_packages ());
  249. (* Like -package but for extensions syntax. Morover -syntax is useless
  250. * when linking. *)
  251. List.iter begin fun syntax ->
  252. flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  253. flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  254. flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  255. flag ["ocaml"; "infer_interface"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  256. end (find_syntaxes ());
  257. (* The default "thread" tag is not compatible with ocamlfind.
  258. * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
  259. * options when using this tag. When using the "-linkpkg" option with
  260. * ocamlfind, this module will then be added twice on the command line.
  261. *
  262. * To solve this, one approach is to add the "-thread" option when using
  263. * the "threads" package using the previous plugin.
  264. *)
  265. flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
  266. flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
  267. flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
  268. flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"])
  269. | _ ->
  270. ()
  271. end
  272. module MyOCamlbuildBase = struct
  273. # 21 "/Users/avsm/src/darcs/oasis/src/plugins/ocamlbuild/MyOCamlbuildBase.ml"
  274. (** Base functions for writing myocamlbuild.ml
  275. @author Sylvain Le Gall
  276. *)
  277. open Ocamlbuild_plugin
  278. type dir = string
  279. type file = string
  280. type name = string
  281. type tag = string
  282. # 55 "/Users/avsm/src/darcs/oasis/src/plugins/ocamlbuild/MyOCamlbuildBase.ml"
  283. type t =
  284. {
  285. lib_ocaml: (name * dir list) list;
  286. lib_c: (name * dir * file list) list;
  287. flags: (tag list * (spec OASISExpr.choices)) list;
  288. }
  289. let env_filename =
  290. Pathname.basename
  291. BaseEnvLight.default_filename
  292. let dispatch_combine lst =
  293. fun e ->
  294. List.iter
  295. (fun dispatch -> dispatch e)
  296. lst
  297. let dispatch t e =
  298. let env =
  299. BaseEnvLight.load
  300. ~filename:env_filename
  301. ~allow_empty:true
  302. ()
  303. in
  304. match e with
  305. | Before_options ->
  306. let no_trailing_dot s =
  307. if String.length s >= 1 && s.[0] = '.' then
  308. String.sub s 1 ((String.length s) - 1)
  309. else
  310. s
  311. in
  312. List.iter
  313. (fun (opt, var) ->
  314. try
  315. opt := no_trailing_dot (BaseEnvLight.var_get var env)
  316. with Not_found ->
  317. Printf.eprintf "W: Cannot get variable %s" var)
  318. [
  319. Options.ext_obj, "ext_obj";
  320. Options.ext_lib, "ext_lib";
  321. Options.ext_dll, "ext_dll";
  322. ]
  323. | After_rules ->
  324. (* Declare OCaml libraries *)
  325. List.iter
  326. (function
  327. | lib, [] ->
  328. ocaml_lib lib;
  329. | lib, dir :: tl ->
  330. ocaml_lib ~dir:dir lib;
  331. List.iter
  332. (fun dir ->
  333. flag
  334. ["ocaml"; "use_"^lib; "compile"]
  335. (S[A"-I"; P dir]))
  336. tl)
  337. t.lib_ocaml;
  338. (* Declare C libraries *)
  339. List.iter
  340. (fun (lib, dir, headers) ->
  341. (* Handle C part of library *)
  342. flag ["link"; "library"; "ocaml"; "byte"; "use_lib"^lib]
  343. (S[A"-dllib"; A("-l"^lib); A"-cclib"; A("-l"^lib)]);
  344. flag ["link"; "library"; "ocaml"; "native"; "use_lib"^lib]
  345. (S[A"-cclib"; A("-l"^lib)]);
  346. flag ["link"; "program"; "ocaml"; "byte"; "use_lib"^lib]
  347. (S[A"-dllib"; A("dll"^lib)]);
  348. (* When ocaml link something that use the C library, then one
  349. need that file to be up to date.
  350. *)
  351. dep ["compile"; "ocaml"; "use_lib"^lib]
  352. [dir/"lib"^lib^"."^(!Options.ext_lib)];
  353. (* TODO: be more specific about what depends on headers *)
  354. (* Depends on .h files *)
  355. dep ["compile"; "c"]
  356. headers;
  357. (* Setup search path for lib *)
  358. flag ["link"; "ocaml"; "use_"^lib]
  359. (S[A"-I"; P(dir)]);
  360. )
  361. t.lib_c;
  362. (* Add flags *)
  363. List.iter
  364. (fun (tags, cond_specs) ->
  365. let spec =
  366. BaseEnvLight.var_choose cond_specs env
  367. in
  368. flag tags & spec)
  369. t.flags
  370. | _ ->
  371. ()
  372. let dispatch_default t =
  373. dispatch_combine
  374. [
  375. dispatch t;
  376. MyOCamlbuildFindlib.dispatch;
  377. ]
  378. end
  379. open Ocamlbuild_plugin;;
  380. let package_default =
  381. {
  382. MyOCamlbuildBase.lib_ocaml = [("lib/workflow", ["lib"])];
  383. lib_c = [("workflow", "lib", [])];
  384. flags =
  385. [
  386. (["oasis_library_workflow_cclib"; "link"],
  387. [
  388. (OASISExpr.EBool true, S []);
  389. (OASISExpr.ETest ("system", "linux"),
  390. S [A "-cclib"; A "-lrt"])
  391. ]);
  392. (["oasis_library_workflow_cclib"; "ocamlmklib"; "c"],
  393. [
  394. (OASISExpr.EBool true, S []);
  395. (OASISExpr.ETest ("system", "linux"), S [A "-lrt"])
  396. ])
  397. ];
  398. }
  399. ;;
  400. let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;;
  401. # 477 "myocamlbuild.ml"
  402. (* OASIS_STOP *)
  403. Ocamlbuild_plugin.dispatch dispatch_default;;