Skip to content

Commit 5685cac

Browse files
authored
Dehackify cxx and llvm building (#557)
* split setup.ml.in and myocamlbuild.ml.in The above specified files contained definitions that were not generic, but belonged to specific modules, thus breaking module abstraction boundaries. The llvm flags were hardcoded in the rule for building C++ files. This PR makes everything in a proper way. We use tags properly in our rules, so that later we can inject proper flags. Now, all packages, that need special building rules, have their own files in the oasis directory. For example, llvm package defines its building rules in three files: - oasis/llvm.setup.ml.in -- define configuration parameters; - oasis/llvm.tags.in -- tag files, that need specific handling; - oasis/llvm.ocamlbuild.ml.in - inject llvm flags, when building tagged files. There are still few things, that should be fixed. For example, both piqi and cxx rules have a hardcoded paths for -I option. * fix configuration on mac os x 1. don't panic if there is no `llvm-config` 2. look at `llvm-confi-mp-$ver` where `$ver` doesn't include patch version
1 parent 55f2c22 commit 5685cac

12 files changed

+186
-157
lines changed

lib/bap_build/bap_build.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ module Plugin_rules = struct
153153
make_list_option "-provides" in
154154
Cmd (S [
155155
A "bapbundle"; A "pack";
156+
T (Tags.of_list ["bundle"; "library"; "plugin"]);
156157
A "-name"; A (dashify (env "%"));
157158
A "-main"; A (env "%.cmxs");
158159
A "-main"; A (env "%.cma");

myocamlbuild.ml.in

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,20 @@
1-
let nonempty = function (A s) -> String.length s <> 0 | _ -> true
2-
3-
(* the piqi support is rather fragile *)
4-
let piqic_rule () : unit =
5-
rule "piqic: piqi -> .ml & _ext.ml"
6-
~prods:["%_piqi.ml"; "%_piqi_ext.ml"]
7-
~deps:["%.piqi"]
8-
(fun env _ ->
9-
Cmd (S (List.filter nonempty [
10-
A (expand "${piqic}");
11-
A (expand "${piqic_flags}");
12-
A "-C";
13-
A "lib/bap_piqi";
14-
A "-I";
15-
A "../lib/bap_piqi";
16-
A (env "%.piqi");
17-
A"--multi-format"])));;
18-
191
let cxx_rule () =
202
let deps = ["%.hpp"; "%.cpp"; "%.h"] and prod = "%.o" in
21-
let action env _ = Cmd (S [
22-
Sh (expand "${cxx} ${cxxflags} ${llvm_cxxflags}");
23-
A "-c"; P (env "%.cpp"); A "-o"; P (env "%.o")]) in
3+
let action env _ =
4+
let src = env "%.cpp" and obj = env "%.o" in
5+
let cxx = expand "${cxx} ${cc_optimization} ${cxxflags}" in
6+
let tags = tags_of_pathname src ++ "c++" ++ "compile" in
7+
Cmd (S [Sh cxx; T tags; A "-c"; P src; A "-o"; Px obj]) in
248
rule "cxx: hpp & cpp & h -> o" ~deps ~prod action
259

26-
let dispatch = function
27-
| Before_rules ->
28-
piqic_rule ();
29-
cxx_rule ();
30-
| After_rules ->
31-
List.iter
32-
(fun tag ->
33-
pflag ["ocaml"; tag] "pa_ounit_lib"
34-
(fun s -> S[A"-ppopt"; A"-pa-ounit-lib"; A"-ppopt"; A s]))
35-
["ocamldep"; "compile"; "doc"];
36-
| _ -> ()
10+
let () = Rules.add cxx_rule
3711

38-
module Ocamlbuild_compat = struct
39-
let mark_tag_used = ignore
40-
include Ocamlbuild_plugin
41-
end
4212

4313
let mark_tags () =
14+
let module Ocamlbuild_compat = struct
15+
let mark_tag_used = ignore
16+
include Ocamlbuild_plugin
17+
end in
4418
let open Ocamlbuild_compat in
4519
List.iter mark_tag_used [
4620
"pkg_core_bench";
@@ -54,17 +28,24 @@ let pr_6184_hack = function
5428
| After_rules ->
5529
(* Pass -predicates to ocamldep *)
5630
pflag ["ocaml"; "ocamldep"] "predicate" (fun s -> S [A "-predicates"; A s]);
31+
| _ -> ()
32+
33+
34+
let predicate_used_libs = function
35+
| After_rules ->
5736
package_default.MyOCamlbuildBase.lib_ocaml |>
5837
List.iter (fun (lib,_,_) ->
5938
flag ["ocaml"; "link"; "use_"^lib]
60-
(S [A "-predicates"; A ("used_"^lib)]));
39+
(S [A "-predicates"; A ("used_"^lib)]))
6140
| _ -> ()
6241

6342

43+
6444
let () =
6545
mark_tags ();
66-
Ocamlbuild_plugin.dispatch (fun hook ->
67-
dispatch hook;
68-
dispatch_default hook;
69-
pr_6184_hack hook;
70-
Ppx_driver_ocamlbuild.dispatch hook)
46+
Ocamlbuild_plugin.dispatch (fun stage ->
47+
Rules.dispatch stage;
48+
dispatch_default stage;
49+
pr_6184_hack stage;
50+
predicate_used_libs stage;
51+
Ppx_driver_ocamlbuild.dispatch stage)

oasis/common.ocamlbuild.ml.in

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
(* OASIS_START *)
22
(* OASIS_STOP *)
3-
#4 "oasis/common.ocamlbuild.ml.in"
3+
44
let oasis_env =
55
BaseEnvLight.load
66
~allow_empty:true
77
()
88
let expand s = BaseEnvLight.var_expand s oasis_env
9+
10+
type rule = unit -> unit
11+
12+
module Rules : sig
13+
val add : rule -> unit
14+
val dispatch : hook -> unit
15+
end = struct
16+
let rules : (unit -> unit) list ref = ref []
17+
let add rule = rules := rule :: !rules
18+
let dispatch = function
19+
| Before_rules -> !rules |> List.iter (fun rule -> rule ())
20+
| _ -> ()
21+
end

oasis/common.setup.ml.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
(* OASIS_STOP *)
44
#5 "oasis/common.setup.ml.in"
55
let definition_end = BaseEnv.var_ignore
6+
let define definitions =
7+
List.iter (fun f -> try f () with exn -> ()) definitions
8+
69

710
let ctxt = !BaseContext.default
811

@@ -47,3 +50,11 @@ let is_undefined var : bool = not (is_defined var)
4750

4851
let is_set_to var value : bool =
4952
is_defined var && BaseEnv.var_get var = value
53+
54+
55+
let rec find_map xs ~f =
56+
match xs with
57+
| [] -> None
58+
| x :: xs -> match f x with
59+
| None -> find_map xs ~f
60+
| yay -> yay

oasis/ida.setup.ml.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
let define_headless = function
23
| Some "true" when BaseEnv.var_get "system" <> "linux" ->
34
invalid_arg "headless mode is supported only on linux"

oasis/llvm.ocamlbuild.ml.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
let () =
2+
flag ["c++"; "compile"; "use_libllvm"] (Sh (expand "${llvm_cxxflags}"))

oasis/llvm.setup.ml.in

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
let strip_patch ver =
2+
if String.length ver <> 5 then ver
3+
else String.sub ver 0 3
4+
5+
6+
let llvm var () : unit =
7+
BaseEnv.var_define
8+
~hide:true
9+
~dump:true
10+
~short_desc:(fun () -> "llvm-config --"^var)
11+
("llvm_"^var)
12+
(fun () ->
13+
let llvm_config = BaseEnv.var_get "llvm_config" in
14+
let llvm_version = BaseEnv.var_get "llvm_version" in
15+
let extract v =
16+
OASISExec.run_read_one_line ~ctxt llvm_config ["--"^v] in
17+
if strip_patch llvm_version > "3.4" && var = "ldflags"
18+
then extract var ^ " " ^ extract "system-libs"
19+
else extract var) |>
20+
definition_end
21+
22+
let llvm_version () : unit =
23+
BaseEnv.var_define
24+
~hide:false
25+
~dump:true
26+
~cli:BaseEnv.CLIWith
27+
~short_desc:(fun () -> "llvm version (e.g., 3.4)")
28+
"llvm_version"
29+
(fun () ->
30+
try
31+
ignore @@ OASISFileUtil.which ~ctxt "llvm-config";
32+
OASISExec.run_read_one_line ~ctxt "llvm-config" ["--version"]
33+
with Not_found -> "3.4") |>
34+
definition_end
35+
36+
let llvm_config () : unit =
37+
BaseEnv.var_define
38+
~hide:false
39+
~dump:true
40+
~cli:BaseEnv.CLIWith
41+
~short_desc:(fun () -> "llvm-config executable")
42+
"llvm_config"
43+
(fun () ->
44+
(* default macports if we're on mac os x *)
45+
let macosx = BaseEnv.var_get "system" = "macosx" in
46+
let vers = match BaseEnv.var_get "llvm_version" with
47+
| "" -> []
48+
| ver when macosx -> ["-mp-" ^ strip_patch ver; "-" ^ strip_patch ver]
49+
| ver -> ["-" ^ ver; "-" ^ strip_patch ver] in
50+
find_map vers ~f:(fun ver ->
51+
try Some (OASISFileUtil.which ~ctxt ("llvm-config" ^ ver))
52+
with Not_found -> None) |> function
53+
| Some path -> path
54+
| None -> raise Not_found) |>
55+
definition_end
56+
57+
let llvm_mainlib () : unit =
58+
BaseEnv.var_define
59+
~hide:true
60+
~dump:true
61+
~short_desc:(fun () -> "main LLVM library")
62+
"llvm_mainlib"
63+
(fun () -> "-lLLVM-"^BaseEnv.var_get "llvm_version") |>
64+
definition_end
65+
66+
67+
let llvm_lib () : unit =
68+
BaseEnv.var_define
69+
~hide:true
70+
~dump:true
71+
~short_desc:(fun () -> "LLVM library(ies) to link with")
72+
"llvm_lib"
73+
(fun () ->
74+
let llvm_static = BaseEnv.var_get "llvm_static" in
75+
let lib = if llvm_static = "true"
76+
then "llvm_libs"
77+
else "llvm_mainlib" in
78+
BaseEnv.var_get lib) |>
79+
definition_end
80+
81+
let () =
82+
define [
83+
llvm_version;
84+
llvm_config;
85+
llvm_mainlib;
86+
llvm "cxxflags";
87+
llvm "ldflags";
88+
llvm "cflags";
89+
llvm "libs";
90+
llvm_lib
91+
]

oasis/llvm.tags.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<plugins/llvm/llvm_*.cpp>: use_libllvm

oasis/objdump.setup.ml.in

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
31
let () =
42
add_variable ~doc:"A list (OCaml syntax) of supported targets" "objdump_targets"
53
~define:(function

oasis/piqi.ocamlbuild.ml.in

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
let nonempty = function (A s) -> String.length s <> 0 | _ -> true
2+
3+
(* the piqi support is rather fragile *)
4+
let piqic_rule () : unit =
5+
rule "piqic: piqi -> .ml & _ext.ml"
6+
~prods:["%_piqi.ml"; "%_piqi_ext.ml"]
7+
~deps:["%.piqi"]
8+
(fun env _ ->
9+
Cmd (S (List.filter nonempty [
10+
A (expand "${piqic}");
11+
A (expand "${piqic_flags}");
12+
A "-C";
13+
A "lib/bap_piqi";
14+
A "-I";
15+
A "../lib/bap_piqi";
16+
A (env "%.piqi");
17+
A"--multi-format"])));;
18+
19+
let () = Rules.add piqic_rule

oasis/piqi.setup.ml.in

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
let piqic () : unit =
2+
let chop str = try
3+
Filename.chop_extension str
4+
with _ -> str in
5+
let piqic_path = BaseCheck.prog_best "piqic_path" ["piqic-ocaml"; "piqic"] () in
6+
BaseEnv.var_define "piqic_flags" (fun () ->
7+
if chop (Filename.basename (BaseEnv.var_get "piqic")) = "piqic"
8+
then "ocaml"
9+
else "") |>
10+
definition_end;
11+
BaseEnv.var_define "piqic" (fun () ->
12+
if List.mem (BaseStandardVar.os_type ()) ["Cygwin"; "Win32"]
13+
then
14+
String.concat " "
15+
(OASISExec.run_read_output ~ctxt "cygpath" [piqic_path])
16+
else piqic_path) |>
17+
definition_end
18+
19+
20+
21+
22+
let () = define [piqic]

0 commit comments

Comments
 (0)