Skip to content

Commit 88a1373

Browse files
authored
Merge branch 'master' into watch-mode
2 parents 8f05ef5 + 166dd06 commit 88a1373

1 file changed

Lines changed: 167 additions & 165 deletions

File tree

src/lib_rules.ml

Lines changed: 167 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,14 @@ module Gen (P : Install_rules.Params) = struct
1717
| Library stuff |
1818
+-----------------------------------------------------------------+ *)
1919

20-
let msvc_hack_cclibs cclibs =
21-
let f lib =
22-
if String.is_prefix lib ~prefix:"-l" then
23-
String.sub lib ~pos:2 ~len:(String.length lib - 2) ^ ".lib"
24-
else
25-
lib
26-
in
27-
let cclibs = List.map cclibs ~f in
28-
let f lib =
29-
if String.is_prefix lib ~prefix:"-l" then
30-
String.sub lib ~pos:2 ~len:(String.length lib - 2)
31-
else
32-
lib
33-
in
34-
List.map cclibs ~f
20+
let msvc_hack_cclibs =
21+
List.map ~f:(fun lib ->
22+
let lib =
23+
match String.drop_prefix lib ~prefix:"-l" with
24+
| None -> lib
25+
| Some l -> l ^ ".lib"
26+
in
27+
Option.value ~default:lib (String.drop_prefix ~prefix:"-l" lib))
3528

3629
let build_lib (lib : Library.t) ~scope ~flags ~dir ~obj_dir ~mode
3730
~top_sorted_modules ~modules =
@@ -93,6 +86,39 @@ module Gen (P : Install_rules.Params) = struct
9386
| Native -> [Library.archive lib ~dir ~ext:ctx.ext_lib])
9487
]))
9588

89+
(* If the compiler reads the cmi for module alias even with
90+
[-w -49 -no-alias-deps], we must sandbox the build of the
91+
alias module since the modules it references are built after. *)
92+
let alias_module_build_sandbox =
93+
Ocaml_version.always_reads_alias_cmi ctx.version
94+
95+
let build_alias_module (m : Module.t) ~main_module_name ~modules ~cctx
96+
~dynlink ~js_of_ocaml =
97+
let file =
98+
match m.impl with
99+
| Some f -> f
100+
| None -> Option.value_exn m.intf
101+
in
102+
SC.add_rule sctx
103+
(Build.return
104+
(Module.Name.Map.values (Module.Name.Map.remove modules m.name)
105+
|> List.map ~f:(fun (m : Module.t) ->
106+
sprintf "(** @canonical %s.%s *)\n\
107+
module %s = %s\n"
108+
(Module.Name.to_string main_module_name)
109+
(Module.Name.to_string m.name)
110+
(Module.Name.to_string m.name)
111+
(Module.Name.to_string (Module.real_unit_name m))
112+
)
113+
|> String.concat ~sep:"\n")
114+
>>> Build.write_file_dyn file.path);
115+
let cctx = Compilation_context.for_alias_module cctx in
116+
Module_compilation.build_module cctx m
117+
~js_of_ocaml
118+
~dynlink
119+
~sandbox:alias_module_build_sandbox
120+
~dep_graphs:(Ocamldep.Dep_graphs.dummy m)
121+
96122
let build_c_file (lib : Library.t) ~scope ~dir ~includes (src, dst) =
97123
SC.add_rule sctx
98124
(SC.expand_and_eval_set sctx ~scope ~dir lib.c_flags
@@ -137,11 +163,124 @@ module Gen (P : Install_rules.Params) = struct
137163
]));
138164
dst
139165

