spacepaste

  1.  
  2. open Ocamlbuild_plugin
  3. (**
  4. Overview of tags:
  5. - [pkg_batteries] to use Batteries as a library, without syntax extensions
  6. - [use_batteries] and [use_batteries_r] to use both Batteries and all the non-destructive syntax extensions
  7. - [pkg_sexplib.syntax] with [syntax_camlp4o] or [syntax_camlp4r] for sexplib
  8. *)
  9. (**
  10. {1 OCamlFind}
  11. *)
  12. let run_and_read = Ocamlbuild_pack.My_unix.run_and_read
  13. let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings
  14. module OCamlFind =
  15. struct
  16. (* this lists all supported packages *)
  17. let find_packages () =
  18. blank_sep_strings &
  19. Lexing.from_string &
  20. run_and_read "ocamlfind list | cut -d' ' -f1"
  21. (* this is supposed to list available syntaxes, but I don't know how to do it. *)
  22. let find_syntaxes () = ["camlp4o"; "camlp4r"]
  23. (* ocamlfind command *)
  24. let ocamlfind x = S[A"ocamlfind"; x]
  25. let before_options () =
  26. (* by using Before_options one let command line options have an higher priority *)
  27. (* on the contrary using After_options will guarantee to have the higher priority *)
  28. (* override default commands by ocamlfind ones *)
  29. Options.ocamlc := ocamlfind & A"ocamlc";
  30. Options.ocamlopt := ocamlfind & A"ocamlopt";
  31. Options.ocamldep := ocamlfind & A"ocamldep";
  32. Options.ocamldoc := ocamlfind & A"ocamldoc";
  33. Options.ocamlmktop := ocamlfind & A"ocamlmktop"
  34. let get_ocamldoc_directory () =
  35. let ocamldoc_directory = run_and_read "ocamlfind ocamldoc -customdir" in
  36. let length = String.length ocamldoc_directory in
  37. assert (length != 0);
  38. let char = ocamldoc_directory.[length - 1] in
  39. if (char = '\n') || (char = '\r') then String.sub ocamldoc_directory 0 (length - 1)
  40. else ocamldoc_directory
  41. let after_rules () =
  42. (* When one link an OCaml library/binary/package, one should use -linkpkg *)
  43. flag ["ocaml"; "byte"; "link"; "program"] & A"-linkpkg";
  44. flag ["ocaml"; "native"; "link"; "program"] & A"-linkpkg";
  45. flag ["ocaml"; "byte"; "link"; "toplevel"] & A"-linkpkg";
  46. (* For each ocamlfind package one inject the -package option when
  47. * compiling, computing dependencies, generating documentation and
  48. * linking. *)
  49. List.iter begin fun pkg ->
  50. flag ["ocaml"; "compile"; "pkg_"^pkg] & S[A"-package"; A pkg];
  51. flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg];
  52. flag ["ocaml"; "doc"; "pkg_"^pkg] & S[A"-package"; A pkg];
  53. flag ["ocaml"; "link"; "pkg_"^pkg] & S[A"-package"; A pkg];
  54. end (find_packages ());
  55. (* Like -package but for extensions syntax. Morover -syntax is useless
  56. * when linking. *)
  57. List.iter begin fun syntax ->
  58. flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  59. flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  60. flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
  61. end (find_syntaxes ());
  62. (* The default "thread" tag is not compatible with ocamlfind.
  63. Indeed, the default rules add the "threads.cma" or "threads.cmxa"
  64. options when using this tag. When using the "-linkpkg" option with
  65. ocamlfind, this module will then be added twice on the command line.
  66. To solve this, one approach is to add the "-thread" option when using
  67. the "threads" package using the previous plugin.
  68. *)
  69. flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
  70. flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
  71. end
  72. (**
  73. {1 OCaml Batteries Included}
  74. *)
  75. module Batteries =
  76. struct
  77. let before_options () = ()
  78. let after_rules () =
  79. flag ["ocaml"; "link"; "byte"; "use_ocamldoc_info"] (S[A "-I"; A "+ocamldoc"; A "odoc_info.cma"]);
  80. flag ["ocaml"; "link"; "native"; "use_ocamldoc_info"] (S[A "-I"; A "+ocamldoc"(*; A "odoc_info.cmxa"*)]);
  81. flag ["ocaml"; "docfile"; "use_ocamldoc_info"] (S[A "-I"; A "+ocamldoc"]);
  82. flag ["ocaml"; "docdir"; "use_ocamldoc_info"] (S[A "-I"; A "+ocamldoc"]);
  83. flag ["ocaml"; "doc"; "use_ocamldoc_info"] (S[A "-I"; A "+ocamldoc"]);
  84. (*The command-line for [use_batteries] and [use_batteries_r]*)
  85. let cl_use_boilerplate = [A "-package"; A "batteries"]
  86. and cl_use_batteries = [A "-package"; A "batteries"]
  87. and cl_use_batteries_o = []
  88. (*[cl_use_batteries_o]: extensions which only make sense in original syntax*)
  89. and cl_camlp4o = [A"-syntax"; A "camlp4o"]
  90. and cl_camlp4r = [A"-syntax"; A "camlp4r"] in
  91. let cl_boilerplate_original = cl_use_boilerplate @ cl_camlp4o
  92. and cl_boilerplate_revised = cl_use_boilerplate @ cl_camlp4r
  93. and cl_batteries_original = cl_use_batteries @ cl_use_batteries_o @ cl_camlp4o
  94. and cl_batteries_revised = cl_use_batteries @ cl_camlp4r in
  95. (** Tag [use_boilerplate] provides boilerplate syntax extensions,
  96. in original syntax*)
  97. flag ["ocaml"; "compile"; "use_boilerplate"] & S cl_boilerplate_original ;
  98. flag ["ocaml"; "ocamldep"; "use_boilerplate"] & S cl_boilerplate_original ;
  99. flag ["ocaml"; "doc"; "use_boilerplate"] & S cl_boilerplate_original ;
  100. flag ["ocaml"; "link"; "use_boilerplate"] & S cl_boilerplate_original ;
  101. (** Tag [use_boilerplate_r] provides boilerplate syntax extensions,
  102. in original syntax*)
  103. flag ["ocaml"; "compile"; "use_boilerplate_r"] & S cl_boilerplate_revised ;
  104. flag ["ocaml"; "ocamldep"; "use_boilerplate_r"] & S cl_boilerplate_revised ;
  105. flag ["ocaml"; "doc"; "use_boilerplate_r"] & S cl_boilerplate_revised ;
  106. flag ["ocaml"; "link"; "use_boilerplate_r"] & S cl_boilerplate_revised ;
  107. (** Tag [use_batteries] provides both package [batteries]
  108. and all syntax extensions, in original syntax. *)
  109. flag ["ocaml"; "compile"; "use_batteries"] & S cl_batteries_original ;
  110. flag ["ocaml"; "ocamldep"; "use_batteries"] & S cl_batteries_original ;
  111. flag ["ocaml"; "doc"; "use_batteries"] & S cl_batteries_original ;
  112. flag ["ocaml"; "link"; "use_batteries"] & S cl_batteries_original ;
  113. (** Tag [use_batteries_r] provides both package [batteries]
  114. and all syntax extensions, in revised syntax. *)
  115. flag ["ocaml"; "compile"; "use_batteries_r"] & S cl_batteries_revised;
  116. flag ["ocaml"; "ocamldep"; "use_batteries_r"] & S cl_batteries_revised;
  117. flag ["ocaml"; "doc"; "use_batteries_r"] & S cl_batteries_revised;
  118. flag ["ocaml"; "link"; "use_batteries_r"] & S cl_batteries_revised
  119. (* flag ["ocaml"; "compile"; "use_batteries"] & S[A "-verbose";
  120. A"-package"; A "batteries.syntax.full";
  121. A"-syntax"; A "batteries.syntax.full"];
  122. flag ["ocaml"; "ocamldep"; "use_batteries"] & S[A "-verbose";
  123. A"-package"; A "batteries.syntax.full";
  124. A"-syntax"; A "batteries.syntax.full"];
  125. flag ["ocaml"; "doc"; "use_batteries"] & S[A "-verbose";
  126. A"-package"; A "batteries.syntax.full";
  127. A"-syntax"; A "batteries.syntax.full"];
  128. flag ["ocaml"; "link"; "use_batteries"] & S[A "-verbose";
  129. A"-package"; A "batteries.syntax.full";
  130. A"-syntax"; A "batteries.syntax.full"];*)
  131. end
  132. let setup_git_version () =
  133. let write_version version ch =
  134. Printf.fprintf ch "let version = %S\n" version;
  135. close_out ch
  136. in
  137. match run_and_read "git describe --long | tr -d '\\n'" with
  138. | "" ->
  139. begin match begin
  140. try
  141. Some (open_out_gen [Open_creat; Open_excl; Open_wronly] 0o644 "common_src/version.ml")
  142. with Sys_error _ -> None
  143. end with
  144. | Some ch -> write_version "unknown" ch
  145. | None -> ()
  146. end
  147. | version -> open_out "common_src/version.ml" |> write_version version
  148. let is_osx =
  149. (run_and_read "uname -s | tr -d '\\n'") = "Darwin"
  150. let _ = dispatch begin function
  151. | Before_options ->
  152. OCamlFind.before_options ();
  153. Batteries.before_options ();
  154. (* use static linking for native binaries *)
  155. if not is_osx then
  156. flag ["link"; "ocaml"; "native"] (S[A"-ccopt"; A"-static"]);
  157. | After_rules ->
  158. OCamlFind.after_rules ();
  159. Batteries.after_rules ();
  160. (* c compilation options *)
  161. flag ["compile"; "c"]
  162. (S[
  163. A"-ccopt"; A"-Wall";
  164. A"-ccopt"; A"-funroll-loops";
  165. A"-ccopt"; A"-O3";
  166. A"-ccopt"; A"-fPIC";
  167. ]);
  168. flag ["compile"; "c"; "debug"]
  169. (S[
  170. A"-ccopt"; A"-O0";
  171. A"-ccopt"; A"-g";
  172. ]);
  173. dep ["compile"; "c"]
  174. ["cdd_src/cdd.h"; "cdd_src/cddmp.h";
  175. "cdd_src/cddtypes.h"; "cdd_src/setoper.h"];
  176. if not is_osx then
  177. flag ["link"; "ocaml"; "native"] (S[A"-cclib"; A"-lpthread"]);
  178. (* custom: incorporate libraries into bytecode *)
  179. flag ["link"; "ocaml"; "byte"] (A"-custom");
  180. (* link with libpplacercside given c_pplacer tag *)
  181. flag ["link"; "ocaml"; "c_pplacer"; "toplevel"]
  182. (S[A"-cclib"; A"-lpplacercside"; A"-cclib"; A"-Lpplacer_src"]);
  183. flag ["link"; "ocaml"; "c_cdd"; "toplevel"]
  184. (S[A"-cclib"; A"-lcdd"; A"-cclib"; A"-Lcdd_src"]);
  185. flag ["link"; "ocaml"; "c_pam"; "toplevel"]
  186. (S[A"-cclib"; A"-lpam"; A"-cclib"; A"-Lpam_src"]);
  187. (* make libpplacercside when needed *)
  188. dep ["c_pplacer"] ["pplacer_src/libpplacercside.a"];
  189. dep ["c_cdd"] ["cdd_src/libcdd.a"];
  190. dep ["c_pam"] ["pam_src/libpam.a"];
  191. flag ["link"; "c_pam"] (S[A"-cclib"; A"-lgsl"]);
  192. | After_options ->
  193. setup_git_version ()
  194. | _ -> ()
  195. end
  196.