@@ -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