140-
(* If the compiler reads the cmi for module alias even with
141-
[-w -49 -no-alias-deps], we must sandbox the build of the
142-
alias module since the modules it references are built after. *)
143-
let alias_module_build_sandbox =
144-
Ocaml_version.always_reads_alias_cmi ctx.version
166+
let ocamlmklib (lib : Library.t) ~dir ~scope ~o_files ~sandbox ~custom
167+
~targets =
168+
SC.add_rule sctx ~sandbox
169+
(SC.expand_and_eval_set sctx ~scope ~dir
170+
lib.c_library_flags ~standard:(Build.return [])
171+
>>>
172+
Build.run ~context:ctx
173+
(Ok ctx.ocamlmklib)
174+
[ As (Utils.g ())
175+
; if custom then A "-custom" else As []
176+
; A "-o"
177+
; Path (Path.relative dir (sprintf "%s_stubs" lib.name))
178+
; Deps o_files
179+
; Dyn (fun cclibs ->
180+
(* https://github.com/ocaml/dune/issues/119 *)
181+
if ctx.ccomp_type = "msvc" then
182+
let cclibs = msvc_hack_cclibs cclibs in
183+
Arg_spec.quote_args "-ldopt" cclibs
184+
else
185+
As cclibs
186+
)
187+
; Hidden_targets targets
188+
])
189+
190+
let build_self_stubs lib ~scope ~dir ~o_files =
191+
let static = Library.stubs_archive lib ~dir ~ext_lib:ctx.ext_lib in
192+
let dynamic = Library.dll lib ~dir ~ext_dll:ctx.ext_dll in
193+
let modes =
194+
Mode_conf.Set.eval lib.modes
195+
~has_native:(Option.is_some ctx.ocamlopt) in
196+
let ocamlmklib = ocamlmklib lib ~scope ~dir ~o_files in
197+
if modes.native &&
198+
modes.byte &&
199+
lib.dynlink
200+
then begin
201+
(* If we build for both modes and support dynlink, use a
202+
single invocation to build both the static and dynamic
203+
libraries *)
204+
ocamlmklib ~sandbox:false ~custom:false ~targets:[static; dynamic]
205+
end else begin
206+
ocamlmklib ~sandbox:false ~custom:true ~targets:[static];
207+
(* We can't tell ocamlmklib to build only the dll, so we
208+
sandbox the action to avoid overriding the static archive *)
209+
ocamlmklib ~sandbox:true ~custom:false ~targets:[dynamic]
210+
end
211+
212+
let build_stubs lib ~dir ~scope ~requires ~dir_contents =
213+
let all_dirs = Dir_contents.dirs dir_contents in
214+
let h_files =
215+
List.fold_left all_dirs ~init:[] ~f:(fun acc dc ->
216+
String.Set.fold (Dir_contents.text_files dc) ~init:acc
217+
~f:(fun fn acc ->
218+
if String.is_suffix fn ~suffix:".h" then
219+
Path.relative (Dir_contents.dir dc) fn :: acc
220+
else
221+
acc))
222+
in
223+
let all_dirs = Path.Set.of_list (List.map all_dirs ~f:Dir_contents.dir) in
224+
let resolve_name ~ext (loc, fn) =
225+
let p = Path.relative dir (fn ^ ext) in
226+
if not (match Path.parent p with
227+
| None -> false
228+
| Some p -> Path.Set.mem all_dirs p) then
229+
Loc.fail loc
230+
"File %a is not part of the current directory group. \
231+
This is not allowed."
232+
Path.pp (Path.drop_optional_build_context p)
233+
;
234+
(p, Path.relative dir (fn ^ ctx.ext_obj))
235+
in
236+
let o_files =
237+
let includes =
238+
Arg_spec.S
239+
[ Hidden_deps h_files
240+
; Arg_spec.of_result_map requires ~f:(fun libs ->
241+
S [ Lib.L.c_include_flags libs ~stdlib_dir:ctx.stdlib_dir
242+
; Hidden_deps (SC.Libs.file_deps sctx libs ~ext:".h")
243+
])
244+
]
245+
in
246+
List.map lib.c_names ~f:(fun name ->
247+
build_c_file lib ~scope ~dir ~includes (resolve_name name ~ext:".c")
248+
) @ List.map lib.cxx_names ~f:(fun name ->
249+
build_cxx_file lib ~scope ~dir ~includes (resolve_name name ~ext:".cpp")
250+
)
251+
in
252+
match lib.self_build_stubs_archive with
253+
| Some _ -> ()
254+
| None -> build_self_stubs lib ~dir ~scope ~o_files
255+
256+
let build_shared lib ~dir ~flags ~(ctx : Context.t) =
257+
Option.iter ctx.ocamlopt ~f:(fun ocamlopt ->
258+
let src = Library.archive lib ~dir ~ext:(Mode.compiled_lib_ext Native) in
259+
let dst = Library.archive lib ~dir ~ext:".cmxs" in
260+
let build =
261+
Build.dyn_paths (Build.arr (fun () ->
262+
[Library.archive lib ~dir ~ext:ctx.ext_lib]))
263+
>>>
264+
Ocaml_flags.get flags Native
265+
>>>
266+
Build.run ~context:ctx
267+
(Ok ocamlopt)
268+
[ Dyn (fun flags -> As flags)
269+
; A "-shared"; A "-linkall"
270+
; A "-I"; Path dir
271+
; A "-o"; Target dst
272+
; Dep src
273+
]
274+
in
275+
let build =
276+
if Library.has_stubs lib then
277+
Build.path (Library.stubs_archive ~dir lib ~ext_lib:ctx.ext_lib)
278+
>>>
279+
build
280+
else
281+
build
282+
in
283+
SC.add_rule sctx build)
145284

146285
let library_rules (lib : Library.t) ~dir_contents ~dir ~scope
147286
~compile_info ~dir_kind =
@@ -201,125 +340,16 @@ module Gen (P : Install_rules.Params) = struct
201340

202341
let dep_graphs = Ocamldep.rules cctx in
203342

204-
Option.iter alias_module ~f:(fun m ->
205-
let file =
206-
match m.impl with
207-
| Some f -> f
208-
| None -> Option.value_exn m.intf
209-
in
210-
SC.add_rule sctx
211-
(Build.return
212-
(Module.Name.Map.values (Module.Name.Map.remove modules m.name)
213-
|> List.map ~f:(fun (m : Module.t) ->
214-
sprintf "(** @canonical %s.%s *)\n\
215-
module %s = %s\n"
216-
(Module.Name.to_string main_module_name)
217-
(Module.Name.to_string m.name)
218-
(Module.Name.to_string m.name)
219-
(Module.Name.to_string (Module.real_unit_name m))
220-
)
221-
|> String.concat ~sep:"\n")
222-
>>> Build.write_file_dyn file.path));
223-
224-
225343
let dynlink = lib.dynlink in
226344
let js_of_ocaml = lib.buildable.js_of_ocaml in
227345
Module_compilation.build_modules cctx ~js_of_ocaml ~dynlink ~dep_graphs;
228-
Option.iter alias_module ~f:(fun m ->
229-
let cctx = Compilation_context.for_alias_module cctx in
230-
Module_compilation.build_module cctx m
231-
~js_of_ocaml
232-
~dynlink
233-
~sandbox:alias_module_build_sandbox
234-
~dep_graphs:(Ocamldep.Dep_graphs.dummy m));
235346

236-
if Library.has_stubs lib then begin
237-
let all_dirs = Dir_contents.dirs dir_contents in
238-
let h_files =
239-
List.fold_left all_dirs ~init:[] ~f:(fun acc dc ->
240-
String.Set.fold (Dir_contents.text_files dc) ~init:acc
241-
~f:(fun fn acc ->
242-
if String.is_suffix fn ~suffix:".h" then
243-
Path.relative (Dir_contents.dir dc) fn :: acc
244-
else
245-
acc))
246-
in
247-
let all_dirs = Path.Set.of_list (List.map all_dirs ~f:Dir_contents.dir) in
248-
let resolve_name ~ext (loc, fn) =
249-
let p = Path.relative dir (fn ^ ext) in
250-
if not (match Path.parent p with
251-
| None -> false
252-
| Some p -> Path.Set.mem all_dirs p) then
253-
Loc.fail loc
254-
"File %a is not part of the current directory group. \
255-
This is not allowed."
256-
Path.pp (Path.drop_optional_build_context p)
257-
;
258-
(p, Path.relative dir (fn ^ ctx.ext_obj))
259-
in
260-
let o_files =
261-
let includes =
262-
Arg_spec.S
263-
[ Hidden_deps h_files
264-
; Arg_spec.of_result_map requires ~f:(fun libs ->
265-
S [ Lib.L.c_include_flags libs ~stdlib_dir:ctx.stdlib_dir
266-
; Hidden_deps (SC.Libs.file_deps sctx libs ~ext:".h")
267-
])
268-
]
269-
in
270-
List.map lib.c_names ~f:(fun name ->
271-
build_c_file lib ~scope ~dir ~includes (resolve_name name ~ext:".c")
272-
) @ List.map lib.cxx_names ~f:(fun name ->
273-
build_cxx_file lib ~scope ~dir ~includes (resolve_name name ~ext:".cpp")
274-
)
275-
in
276-
match lib.self_build_stubs_archive with
277-
| Some _ -> ()
278-
| None ->
279-
let ocamlmklib ~sandbox ~custom ~targets =
280-
SC.add_rule sctx ~sandbox
281-
(SC.expand_and_eval_set sctx ~scope ~dir
282-
lib.c_library_flags ~standard:(Build.return [])
283-
>>>
284-
Build.run ~context:ctx
285-
(Ok ctx.ocamlmklib)
286-
[ As (Utils.g ())
287-
; if custom then A "-custom" else As []
288-
; A "-o"
289-
; Path (Path.relative dir (sprintf "%s_stubs" lib.name))
290-
; Deps o_files
291-
; Dyn (fun cclibs ->
292-
(* https://github.com/ocaml/dune/issues/119 *)
293-
if ctx.ccomp_type = "msvc" then
294-
let cclibs = msvc_hack_cclibs cclibs in
295-
Arg_spec.quote_args "-ldopt" cclibs
296-
else
297-
As cclibs
298-
)
299-
; Hidden_targets targets
300-
])
301-
in
302-
let static = Library.stubs_archive lib ~dir ~ext_lib:ctx.ext_lib in
303-
let dynamic = Library.dll lib ~dir ~ext_dll:ctx.ext_dll in
304-
let modes =
305-
Mode_conf.Set.eval lib.modes
306-
~has_native:(Option.is_some ctx.ocamlopt)
307-
in
308-
if modes.native &&
309-
modes.byte &&
310-
lib.dynlink
311-
then begin
312-
(* If we build for both modes and support dynlink, use a
313-
single invocation to build both the static and dynamic
314-
libraries *)
315-
ocamlmklib ~sandbox:false ~custom:false ~targets:[static; dynamic]
316-
end else begin
317-
ocamlmklib ~sandbox:false ~custom:true ~targets:[static];
318-
(* We can't tell ocamlmklib to build only the dll, so we
319-
sandbox the action to avoid overriding the static archive *)
320-
ocamlmklib ~sandbox:true ~custom:false ~targets:[dynamic]
321-
end
322-
end;
347+
Option.iter alias_module
348+
~f:(build_alias_module ~main_module_name ~modules ~cctx ~dynlink
349+
~js_of_ocaml);
350+
351+
if Library.has_stubs lib then
352+
build_stubs lib ~dir ~scope ~requires ~dir_contents;
323353

324354
List.iter Cm_kind.all ~f:(fun cm_kind ->
325355
let files =
@@ -353,38 +383,10 @@ module Gen (P : Install_rules.Params) = struct
353383
SC.add_rules sctx (
354384
let src = Library.archive lib ~dir ~ext:(Mode.compiled_lib_ext Mode.Byte) in
355385
let target = Path.extend_basename src ~suffix:".js" in
356-
Js_of_ocaml_rules.build_cm cctx
357-
~js_of_ocaml:lib.buildable.js_of_ocaml ~src ~target);
386+
Js_of_ocaml_rules.build_cm cctx ~js_of_ocaml ~src ~target);
358387

359388
if ctx.natdynlink_supported then
360-
Option.iter ctx.ocamlopt ~f:(fun ocamlopt ->
361-
let src = Library.archive lib ~dir ~ext:(Mode.compiled_lib_ext Native) in
362-
let dst = Library.archive lib ~dir ~ext:".cmxs" in
363-
let build =
364-
Build.dyn_paths (Build.arr (fun () ->
365-
[Library.archive lib ~dir ~ext:ctx.ext_lib]))
366-
>>>
367-
Ocaml_flags.get flags Native
368-
>>>
369-
Build.run ~context:ctx
370-
(Ok ocamlopt)
371-
[ Dyn (fun flags -> As flags)
372-
; A "-shared"; A "-linkall"
373-
; A "-I"; Path dir
374-
; A "-o"; Target dst
375-
; Dep src
376-
]
377-
in
378-
let build =
379-
if Library.has_stubs lib then
380-
Build.path (Library.stubs_archive ~dir lib ~ext_lib:ctx.ext_lib)
381-
>>>
382-
build
383-
else
384-
build
385-
in
386-
SC.add_rule sctx build
387-
);
389+
build_shared lib ~dir ~flags ~ctx;
388390

389391
Odoc.setup_library_odoc_rules lib ~requires ~modules ~dep_graphs ~scope;
390392

0 commit comments

Comments
 (0)