Move rules for module compilation in their own file
This commit is contained in:
parent
a8c2dcc928
commit
416d4c6ead
|
@ -36,6 +36,9 @@ let default = make "DEFAULT"
|
||||||
let runtest = make "runtest"
|
let runtest = make "runtest"
|
||||||
let install = make "install"
|
let install = make "install"
|
||||||
|
|
||||||
|
let lib_cm_all ~dir lib_name cm_kind =
|
||||||
|
make (sprintf "%s%s-all" lib_name (Cm_kind.ext cm_kind)) ~dir
|
||||||
|
|
||||||
let recursive_aliases =
|
let recursive_aliases =
|
||||||
[ default
|
[ default
|
||||||
; runtest
|
; runtest
|
||||||
|
|
|
@ -6,6 +6,8 @@ val default : dir:Path.t -> t
|
||||||
val runtest : dir:Path.t -> t
|
val runtest : dir:Path.t -> t
|
||||||
val install : dir:Path.t -> t
|
val install : dir:Path.t -> t
|
||||||
|
|
||||||
|
val lib_cm_all : dir:Path.t -> string -> Cm_kind.t -> t
|
||||||
|
|
||||||
val dep : t -> ('a, 'a) Build.t
|
val dep : t -> ('a, 'a) Build.t
|
||||||
val file : t -> Path.t
|
val file : t -> Path.t
|
||||||
|
|
||||||
|
|
120
src/gen_rules.ml
120
src/gen_rules.ml
|
@ -16,112 +16,6 @@ module Gen(P : Params) = struct
|
||||||
|
|
||||||
let ctx = SC.context sctx
|
let ctx = SC.context sctx
|
||||||
|
|
||||||
(* +-----------------------------------------------------------------+
|
|
||||||
| ml/mli compilation |
|
|
||||||
+-----------------------------------------------------------------+ *)
|
|
||||||
|
|
||||||
let lib_cm_all ~dir (lib : Library.t) cm_kind =
|
|
||||||
Path.relative dir
|
|
||||||
(sprintf "%s%s-all" lib.name (Cm_kind.ext cm_kind))
|
|
||||||
|
|
||||||
let lib_dependencies (libs : Lib.t list) ~(cm_kind : Cm_kind.t) =
|
|
||||||
List.concat_map libs ~f:(function
|
|
||||||
| External _ -> []
|
|
||||||
| Internal (dir, lib) ->
|
|
||||||
match cm_kind with
|
|
||||||
| Cmi | Cmo ->
|
|
||||||
[lib_cm_all ~dir lib Cmi]
|
|
||||||
| Cmx ->
|
|
||||||
[lib_cm_all ~dir lib Cmx])
|
|
||||||
|
|
||||||
let build_cm ?sandbox ~dynlink ~flags ~cm_kind ~dep_graph ~requires
|
|
||||||
~(modules : Module.t String_map.t) ~dir ~alias_module (m : Module.t) =
|
|
||||||
Option.iter (Mode.of_cm_kind cm_kind |> Context.compiler ctx) ~f:(fun compiler ->
|
|
||||||
Option.iter (Module.cm_source ~dir m cm_kind) ~f:(fun src ->
|
|
||||||
let ml_kind = Cm_kind.source cm_kind in
|
|
||||||
let dst = Module.cm_file m ~dir cm_kind in
|
|
||||||
let extra_args, extra_deps, extra_targets =
|
|
||||||
match cm_kind, m.intf with
|
|
||||||
(* If there is no mli, [ocamlY -c file.ml] produces both the
|
|
||||||
.cmY and .cmi. We choose to use ocamlc to produce the cmi
|
|
||||||
and to produce the cmx we have to wait to avoid race
|
|
||||||
conditions. *)
|
|
||||||
| Cmo, None -> [], [], [Module.cm_file m ~dir Cmi]
|
|
||||||
| Cmx, None ->
|
|
||||||
(* Change [-intf-suffix] so that the compiler thinks the
|
|
||||||
cmi exists and reads it instead of re-creating it, which
|
|
||||||
could create a race condition. *)
|
|
||||||
([ "-intf-suffix"
|
|
||||||
; Filename.extension m.impl.name
|
|
||||||
],
|
|
||||||
[Module.cm_file m ~dir Cmi], [])
|
|
||||||
| Cmi, None -> assert false
|
|
||||||
| Cmi, Some _ -> [], [], []
|
|
||||||
(* We need the .cmi to build either the .cmo or .cmx *)
|
|
||||||
| (Cmo | Cmx), Some _ -> [], [Module.cm_file m ~dir Cmi], []
|
|
||||||
in
|
|
||||||
let extra_targets =
|
|
||||||
match cm_kind with
|
|
||||||
| Cmx -> Path.relative dir (m.obj_name ^ ctx.ext_obj) :: extra_targets
|
|
||||||
| Cmi | Cmo -> extra_targets
|
|
||||||
in
|
|
||||||
let dep_graph = Ml_kind.Dict.get dep_graph ml_kind in
|
|
||||||
let other_cm_files =
|
|
||||||
Build.dyn_paths
|
|
||||||
(dep_graph >>^ (fun dep_graph ->
|
|
||||||
let deps =
|
|
||||||
List.map (Utils.find_deps ~dir dep_graph m.name)
|
|
||||||
~f:(Utils.find_module ~dir modules)
|
|
||||||
in
|
|
||||||
List.concat_map
|
|
||||||
deps
|
|
||||||
~f:(fun m ->
|
|
||||||
match cm_kind with
|
|
||||||
| Cmi | Cmo -> [Module.cm_file m ~dir Cmi]
|
|
||||||
| Cmx -> [Module.cm_file m ~dir Cmi; Module.cm_file m ~dir Cmx])))
|
|
||||||
in
|
|
||||||
let extra_targets, cmt_args =
|
|
||||||
match cm_kind with
|
|
||||||
| Cmx -> (extra_targets, Arg_spec.S [])
|
|
||||||
| Cmi | Cmo ->
|
|
||||||
let fn = Option.value_exn (Module.cmt_file m ~dir ml_kind) in
|
|
||||||
(fn :: extra_targets, A "-bin-annot")
|
|
||||||
in
|
|
||||||
SC.add_rule sctx ?sandbox
|
|
||||||
(Build.paths extra_deps >>>
|
|
||||||
other_cm_files >>>
|
|
||||||
requires >>>
|
|
||||||
Build.dyn_paths (Build.arr (lib_dependencies ~cm_kind)) >>>
|
|
||||||
Build.run ~context:ctx (Dep compiler)
|
|
||||||
~extra_targets
|
|
||||||
[ Ocaml_flags.get_for_cm flags ~cm_kind
|
|
||||||
; cmt_args
|
|
||||||
; Dyn Lib.include_flags
|
|
||||||
; As extra_args
|
|
||||||
; if dynlink || cm_kind <> Cmx then As [] else A "-nodynlink"
|
|
||||||
; A "-no-alias-deps"
|
|
||||||
; A "-I"; Path dir
|
|
||||||
; (match alias_module with
|
|
||||||
| None -> S []
|
|
||||||
| Some (m : Module.t) -> As ["-open"; m.name])
|
|
||||||
; A "-o"; Target dst
|
|
||||||
; A "-c"; Ml_kind.flag ml_kind; Dep src
|
|
||||||
])))
|
|
||||||
|
|
||||||
let build_module ?sandbox ~dynlink ~flags m ~dir ~dep_graph ~modules ~requires
|
|
||||||
~alias_module =
|
|
||||||
List.iter Cm_kind.all ~f:(fun cm_kind ->
|
|
||||||
build_cm ?sandbox ~dynlink ~flags ~dir ~dep_graph ~modules m ~cm_kind ~requires
|
|
||||||
~alias_module)
|
|
||||||
|
|
||||||
let build_modules ~dynlink ~flags ~dir ~dep_graph ~modules ~requires ~alias_module =
|
|
||||||
String_map.iter
|
|
||||||
(match alias_module with
|
|
||||||
| None -> modules
|
|
||||||
| Some (m : Module.t) -> String_map.remove m.name modules)
|
|
||||||
~f:(fun ~key:_ ~data:m ->
|
|
||||||
build_module m ~dynlink ~flags ~dir ~dep_graph ~modules ~requires ~alias_module)
|
|
||||||
|
|
||||||
(* +-----------------------------------------------------------------+
|
(* +-----------------------------------------------------------------+
|
||||||
| Interpretation of [modules] fields |
|
| Interpretation of [modules] fields |
|
||||||
+-----------------------------------------------------------------+ *)
|
+-----------------------------------------------------------------+ *)
|
||||||
|
@ -203,8 +97,9 @@ module Gen(P : Params) = struct
|
||||||
String_map.fold modules ~init:[] ~f:(fun ~key:_ ~data:m acc ->
|
String_map.fold modules ~init:[] ~f:(fun ~key:_ ~data:m acc ->
|
||||||
Module.cm_file m ~dir cm_kind :: acc)
|
Module.cm_file m ~dir cm_kind :: acc)
|
||||||
in
|
in
|
||||||
SC.add_rule sctx (Build.paths deps >>>
|
Alias.add_deps (SC.aliases sctx)
|
||||||
Build.create_file (lib_cm_all lib ~dir cm_kind))
|
(Alias.lib_cm_all ~dir lib.name cm_kind)
|
||||||
|
deps
|
||||||
|
|
||||||
let expand_includes ~dir includes =
|
let expand_includes ~dir includes =
|
||||||
Arg_spec.As (List.concat_map includes ~f:(fun s ->
|
Arg_spec.As (List.concat_map includes ~f:(fun s ->
|
||||||
|
@ -357,10 +252,11 @@ module Gen(P : Params) = struct
|
||||||
SC.Libs.add_select_rules sctx ~dir lib.buildable.libraries;
|
SC.Libs.add_select_rules sctx ~dir lib.buildable.libraries;
|
||||||
|
|
||||||
let dynlink = lib.dynlink in
|
let dynlink = lib.dynlink in
|
||||||
build_modules ~dynlink ~flags ~dir ~dep_graph ~modules ~requires ~alias_module;
|
Module_compilation.build_modules sctx
|
||||||
|
~dynlink ~flags ~dir ~dep_graph ~modules ~requires ~alias_module;
|
||||||
Option.iter alias_module ~f:(fun m ->
|
Option.iter alias_module ~f:(fun m ->
|
||||||
let flags = Ocaml_flags.default () in
|
let flags = Ocaml_flags.default () in
|
||||||
build_module m
|
Module_compilation.build_module sctx m
|
||||||
~dynlink
|
~dynlink
|
||||||
~sandbox:alias_module_build_sandbox
|
~sandbox:alias_module_build_sandbox
|
||||||
~flags:{ flags with common = flags.common @ ["-w"; "-49"] }
|
~flags:{ flags with common = flags.common @ ["-w"; "-49"] }
|
||||||
|
@ -533,8 +429,8 @@ module Gen(P : Params) = struct
|
||||||
SC.Libs.add_select_rules sctx ~dir exes.buildable.libraries;
|
SC.Libs.add_select_rules sctx ~dir exes.buildable.libraries;
|
||||||
|
|
||||||
(* CR-someday jdimino: this should probably say [~dynlink:false] *)
|
(* CR-someday jdimino: this should probably say [~dynlink:false] *)
|
||||||
build_modules ~dynlink:true ~flags ~dir ~dep_graph ~modules ~requires
|
Module_compilation.build_modules sctx ~dynlink:true ~flags ~dir ~dep_graph ~modules
|
||||||
~alias_module:None;
|
~requires ~alias_module:None;
|
||||||
|
|
||||||
List.iter exes.names ~f:(fun name ->
|
List.iter exes.names ~f:(fun name ->
|
||||||
List.iter Mode.all ~f:(fun mode ->
|
List.iter Mode.all ~f:(fun mode ->
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
open Import
|
||||||
|
open Jbuild_types
|
||||||
|
open Build.O
|
||||||
|
|
||||||
|
module SC = Super_context
|
||||||
|
|
||||||
|
let lib_cm_all ~dir (lib : Library.t) cm_kind =
|
||||||
|
Alias.file (Alias.lib_cm_all ~dir lib.name cm_kind)
|
||||||
|
|
||||||
|
let lib_dependencies (libs : Lib.t list) ~(cm_kind : Cm_kind.t) =
|
||||||
|
List.concat_map libs ~f:(function
|
||||||
|
| External _ -> []
|
||||||
|
| Internal (dir, lib) ->
|
||||||
|
match cm_kind with
|
||||||
|
| Cmi | Cmo ->
|
||||||
|
[lib_cm_all ~dir lib Cmi]
|
||||||
|
| Cmx ->
|
||||||
|
[lib_cm_all ~dir lib Cmx])
|
||||||
|
|
||||||
|
let build_cm sctx ?sandbox ~dynlink ~flags ~cm_kind ~(dep_graph:Ocamldep.dep_graph)
|
||||||
|
~requires ~(modules : Module.t String_map.t) ~dir ~alias_module (m : Module.t) =
|
||||||
|
let ctx = SC.context sctx in
|
||||||
|
Option.iter (Mode.of_cm_kind cm_kind |> Context.compiler ctx) ~f:(fun compiler ->
|
||||||
|
Option.iter (Module.cm_source ~dir m cm_kind) ~f:(fun src ->
|
||||||
|
let ml_kind = Cm_kind.source cm_kind in
|
||||||
|
let dst = Module.cm_file m ~dir cm_kind in
|
||||||
|
let extra_args, extra_deps, extra_targets =
|
||||||
|
match cm_kind, m.intf with
|
||||||
|
(* If there is no mli, [ocamlY -c file.ml] produces both the
|
||||||
|
.cmY and .cmi. We choose to use ocamlc to produce the cmi
|
||||||
|
and to produce the cmx we have to wait to avoid race
|
||||||
|
conditions. *)
|
||||||
|
| Cmo, None -> [], [], [Module.cm_file m ~dir Cmi]
|
||||||
|
| Cmx, None ->
|
||||||
|
(* Change [-intf-suffix] so that the compiler thinks the
|
||||||
|
cmi exists and reads it instead of re-creating it, which
|
||||||
|
could create a race condition. *)
|
||||||
|
([ "-intf-suffix"
|
||||||
|
; Filename.extension m.impl.name
|
||||||
|
],
|
||||||
|
[Module.cm_file m ~dir Cmi], [])
|
||||||
|
| Cmi, None -> assert false
|
||||||
|
| Cmi, Some _ -> [], [], []
|
||||||
|
(* We need the .cmi to build either the .cmo or .cmx *)
|
||||||
|
| (Cmo | Cmx), Some _ -> [], [Module.cm_file m ~dir Cmi], []
|
||||||
|
in
|
||||||
|
let extra_targets =
|
||||||
|
match cm_kind with
|
||||||
|
| Cmx -> Path.relative dir (m.obj_name ^ ctx.ext_obj) :: extra_targets
|
||||||
|
| Cmi | Cmo -> extra_targets
|
||||||
|
in
|
||||||
|
let dep_graph = Ml_kind.Dict.get dep_graph ml_kind in
|
||||||
|
let other_cm_files =
|
||||||
|
Build.dyn_paths
|
||||||
|
(dep_graph >>^ (fun dep_graph ->
|
||||||
|
let deps =
|
||||||
|
List.map (Utils.find_deps ~dir dep_graph m.name)
|
||||||
|
~f:(Utils.find_module ~dir modules)
|
||||||
|
in
|
||||||
|
List.concat_map
|
||||||
|
deps
|
||||||
|
~f:(fun m ->
|
||||||
|
match cm_kind with
|
||||||
|
| Cmi | Cmo -> [Module.cm_file m ~dir Cmi]
|
||||||
|
| Cmx -> [Module.cm_file m ~dir Cmi; Module.cm_file m ~dir Cmx])))
|
||||||
|
in
|
||||||
|
let extra_targets, cmt_args =
|
||||||
|
match cm_kind with
|
||||||
|
| Cmx -> (extra_targets, Arg_spec.S [])
|
||||||
|
| Cmi | Cmo ->
|
||||||
|
let fn = Option.value_exn (Module.cmt_file m ~dir ml_kind) in
|
||||||
|
(fn :: extra_targets, A "-bin-annot")
|
||||||
|
in
|
||||||
|
SC.add_rule sctx ?sandbox
|
||||||
|
(Build.paths extra_deps >>>
|
||||||
|
other_cm_files >>>
|
||||||
|
requires >>>
|
||||||
|
Build.dyn_paths (Build.arr (lib_dependencies ~cm_kind)) >>>
|
||||||
|
Build.run ~context:ctx (Dep compiler)
|
||||||
|
~extra_targets
|
||||||
|
[ Ocaml_flags.get_for_cm flags ~cm_kind
|
||||||
|
; cmt_args
|
||||||
|
; Dyn Lib.include_flags
|
||||||
|
; As extra_args
|
||||||
|
; if dynlink || cm_kind <> Cmx then As [] else A "-nodynlink"
|
||||||
|
; A "-no-alias-deps"
|
||||||
|
; A "-I"; Path dir
|
||||||
|
; (match alias_module with
|
||||||
|
| None -> S []
|
||||||
|
| Some (m : Module.t) -> As ["-open"; m.name])
|
||||||
|
; A "-o"; Target dst
|
||||||
|
; A "-c"; Ml_kind.flag ml_kind; Dep src
|
||||||
|
])))
|
||||||
|
|
||||||
|
let build_module sctx ?sandbox ~dynlink ~flags m ~dir ~dep_graph ~modules ~requires
|
||||||
|
~alias_module =
|
||||||
|
List.iter Cm_kind.all ~f:(fun cm_kind ->
|
||||||
|
build_cm sctx ?sandbox ~dynlink ~flags ~dir ~dep_graph ~modules m ~cm_kind ~requires
|
||||||
|
~alias_module)
|
||||||
|
|
||||||
|
let build_modules sctx ~dynlink ~flags ~dir ~dep_graph ~modules ~requires ~alias_module =
|
||||||
|
String_map.iter
|
||||||
|
(match alias_module with
|
||||||
|
| None -> modules
|
||||||
|
| Some (m : Module.t) -> String_map.remove m.name modules)
|
||||||
|
~f:(fun ~key:_ ~data:m ->
|
||||||
|
build_module sctx m ~dynlink ~flags ~dir ~dep_graph ~modules ~requires
|
||||||
|
~alias_module)
|
|
@ -0,0 +1,29 @@
|
||||||
|
(** OCaml module compilation *)
|
||||||
|
|
||||||
|
open Import
|
||||||
|
|
||||||
|
(** Setup rules to build a single module *)
|
||||||
|
val build_module
|
||||||
|
: Super_context.t
|
||||||
|
-> ?sandbox:bool
|
||||||
|
-> dynlink:bool
|
||||||
|
-> flags:Ocaml_flags.t
|
||||||
|
-> Module.t
|
||||||
|
-> dir:Path.t
|
||||||
|
-> dep_graph:Ocamldep.dep_graph
|
||||||
|
-> modules:Module.t String_map.t
|
||||||
|
-> requires:(unit, Lib.t list) Build.t
|
||||||
|
-> alias_module:Module.t option
|
||||||
|
-> unit
|
||||||
|
|
||||||
|
(** Setup rules to build all of [modules] *)
|
||||||
|
val build_modules
|
||||||
|
: Super_context.t
|
||||||
|
-> dynlink:bool
|
||||||
|
-> flags:Ocaml_flags.t
|
||||||
|
-> dir:Path.t
|
||||||
|
-> dep_graph:Ocamldep.dep_graph
|
||||||
|
-> modules:Module.t String_map.t
|
||||||
|
-> requires:(unit, Lib.t list) Build.t
|
||||||
|
-> alias_module:Module.t option
|
||||||
|
-> unit
|
|
@ -3,6 +3,8 @@ open Build.O
|
||||||
|
|
||||||
module SC = Super_context
|
module SC = Super_context
|
||||||
|
|
||||||
|
type dep_graph = (unit, string list String_map.t) Build.t Ml_kind.Dict.t
|
||||||
|
|
||||||
let parse_deps ~dir lines ~modules ~alias_module =
|
let parse_deps ~dir lines ~modules ~alias_module =
|
||||||
List.map lines ~f:(fun line ->
|
List.map lines ~f:(fun line ->
|
||||||
match String.index line ':' with
|
match String.index line ':' with
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
open Import
|
open Import
|
||||||
|
|
||||||
|
type dep_graph = (unit, string list String_map.t) Build.t Ml_kind.Dict.t
|
||||||
|
|
||||||
(** Generate ocamldep rules for the given modules. [item] is either the internal name of a
|
(** Generate ocamldep rules for the given modules. [item] is either the internal name of a
|
||||||
library of the first name of a list of executables.
|
library of the first name of a list of executables.
|
||||||
|
|
||||||
|
@ -13,7 +15,7 @@ val rules
|
||||||
-> item:string
|
-> item:string
|
||||||
-> modules:Module.t String_map.t
|
-> modules:Module.t String_map.t
|
||||||
-> alias_module:Module.t option
|
-> alias_module:Module.t option
|
||||||
-> (unit, string list String_map.t) Build.t Ml_kind.Dict.t
|
-> dep_graph
|
||||||
|
|
||||||
(** Close and convert a list of module names to a list of .cm file names *)
|
(** Close and convert a list of module names to a list of .cm file names *)
|
||||||
val names_to_top_closed_cm_files
|
val names_to_top_closed_cm_files
|
||||||
|
|
Loading…
Reference in New Issue