summaryrefslogtreecommitdiffstats
path: root/myocamlbuild.ml
blob: 698f3dca75161b9132fdd02f1acfb6432b400ffb (plain)
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
open Ocamlbuild_plugin
open Command

let run_and_read      = Ocamlbuild_pack.My_unix.run_and_read

let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings

let hdf4_linkflags cclib =
  let tag = if cclib then A "-cclib" else N in
  let all_elements =
    blank_sep_strings &
      Lexing.from_string &
      run_and_read "h4cc -show"
  in
  let is_linker_flag s = s.[0] = '-' && (s.[1] = 'l' || s.[1] = 'L') in
  let flags = List.filter is_linker_flag all_elements in
  S (List.map (fun flag -> S [tag; A flag]) flags)

(* A simple function to check if a string is empty/whitespace *)
let is_all_whitespace s =
  try
    String.iter (fun c -> if c <> ' ' then raise Exit) s;
    true
  with Exit -> false

let get_env_elem s =
  let it = getenv s in
  match is_all_whitespace it with
      true -> N
    | false -> A it

let camlidl_lib = get_env_elem "CAMLIDL_LIB"
let camlidl_lib_dir = get_env_elem "CAMLIDL_LIB_DIR"
let other_cflags = get_env_elem "CFLAGS"

(* ocamlfind packages required for compilation *)
let packages = "batteries extbigarray pcre"

(* Build an appropriate ocamlfind command line *)
let ocamlfind cmd cc =
  S (
    [A "ocamlfind"; A cmd]
    @ (match cc with None -> [N] | Some x -> [A "-cc"; A x])
    @ [A "-package"; A packages]
  )

(* Link packages in when needed. *)
let () = flag ["ocaml"; "link"; "program"] (A "-linkpkg")

(* The camlidl command to use (default: first one found in $PATH) *)
let camlidl = S([A"camlidl"; A"-header"])

(* Files included in the main idl descriptor *)
let idl_includes =
  ["hdf_h.inc"; "mfhdf_h.inc"; "hlimits_h.idl"; "hdf_extras.idl"]
;;

dispatch begin function
  | After_options ->
      (* Redefine ocaml{c,opt,dep} to use the ocamlfind equivalents *)
      Options.ocamlc := ocamlfind "c" (Some "h4cc");
      Options.ocamlopt := ocamlfind "opt" (Some "h4cc");
      Options.ocamldep := ocamlfind "dep" None;
  | After_rules ->
      (* Handle *.idl files properly... I think *)
      rule "camlidl processing"
        ~prods:["%.mli"; "%.ml"; "%_stubs.c"]
        ~deps:["%.idl"]
        begin fun env _build ->
          let idl = env "%.idl" in
          let tags = tags_of_pathname idl++"compile"++"camlidl" in
          let cmd = Cmd(S[camlidl; T tags; P idl]) in
          Seq [cmd]
        end;

      (* gcc needs to know where to find the needed #includes *)
      flag ["c"; "compile"]
        (S[A"-ccopt"; other_cflags]);

      (* Include the HDF and camlidl compiler options for ocamlmklib *)
      flag ["ocamlmklib"; "c"]
        (S[camlidl_lib_dir; camlidl_lib; hdf4_linkflags false]);

      (* Custom tag for OCaml bytecode *)
      flag ["ocaml"; "link"; "byte"]
        (A"-custom");

      (* Use the proper extras when compiling the OCaml library *)
      flag ["ocaml"; "link"; "library"; "byte"]
        (S[A"-dllib"; A "-lhdf_stubs"; A"-cclib"; A"-lhdf_stubs";
           A"-cclib"; camlidl_lib; hdf4_linkflags true]);

      flag ["ocaml"; "link"; "library"; "native"]
        (S[A"-cclib"; A"-lhdf_stubs"; A"-cclib"; camlidl_lib;
           hdf4_linkflags true]);

      (* Make sure the C pieces and built... *)
      dep ["ocaml"; "compile"] ["libhdf_stubs.a"];

      (* Any camlidl work must be updated if the camlidl inputs are changed *)
      dep ["compile"; "camlidl"] idl_includes;

  | _ -> ()
end