Move rules for module compilation in their own file

This commit is contained in:
Jeremie Dimino 2017-04-28 15:12:05 +01:00
parent a8c2dcc928
commit 416d4c6ead
7 changed files with 155 additions and 113 deletions

View File

@ -36,6 +36,9 @@ let default = make "DEFAULT"
let runtest = make "runtest"
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 =
[ default
; runtest

View File

@ -6,6 +6,8 @@ val default : dir:Path.t -> t
val runtest : 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 file : t -> Path.t

View File

@ -16,112 +16,6 @@ module Gen(P : Params) = struct
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 |
+-----------------------------------------------------------------+ *)
@ -203,8 +97,9 @@ module Gen(P : Params) = struct
String_map.fold modules ~init:[] ~f:(fun ~key:_ ~data:m acc ->
Module.cm_file m ~dir cm_kind :: acc)
in
SC.add_rule sctx (Build.paths deps >>>
Build.create_file (lib_cm_all lib ~dir cm_kind))
Alias.add_deps (SC.aliases sctx)
(Alias.lib_cm_all ~dir lib.name cm_kind)
deps
let expand_includes ~dir includes =
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;
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 ->
let flags = Ocaml_flags.default () in
build_module m
Module_compilation.build_module sctx m
~dynlink
~sandbox:alias_module_build_sandbox
~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;
(* CR-someday jdimino: this should probably say [~dynlink:false] *)
build_modules ~dynlink:true ~flags ~dir ~dep_graph ~modules ~requires
~alias_module:None;
Module_compilation.build_modules sctx ~dynlink:true ~flags ~dir ~dep_graph ~modules
~requires ~alias_module:None;
List.iter exes.names ~f:(fun name ->
List.iter Mode.all ~f:(fun mode ->

108
src/module_compilation.ml Normal file
View File

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

View File

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

View File

@ -3,6 +3,8 @@ open Build.O
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 =
List.map lines ~f:(fun line ->
match String.index line ':' with

View File

@ -2,6 +2,8 @@
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
library of the first name of a list of executables.
@ -13,7 +15,7 @@ val rules
-> item:string
-> modules:Module.t String_map.t
-> 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 *)
val names_to_top_closed_cm_files