Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 5cba00e9e6
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 189 lines (168 sloc) 6.498 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
open Ocamlbuild_plugin
open Ocamlbuild_pack.Ocamlbuild_where
open Command

(*
* myocamlbuild.config example:
* # comment
* install_dir=../../site-lib
* bytecode=true
* nativecode=false
* xml=../../site-lib/xml
*)
let config =
  if not (Pathname.exists "myocamlbuild.config") then
    []
  else
    List.fold_left (fun acc line ->
                      if line.[0] = '#' then
                        acc
                      else
                        let sp = String.index line '=' in
                        let pair = ((String.sub line 0 sp),
                                    (String.sub line (sp+1)
                                       (String.length line - sp - 1))) in
                          pair :: acc
                   ) [] (string_list_of_file "myocamlbuild.config")

let get_install_dir () =
  try List.assoc "install_dir" config
  with Not_found ->
    Printf.printf "Please specify install_dir parameter in myocamlbuild.config";
    exit 1

let ocamlfind_query pkg =
  let cmd = Printf.sprintf
    "%s/ocamlfind query %s" !bindir (Filename.quote pkg) in
    Ocamlbuild_pack.My_unix.run_and_open cmd
      (fun ic ->
         (* Log.dprintf 5 "Getting Ocaml directory from command %s" cmd; *)
         input_line ic)

let tags =
  ["use_bigarray"; "use_dbm"; "use_dynlink"; "use_graphics";
   "use_nums"; "use_str"; "use_toplevel"; "use_unix"; "use_threads"]

let pkg_tags = ref []

let rec ocamlfind_get_deps predicates pkg =
  let rec aux_parse acc ic =
    let line = try Some (input_line ic) with _ -> None in
      match line with
        | None -> S (List.rev acc)
        | Some v ->
            let r = Ocamlbuild_pack.Lexers.space_sep_strings &
              Lexing.from_string v in
            let pkg, tail = List.hd r, List.tl r in
              if List.mem ("use_" ^ pkg) tags then
                aux_parse acc ic
              else if List.mem ("use_" ^ pkg, predicates) !pkg_tags then
                aux_parse acc ic
              else (
                pkg_tags := ("use_" ^ pkg, predicates) :: !pkg_tags;
                let deps = ocamlfind_get_deps predicates pkg in
                let rest = S[deps; A"-I"; A(List.hd tail);
                             S(List.map (fun a -> A a) (List.tl tail))]
                in
                  aux_parse (rest :: acc) ic
              )
  in
  let cmd = Printf.sprintf
    "%s/ocamlfind query -r -predicates %s -format \"%%p %%d %%A\" %s"
    !bindir predicates pkg in
    Ocamlbuild_pack.My_unix.run_and_open cmd &
      aux_parse []

let add_package pkg =
  let use_pkg = "use_" ^ pkg in
    flag ["ocaml"; "compile"; use_pkg] &
      S[A"-I"; A(ocamlfind_query pkg)];
    flag ["ocaml"; "link"; "native"; use_pkg] &
      ocamlfind_get_deps "native,mt" pkg;
    flag ["ocaml"; "link"; "byte"; use_pkg] &
      ocamlfind_get_deps "byte,mt" pkg

let extern ?cma ?tag_name name =
  try
    let path = List.assoc name config in
      ocaml_lib ~extern:true ?dir:(if path = "" then None else Some path)
        ?tag_name (match cma with | None -> name | Some name -> name)
  with Not_found ->
    add_package name
  
let make_binding ?include_dir ?lib_dir ~lib ?headers name =
  flag ["ocamlmklib"; "c"; ("use_" ^ name ^ "_clib")] &
    (match lib_dir with
       | None -> S[A lib]
       | Some dir -> S[A dir; A lib]
    );
               
  (match include_dir with
     | None -> ()
     | Some dir ->
         flag ["c"; "compile"; ("include_" ^ name ^ "_clib")] &
           S[A"-ccopt"; A dir]
  );

  flag ["link"; "ocaml"; "library"; ("use_" ^ name ^ "_clib")] &
    (match lib_dir with
       | None -> S[A"-cclib"; A lib]
       | Some dir -> S[A"-ccopt"; A dir; A"-cclib"; A lib]
    );
  
  (* If `static' is true then every ocaml link in bytecode will add -custom *)
  if true then
    flag ["link"; "ocaml"; "byte"; "use_lib" ^ name] & A"-custom";

  ocaml_lib name;
  
  flag ["link"; "library"; "ocaml"; "byte"; "use_lib" ^ name] &
    S[A"-dllib"; A("-l" ^ name);
      A"-ccopt"; A("-L ."); A"-cclib"; A("-l" ^ name)];

  flag ["link"; "library"; "ocaml"; "native"; "use_lib" ^ name] &
    S[A"-ccopt"; A"-L."; A"-cclib"; A("-l" ^ name)];

  dep ["link"; "ocaml"; ("use_lib" ^ name)] ["lib" ^ name -.- "a"];
  
  (* This will import headers in the build directory. *)
  match headers with
    | None -> ()
    | Some h ->
        dep ["compile"; "c"] h
  
let bytecode =
  try bool_of_string (List.assoc "bytecode" config) with Not_found -> true
let nativecode =
  try bool_of_string (List.assoc "nativecode" config) with Not_found -> true

let make_deps name =
  if bytecode then
    name -.- "cma" :: (if nativecode then [name -.- "cmxa"] else [])
  else
    (if nativecode then [name -.- "cmxa"] else [])

let install_lib name ?cma modules =
  let cma =
    match cma with
      | None -> name
      | Some v -> v
  in
  let deps = make_deps cma in
    rule "Install Library"
      ~prod:"install"
      ~deps
      (fun env _build ->
         let install_dir = get_install_dir () in
         let deps = List.map (fun file -> A file) deps in
         let mllib =
           let mllib = cma -.- "mllib" in
             if Pathname.exists mllib then
               let l = string_list_of_file mllib in
               let add_cmi file acc =
                 if Pathname.exists (file -.- "mli") then
                   A (file -.- "mli") :: A (file -.- "cmi") :: acc
                 else
                   A (file -.- "cmi") :: acc
               in
                 List.fold_left (fun acc f ->
                                   if Pathname.exists (f -.- "cmi") then
                                     add_cmi f acc
                                   else
                                     let f = String.uncapitalize f in
                                       if Pathname.exists (f -.- "cmi") then
                                         add_cmi f acc
                                       else
                                         acc
                                ) [A (cma -.- "a")] l
             else if Pathname.exists (cma -.- "mli") then
               [A (cma -.- "mli") ; A (cma -.- "cmi")]
             else
               [A (cma -.- "cmi")]
         in
         let files = List.map (fun file -> A file) modules in
           Seq [Cmd (S[A"mkdir"; A"-p"; P (install_dir / name)]);
                Cmd (S[Px"install"; S deps; P (install_dir / name)]);
                Cmd (S[Px"install"; S mllib; S files; P (install_dir / name)]);
               ]
      )
Something went wrong with that request. Please try again.