Merge branch 'master' into suffix-prefix-fast
This commit is contained in:
commit
6f3467ad96
|
@ -6,7 +6,7 @@ val create
|
||||||
: Context.t
|
: Context.t
|
||||||
-> public_libs:Lib.DB.t
|
-> public_libs:Lib.DB.t
|
||||||
-> 'a list
|
-> 'a list
|
||||||
-> f:('a -> Jbuild.Stanza.t list)
|
-> f:('a -> Stanza.t list)
|
||||||
-> t
|
-> t
|
||||||
|
|
||||||
(** A named artifact that is looked up in the PATH if not found in the tree
|
(** A named artifact that is looked up in the PATH if not found in the tree
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
open Import
|
||||||
|
|
||||||
|
module SC = Super_context
|
||||||
|
|
||||||
|
module Includes = struct
|
||||||
|
type t = string list Arg_spec.t Cm_kind.Dict.t
|
||||||
|
|
||||||
|
let make sctx ~requires : _ Cm_kind.Dict.t =
|
||||||
|
match requires with
|
||||||
|
| Error exn -> Cm_kind.Dict.make_all (Arg_spec.Dyn (fun _ -> raise exn))
|
||||||
|
| Ok libs ->
|
||||||
|
let iflags =
|
||||||
|
Lib.L.include_flags libs ~stdlib_dir:(SC.context sctx).stdlib_dir
|
||||||
|
in
|
||||||
|
let cmi_includes =
|
||||||
|
Arg_spec.S [ iflags
|
||||||
|
; Hidden_deps
|
||||||
|
(SC.Libs.file_deps sctx libs ~ext:".cmi")
|
||||||
|
]
|
||||||
|
in
|
||||||
|
let cmi_and_cmx_includes =
|
||||||
|
Arg_spec.S [ iflags
|
||||||
|
; Hidden_deps
|
||||||
|
(SC.Libs.file_deps sctx libs ~ext:".cmi-and-.cmx")
|
||||||
|
]
|
||||||
|
in
|
||||||
|
{ cmi = cmi_includes
|
||||||
|
; cmo = cmi_includes
|
||||||
|
; cmx = cmi_and_cmx_includes
|
||||||
|
}
|
||||||
|
|
||||||
|
let empty =
|
||||||
|
Cm_kind.Dict.make_all (Arg_spec.As [])
|
||||||
|
end
|
||||||
|
|
||||||
|
type t =
|
||||||
|
{ super_context : Super_context.t
|
||||||
|
; scope : Scope.t
|
||||||
|
; dir : Path.t
|
||||||
|
; obj_dir : Path.t
|
||||||
|
; modules : Module.t Module.Name.Map.t
|
||||||
|
; alias_module : Module.t option
|
||||||
|
; lib_interface_module : Module.t option
|
||||||
|
; flags : Ocaml_flags.t
|
||||||
|
; requires : Lib.t list Or_exn.t
|
||||||
|
; includes : Includes.t
|
||||||
|
; preprocessing : Preprocessing.t
|
||||||
|
}
|
||||||
|
|
||||||
|
let super_context t = t.super_context
|
||||||
|
let scope t = t.scope
|
||||||
|
let dir t = t.dir
|
||||||
|
let obj_dir t = t.obj_dir
|
||||||
|
let modules t = t.modules
|
||||||
|
let alias_module t = t.alias_module
|
||||||
|
let lib_interface_module t = t.lib_interface_module
|
||||||
|
let flags t = t.flags
|
||||||
|
let requires t = t.requires
|
||||||
|
let includes t = t.includes
|
||||||
|
let preprocessing t = t.preprocessing
|
||||||
|
|
||||||
|
let create ~super_context ~scope ~dir ?(obj_dir=dir) ~modules ?alias_module
|
||||||
|
?lib_interface_module ~flags ~requires
|
||||||
|
?(preprocessing=Preprocessing.dummy) () =
|
||||||
|
{ super_context
|
||||||
|
; scope
|
||||||
|
; dir
|
||||||
|
; obj_dir
|
||||||
|
; modules
|
||||||
|
; alias_module
|
||||||
|
; lib_interface_module
|
||||||
|
; flags
|
||||||
|
; requires
|
||||||
|
; includes = Includes.make super_context ~requires
|
||||||
|
; preprocessing
|
||||||
|
}
|
||||||
|
|
||||||
|
let for_alias_module t =
|
||||||
|
let flags = Ocaml_flags.default ~profile:(SC.profile t.super_context) in
|
||||||
|
{ t with
|
||||||
|
flags = Ocaml_flags.append_common flags ["-w"; "-49"]
|
||||||
|
; includes = Includes.empty
|
||||||
|
; alias_module = None
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
(** High-level API for compiling OCaml files *)
|
||||||
|
|
||||||
|
open Import
|
||||||
|
|
||||||
|
(** Represent a compilation context.
|
||||||
|
|
||||||
|
A compilation context contains all the necessary information to
|
||||||
|
preprocess and compile OCaml source files. Exactly one compilation
|
||||||
|
context is associated to each library, executable and executbales
|
||||||
|
stanza.
|
||||||
|
*)
|
||||||
|
type t
|
||||||
|
|
||||||
|
(** Create a compilation context. *)
|
||||||
|
val create
|
||||||
|
: super_context : Super_context.t
|
||||||
|
-> scope : Scope.t
|
||||||
|
-> dir : Path.t
|
||||||
|
-> ?obj_dir : Path.t
|
||||||
|
-> modules : Module.t Module.Name.Map.t
|
||||||
|
-> ?alias_module : Module.t
|
||||||
|
-> ?lib_interface_module : Module.t
|
||||||
|
-> flags : Ocaml_flags.t
|
||||||
|
-> requires : Lib.t list Or_exn.t
|
||||||
|
-> ?preprocessing : Preprocessing.t
|
||||||
|
-> unit
|
||||||
|
-> t
|
||||||
|
|
||||||
|
(** Return a compilation context suitable for compiling the alias module. *)
|
||||||
|
val for_alias_module : t -> t
|
||||||
|
|
||||||
|
val super_context : t -> Super_context.t
|
||||||
|
val scope : t -> Scope.t
|
||||||
|
val dir : t -> Path.t
|
||||||
|
val obj_dir : t -> Path.t
|
||||||
|
val modules : t -> Module.t Module.Name.Map.t
|
||||||
|
val alias_module : t -> Module.t option
|
||||||
|
val lib_interface_module : t -> Module.t option
|
||||||
|
val flags : t -> Ocaml_flags.t
|
||||||
|
val requires : t -> Lib.t list Or_exn.t
|
||||||
|
val includes : t -> string list Arg_spec.t Cm_kind.Dict.t
|
||||||
|
val preprocessing : t -> Preprocessing.t
|
53
src/exe.ml
53
src/exe.ml
|
@ -1,6 +1,7 @@
|
||||||
open Import
|
open Import
|
||||||
open Build.O
|
open Build.O
|
||||||
|
|
||||||
|
module CC = Compilation_context
|
||||||
module SC = Super_context
|
module SC = Super_context
|
||||||
|
|
||||||
module Program = struct
|
module Program = struct
|
||||||
|
@ -103,19 +104,18 @@ module Linkage = struct
|
||||||
end
|
end
|
||||||
|
|
||||||
let link_exe
|
let link_exe
|
||||||
~dir
|
|
||||||
~obj_dir
|
|
||||||
~scope
|
|
||||||
~requires
|
|
||||||
~name
|
~name
|
||||||
~(linkage:Linkage.t)
|
~(linkage:Linkage.t)
|
||||||
~top_sorted_modules
|
~top_sorted_modules
|
||||||
?(flags=Ocaml_flags.empty)
|
|
||||||
?(link_flags=Build.arr (fun _ -> []))
|
?(link_flags=Build.arr (fun _ -> []))
|
||||||
?(js_of_ocaml=Jbuild.Js_of_ocaml.default)
|
?(js_of_ocaml=Jbuild.Js_of_ocaml.default)
|
||||||
sctx
|
cctx
|
||||||
=
|
=
|
||||||
let ctx = SC.context sctx in
|
let sctx = CC.super_context cctx in
|
||||||
|
let ctx = SC.context sctx in
|
||||||
|
let dir = CC.dir cctx in
|
||||||
|
let obj_dir = CC.obj_dir cctx in
|
||||||
|
let requires = CC.requires cctx in
|
||||||
let mode = linkage.mode in
|
let mode = linkage.mode in
|
||||||
let exe = Path.relative dir (name ^ linkage.ext) in
|
let exe = Path.relative dir (name ^ linkage.ext) in
|
||||||
let compiler = Option.value_exn (Context.compiler ctx mode) in
|
let compiler = Option.value_exn (Context.compiler ctx mode) in
|
||||||
|
@ -139,7 +139,7 @@ let link_exe
|
||||||
SC.add_rule sctx
|
SC.add_rule sctx
|
||||||
(Build.fanout3
|
(Build.fanout3
|
||||||
(register_native_objs_deps modules_and_cm_files >>^ snd)
|
(register_native_objs_deps modules_and_cm_files >>^ snd)
|
||||||
(Ocaml_flags.get flags mode)
|
(Ocaml_flags.get (CC.flags cctx) mode)
|
||||||
link_flags
|
link_flags
|
||||||
>>>
|
>>>
|
||||||
Build.of_result_map requires ~f:(fun libs ->
|
Build.of_result_map requires ~f:(fun libs ->
|
||||||
|
@ -162,56 +162,39 @@ let link_exe
|
||||||
let cm_and_flags =
|
let cm_and_flags =
|
||||||
Build.fanout
|
Build.fanout
|
||||||
(modules_and_cm_files >>^ snd)
|
(modules_and_cm_files >>^ snd)
|
||||||
(SC.expand_and_eval_set sctx ~scope ~dir js_of_ocaml.flags
|
(SC.expand_and_eval_set sctx ~scope:(CC.scope cctx) ~dir
|
||||||
|
js_of_ocaml.flags
|
||||||
~standard:(Build.return (Js_of_ocaml_rules.standard sctx)))
|
~standard:(Build.return (Js_of_ocaml_rules.standard sctx)))
|
||||||
in
|
in
|
||||||
SC.add_rules sctx (List.map rules ~f:(fun r -> cm_and_flags >>> r))
|
SC.add_rules sctx (List.map rules ~f:(fun r -> cm_and_flags >>> r))
|
||||||
|
|
||||||
let build_and_link_many
|
let build_and_link_many
|
||||||
~dir ~obj_dir ~programs ~modules
|
~programs
|
||||||
~scope
|
|
||||||
~linkages
|
~linkages
|
||||||
?(requires=Ok [])
|
|
||||||
?already_used
|
?already_used
|
||||||
?(flags=Ocaml_flags.empty)
|
|
||||||
?link_flags
|
?link_flags
|
||||||
?(js_of_ocaml=Jbuild.Js_of_ocaml.default)
|
?(js_of_ocaml=Jbuild.Js_of_ocaml.default)
|
||||||
sctx
|
cctx
|
||||||
=
|
=
|
||||||
let modules =
|
let dep_graphs = Ocamldep.rules cctx ?already_used in
|
||||||
Module.Name.Map.map modules ~f:(Module.set_obj_name ~wrapper:None)
|
|
||||||
in
|
|
||||||
|
|
||||||
let dep_graphs =
|
|
||||||
Ocamldep.rules sctx ~dir ~modules ?already_used
|
|
||||||
~alias_module:None ~lib_interface_module:None
|
|
||||||
in
|
|
||||||
|
|
||||||
(* CR-someday jdimino: this should probably say [~dynlink:false] *)
|
(* CR-someday jdimino: this should probably say [~dynlink:false] *)
|
||||||
Module_compilation.build_modules sctx
|
Module_compilation.build_modules cctx ~js_of_ocaml ~dep_graphs;
|
||||||
~js_of_ocaml
|
|
||||||
~dynlink:true ~flags ~scope ~dir ~obj_dir ~dep_graphs ~modules
|
|
||||||
~requires ~alias_module:None;
|
|
||||||
|
|
||||||
List.iter programs ~f:(fun { Program.name; main_module_name } ->
|
List.iter programs ~f:(fun { Program.name; main_module_name } ->
|
||||||
let top_sorted_modules =
|
let top_sorted_modules =
|
||||||
let main = Option.value_exn
|
let main = Option.value_exn
|
||||||
(Module.Name.Map.find modules main_module_name) in
|
(Module.Name.Map.find (CC.modules cctx) main_module_name) in
|
||||||
Ocamldep.Dep_graph.top_closed_implementations dep_graphs.impl
|
Ocamldep.Dep_graph.top_closed_implementations dep_graphs.impl
|
||||||
[main]
|
[main]
|
||||||
in
|
in
|
||||||
List.iter linkages ~f:(fun linkage ->
|
List.iter linkages ~f:(fun linkage ->
|
||||||
link_exe sctx
|
link_exe cctx
|
||||||
~dir
|
|
||||||
~obj_dir
|
|
||||||
~scope
|
|
||||||
~requires
|
|
||||||
~name
|
~name
|
||||||
~linkage
|
~linkage
|
||||||
~top_sorted_modules
|
~top_sorted_modules
|
||||||
~js_of_ocaml
|
~js_of_ocaml
|
||||||
~flags
|
|
||||||
?link_flags))
|
?link_flags))
|
||||||
|
|
||||||
let build_and_link ~dir ~obj_dir ~program =
|
let build_and_link ~program =
|
||||||
build_and_link_many ~dir ~obj_dir ~programs:[program]
|
build_and_link_many ~programs:[program]
|
||||||
|
|
31
src/exe.mli
31
src/exe.mli
|
@ -1,7 +1,5 @@
|
||||||
(** Compilation and linking of executables *)
|
(** Compilation and linking of executables *)
|
||||||
|
|
||||||
open Import
|
|
||||||
|
|
||||||
module Program : sig
|
module Program : sig
|
||||||
type t =
|
type t =
|
||||||
{ name : string
|
{ name : string
|
||||||
|
@ -39,48 +37,31 @@ end
|
||||||
(** Build and link one or more executables *)
|
(** Build and link one or more executables *)
|
||||||
|
|
||||||
val build_and_link
|
val build_and_link
|
||||||
: dir:Path.t
|
: program:Program.t
|
||||||
-> obj_dir:Path.t
|
|
||||||
-> program:Program.t
|
|
||||||
-> modules:Module.t Module.Name.Map.t
|
|
||||||
-> scope:Scope.t
|
|
||||||
-> linkages:Linkage.t list
|
-> linkages:Linkage.t list
|
||||||
-> ?requires:Lib.t list Or_exn.t
|
|
||||||
-> ?already_used:Module.Name.Set.t
|
-> ?already_used:Module.Name.Set.t
|
||||||
-> ?flags:Ocaml_flags.t
|
|
||||||
-> ?link_flags:(unit, string list) Build.t
|
-> ?link_flags:(unit, string list) Build.t
|
||||||
-> ?js_of_ocaml:Jbuild.Js_of_ocaml.t
|
-> ?js_of_ocaml:Jbuild.Js_of_ocaml.t
|
||||||
-> Super_context.t
|
-> Compilation_context.t
|
||||||
-> unit
|
-> unit
|
||||||
|
|
||||||
val build_and_link_many
|
val build_and_link_many
|
||||||
: dir:Path.t
|
: programs:Program.t list
|
||||||
-> obj_dir:Path.t
|
|
||||||
-> programs:Program.t list
|
|
||||||
-> modules:Module.t Module.Name.Map.t
|
|
||||||
-> scope:Scope.t
|
|
||||||
-> linkages:Linkage.t list
|
-> linkages:Linkage.t list
|
||||||
-> ?requires:Lib.t list Or_exn.t
|
|
||||||
-> ?already_used:Module.Name.Set.t
|
-> ?already_used:Module.Name.Set.t
|
||||||
-> ?flags:Ocaml_flags.t
|
|
||||||
-> ?link_flags:(unit, string list) Build.t
|
-> ?link_flags:(unit, string list) Build.t
|
||||||
-> ?js_of_ocaml:Jbuild.Js_of_ocaml.t
|
-> ?js_of_ocaml:Jbuild.Js_of_ocaml.t
|
||||||
-> Super_context.t
|
-> Compilation_context.t
|
||||||
-> unit
|
-> unit
|
||||||
|
|
||||||
(** {1 Low-level functions} *)
|
(** {1 Low-level functions} *)
|
||||||
|
|
||||||
(** Link a single executable *)
|
(** Link a single executable *)
|
||||||
val link_exe
|
val link_exe
|
||||||
: dir:Path.t
|
: name:string
|
||||||
-> obj_dir:Path.t
|
|
||||||
-> scope:Scope.t
|
|
||||||
-> requires:Lib.t list Or_exn.t
|
|
||||||
-> name:string
|
|
||||||
-> linkage:Linkage.t
|
-> linkage:Linkage.t
|
||||||
-> top_sorted_modules:(unit, Module.t list) Build.t
|
-> top_sorted_modules:(unit, Module.t list) Build.t
|
||||||
-> ?flags:Ocaml_flags.t
|
|
||||||
-> ?link_flags:(unit, string list) Build.t
|
-> ?link_flags:(unit, string list) Build.t
|
||||||
-> ?js_of_ocaml:Jbuild.Js_of_ocaml.t
|
-> ?js_of_ocaml:Jbuild.Js_of_ocaml.t
|
||||||
-> Super_context.t
|
-> Compilation_context.t
|
||||||
-> unit
|
-> unit
|
||||||
|
|
195
src/gen_rules.ml
195
src/gen_rules.ml
|
@ -10,6 +10,7 @@ open! No_io
|
||||||
|
|
||||||
module Gen(P : Install_rules.Params) = struct
|
module Gen(P : Install_rules.Params) = struct
|
||||||
module Alias = Build_system.Alias
|
module Alias = Build_system.Alias
|
||||||
|
module CC = Compilation_context
|
||||||
module SC = Super_context
|
module SC = Super_context
|
||||||
module Odoc = Odoc.Gen(P)
|
module Odoc = Odoc.Gen(P)
|
||||||
|
|
||||||
|
@ -253,8 +254,7 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
List.concat_map stanzas ~f:(fun stanza ->
|
List.concat_map stanzas ~f:(fun stanza ->
|
||||||
match (stanza : Stanza.t) with
|
match (stanza : Stanza.t) with
|
||||||
| Menhir menhir ->
|
| Menhir menhir ->
|
||||||
Menhir_rules.gen_rules sctx ~dir ~scope menhir
|
Menhir_rules.targets menhir
|
||||||
|> List.map ~f:Path.basename
|
|
||||||
| Rule rule ->
|
| Rule rule ->
|
||||||
List.map (user_rule rule ~dir ~scope) ~f:Path.basename
|
List.map (user_rule rule ~dir ~scope) ~f:Path.basename
|
||||||
| Copy_files def ->
|
| Copy_files def ->
|
||||||
|
@ -267,8 +267,7 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
match (dep : Jbuild.Lib_dep.t) with
|
match (dep : Jbuild.Lib_dep.t) with
|
||||||
| Direct _ -> None
|
| Direct _ -> None
|
||||||
| Select s -> Some s.result_fn)
|
| Select s -> Some s.result_fn)
|
||||||
| Documentation _ | Alias _ | Provides _ | Install _
|
| _ -> [])
|
||||||
| Env _ -> [])
|
|
||||||
|> String.Set.of_list
|
|> String.Set.of_list
|
||||||
in
|
in
|
||||||
String.Set.union generated_files
|
String.Set.union generated_files
|
||||||
|
@ -550,14 +549,10 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
let flags = SC.ocaml_flags sctx ~scope ~dir lib.buildable in
|
let flags = SC.ocaml_flags sctx ~scope ~dir lib.buildable in
|
||||||
let { modules; main_module_name; alias_module } = modules_by_lib ~dir lib in
|
let { modules; main_module_name; alias_module } = modules_by_lib ~dir lib in
|
||||||
let source_modules = modules in
|
let source_modules = modules in
|
||||||
let already_used =
|
|
||||||
Modules_partitioner.acknowledge modules_partitioner
|
|
||||||
~loc:lib.buildable.loc ~modules
|
|
||||||
in
|
|
||||||
(* Preprocess before adding the alias module as it doesn't need
|
(* Preprocess before adding the alias module as it doesn't need
|
||||||
preprocessing *)
|
preprocessing *)
|
||||||
let modules =
|
let pp =
|
||||||
Preprocessing.pp_and_lint_modules sctx ~dir ~dep_kind ~modules ~scope
|
Preprocessing.make sctx ~dir ~dep_kind ~scope
|
||||||
~preprocess:lib.buildable.preprocess
|
~preprocess:lib.buildable.preprocess
|
||||||
~preprocessor_deps:
|
~preprocessor_deps:
|
||||||
(SC.Deps.interpret sctx ~scope ~dir
|
(SC.Deps.interpret sctx ~scope ~dir
|
||||||
|
@ -565,6 +560,7 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
~lint:lib.buildable.lint
|
~lint:lib.buildable.lint
|
||||||
~lib_name:(Some lib.name)
|
~lib_name:(Some lib.name)
|
||||||
in
|
in
|
||||||
|
let modules = Preprocessing.pp_modules pp modules in
|
||||||
|
|
||||||
let modules =
|
let modules =
|
||||||
match alias_module with
|
match alias_module with
|
||||||
|
@ -572,14 +568,31 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
| Some m -> Module.Name.Map.add modules m.name m
|
| Some m -> Module.Name.Map.add modules m.name m
|
||||||
in
|
in
|
||||||
|
|
||||||
let dep_graphs =
|
let lib_interface_module =
|
||||||
Ocamldep.rules sctx ~dir ~modules ~already_used ~alias_module
|
if lib.wrapped then
|
||||||
~lib_interface_module:(
|
Module.Name.Map.find modules main_module_name
|
||||||
if lib.wrapped then
|
else
|
||||||
Module.Name.Map.find modules main_module_name
|
None
|
||||||
else
|
|
||||||
None)
|
|
||||||
in
|
in
|
||||||
|
let cctx =
|
||||||
|
Compilation_context.create ()
|
||||||
|
~super_context:sctx
|
||||||
|
~scope
|
||||||
|
~dir
|
||||||
|
~obj_dir
|
||||||
|
~modules
|
||||||
|
?alias_module
|
||||||
|
?lib_interface_module
|
||||||
|
~flags
|
||||||
|
~requires
|
||||||
|
~preprocessing:pp
|
||||||
|
in
|
||||||
|
|
||||||
|
let already_used =
|
||||||
|
Modules_partitioner.acknowledge modules_partitioner cctx
|
||||||
|
~loc:lib.buildable.loc ~modules:source_modules
|
||||||
|
in
|
||||||
|
let dep_graphs = Ocamldep.rules cctx ~already_used in
|
||||||
|
|
||||||
Option.iter alias_module ~f:(fun m ->
|
Option.iter alias_module ~f:(fun m ->
|
||||||
let file =
|
let file =
|
||||||
|
@ -604,22 +617,14 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
|
|
||||||
let dynlink = lib.dynlink in
|
let dynlink = lib.dynlink in
|
||||||
let js_of_ocaml = lib.buildable.js_of_ocaml in
|
let js_of_ocaml = lib.buildable.js_of_ocaml in
|
||||||
Module_compilation.build_modules sctx
|
Module_compilation.build_modules cctx ~js_of_ocaml ~dynlink ~dep_graphs;
|
||||||
~js_of_ocaml ~dynlink ~flags ~scope ~dir ~obj_dir ~dep_graphs
|
|
||||||
~modules ~requires ~alias_module;
|
|
||||||
Option.iter alias_module ~f:(fun m ->
|
Option.iter alias_module ~f:(fun m ->
|
||||||
let flags = Ocaml_flags.default ~profile:(SC.profile sctx) in
|
let cctx = Compilation_context.for_alias_module cctx in
|
||||||
Module_compilation.build_module sctx m
|
Module_compilation.build_module cctx m
|
||||||
~js_of_ocaml
|
~js_of_ocaml
|
||||||
~dynlink
|
~dynlink
|
||||||
~sandbox:alias_module_build_sandbox
|
~sandbox:alias_module_build_sandbox
|
||||||
~flags:(Ocaml_flags.append_common flags ["-w"; "-49"])
|
~dep_graphs:(Ocamldep.Dep_graphs.dummy m));
|
||||||
~scope
|
|
||||||
~dir
|
|
||||||
~obj_dir
|
|
||||||
~dep_graphs:(Ocamldep.Dep_graphs.dummy m)
|
|
||||||
~includes:(Cm_kind.Dict.make_all (Arg_spec.As []))
|
|
||||||
~alias_module:None);
|
|
||||||
|
|
||||||
if Library.has_stubs lib then begin
|
if Library.has_stubs lib then begin
|
||||||
let h_files =
|
let h_files =
|
||||||
|
@ -799,32 +804,30 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
+-----------------------------------------------------------------+ *)
|
+-----------------------------------------------------------------+ *)
|
||||||
|
|
||||||
let executables_rules ~dir ~all_modules
|
let executables_rules ~dir ~all_modules
|
||||||
?modules_partitioner ~scope ~compile_info
|
~modules_partitioner ~scope ~compile_info
|
||||||
(exes : Executables.t) =
|
(exes : Executables.t) =
|
||||||
let requires = Lib.Compile.requires compile_info in
|
let requires = Lib.Compile.requires compile_info in
|
||||||
let modules =
|
let modules =
|
||||||
parse_modules ~all_modules ~buildable:exes.buildable
|
parse_modules ~all_modules ~buildable:exes.buildable
|
||||||
in
|
in
|
||||||
let already_used =
|
|
||||||
match modules_partitioner with
|
|
||||||
| None -> Module.Name.Set.empty
|
|
||||||
| Some mp ->
|
|
||||||
Modules_partitioner.acknowledge mp
|
|
||||||
~loc:exes.buildable.loc ~modules
|
|
||||||
in
|
|
||||||
|
|
||||||
let modules =
|
let preprocessor_deps =
|
||||||
let preprocessor_deps =
|
SC.Deps.interpret sctx exes.buildable.preprocessor_deps
|
||||||
SC.Deps.interpret sctx exes.buildable.preprocessor_deps
|
~scope ~dir
|
||||||
~scope ~dir
|
in
|
||||||
in
|
let pp =
|
||||||
Preprocessing.pp_and_lint_modules sctx ~dir ~dep_kind:Required ~modules
|
Preprocessing.make sctx ~dir ~dep_kind:Required
|
||||||
~scope
|
~scope
|
||||||
~preprocess:exes.buildable.preprocess
|
~preprocess:exes.buildable.preprocess
|
||||||
~preprocessor_deps
|
~preprocessor_deps
|
||||||
~lint:exes.buildable.lint
|
~lint:exes.buildable.lint
|
||||||
~lib_name:None
|
~lib_name:None
|
||||||
in
|
in
|
||||||
|
let modules =
|
||||||
|
Module.Name.Map.map modules ~f:(fun m ->
|
||||||
|
Preprocessing.pp_module_as pp m.name m
|
||||||
|
|> Module.set_obj_name ~wrapper:None)
|
||||||
|
in
|
||||||
|
|
||||||
let programs =
|
let programs =
|
||||||
List.map exes.names ~f:(fun (loc, name) ->
|
List.map exes.names ~f:(fun (loc, name) ->
|
||||||
|
@ -873,16 +876,27 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
let obj_dir =
|
let obj_dir =
|
||||||
Utils.executable_object_directory ~dir (List.hd programs).name
|
Utils.executable_object_directory ~dir (List.hd programs).name
|
||||||
in
|
in
|
||||||
Exe.build_and_link_many sctx
|
|
||||||
~dir
|
let cctx =
|
||||||
~obj_dir
|
Compilation_context.create ()
|
||||||
|
~super_context:sctx
|
||||||
|
~scope
|
||||||
|
~dir
|
||||||
|
~obj_dir
|
||||||
|
~modules
|
||||||
|
~flags
|
||||||
|
~requires
|
||||||
|
~preprocessing:pp
|
||||||
|
in
|
||||||
|
let already_used =
|
||||||
|
Modules_partitioner.acknowledge modules_partitioner cctx
|
||||||
|
~loc:exes.buildable.loc ~modules
|
||||||
|
in
|
||||||
|
|
||||||
|
Exe.build_and_link_many cctx
|
||||||
~programs
|
~programs
|
||||||
~modules
|
|
||||||
~already_used
|
~already_used
|
||||||
~scope
|
|
||||||
~linkages
|
~linkages
|
||||||
~requires
|
|
||||||
~flags
|
|
||||||
~link_flags
|
~link_flags
|
||||||
~js_of_ocaml:exes.buildable.js_of_ocaml;
|
~js_of_ocaml:exes.buildable.js_of_ocaml;
|
||||||
|
|
||||||
|
@ -893,7 +907,7 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
~objs_dirs:(Path.Set.singleton obj_dir)
|
~objs_dirs:(Path.Set.singleton obj_dir)
|
||||||
|
|
||||||
let executables_rules ~dir ~all_modules
|
let executables_rules ~dir ~all_modules
|
||||||
?modules_partitioner ~scope (exes : Executables.t) =
|
~modules_partitioner ~scope (exes : Executables.t) =
|
||||||
let compile_info =
|
let compile_info =
|
||||||
Lib.DB.resolve_user_written_deps (Scope.libs scope)
|
Lib.DB.resolve_user_written_deps (Scope.libs scope)
|
||||||
exes.buildable.libraries
|
exes.buildable.libraries
|
||||||
|
@ -904,7 +918,7 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
SC.Libs.with_lib_deps sctx compile_info ~dir
|
SC.Libs.with_lib_deps sctx compile_info ~dir
|
||||||
~f:(fun () ->
|
~f:(fun () ->
|
||||||
executables_rules exes ~dir ~all_modules
|
executables_rules exes ~dir ~all_modules
|
||||||
?modules_partitioner ~scope ~compile_info)
|
~modules_partitioner ~scope ~compile_info)
|
||||||
|
|
||||||
(* +-----------------------------------------------------------------+
|
(* +-----------------------------------------------------------------+
|
||||||
| Aliases |
|
| Aliases |
|
||||||
|
@ -951,39 +965,56 @@ module Gen(P : Install_rules.Params) = struct
|
||||||
(* This interprets "rule" and "copy_files" stanzas. *)
|
(* This interprets "rule" and "copy_files" stanzas. *)
|
||||||
let files = text_files ~dir:ctx_dir in
|
let files = text_files ~dir:ctx_dir in
|
||||||
let all_modules = modules_by_dir ~dir:ctx_dir in
|
let all_modules = modules_by_dir ~dir:ctx_dir in
|
||||||
let modules_partitioner = Modules_partitioner.create ~all_modules in
|
let modules_partitioner = Modules_partitioner.create () in
|
||||||
List.filter_map stanzas ~f:(fun stanza ->
|
let merlins =
|
||||||
let dir = ctx_dir in
|
List.filter_map stanzas ~f:(fun stanza ->
|
||||||
match (stanza : Stanza.t) with
|
let dir = ctx_dir in
|
||||||
| Library lib ->
|
match (stanza : Stanza.t) with
|
||||||
Some (library_rules lib ~dir ~files ~scope ~modules_partitioner)
|
| Library lib ->
|
||||||
| Executables exes ->
|
Some (library_rules lib ~dir ~files ~scope ~modules_partitioner)
|
||||||
Some (executables_rules exes ~dir ~all_modules ~scope
|
| Executables exes ->
|
||||||
~modules_partitioner)
|
Some (executables_rules exes ~dir ~all_modules ~scope
|
||||||
| Alias alias ->
|
~modules_partitioner)
|
||||||
alias_rules alias ~dir ~scope;
|
| Alias alias ->
|
||||||
None
|
alias_rules alias ~dir ~scope;
|
||||||
| Copy_files { glob; _ } ->
|
None
|
||||||
let src_dir =
|
| Copy_files { glob; _ } ->
|
||||||
let loc = String_with_vars.loc glob in
|
let src_dir =
|
||||||
let src_glob = SC.expand_vars sctx ~dir glob ~scope in
|
let loc = String_with_vars.loc glob in
|
||||||
Path.parent_exn (Path.relative src_dir src_glob ~error_loc:loc)
|
let src_glob = SC.expand_vars sctx ~dir glob ~scope in
|
||||||
in
|
Path.parent_exn (Path.relative src_dir src_glob ~error_loc:loc)
|
||||||
Some
|
in
|
||||||
(Merlin.make ()
|
Some
|
||||||
~source_dirs:(Path.Set.singleton src_dir))
|
(Merlin.make ()
|
||||||
| _ -> None)
|
~source_dirs:(Path.Set.singleton src_dir))
|
||||||
|> Merlin.merge_all
|
|
||||||
|> Option.map ~f:(fun m -> Merlin.add_source_dir m src_dir)
|
|
||||||
|> Option.iter ~f:(Merlin.add_rules sctx ~dir:ctx_dir ~scope);
|
|
||||||
Utop.setup sctx ~dir:ctx_dir ~libs:(
|
|
||||||
List.filter_map stanzas ~f:(function
|
|
||||||
| Stanza.Library lib -> Some lib
|
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
) ~scope;
|
in
|
||||||
|
Option.iter (Merlin.merge_all merlins) ~f:(fun m ->
|
||||||
|
Merlin.add_rules sctx ~dir:ctx_dir ~scope
|
||||||
|
(Merlin.add_source_dir m src_dir));
|
||||||
|
Utop.setup sctx ~dir:ctx_dir ~scope ~libs:(
|
||||||
|
List.filter_map stanzas ~f:(function
|
||||||
|
| Library lib -> Some lib
|
||||||
|
| _ -> None));
|
||||||
|
List.iter stanzas ~f:(fun stanza ->
|
||||||
|
match (stanza : Stanza.t) with
|
||||||
|
| Menhir m ->
|
||||||
|
let cctx =
|
||||||
|
match
|
||||||
|
List.find_map (Menhir_rules.module_names m)
|
||||||
|
~f:(Modules_partitioner.find modules_partitioner)
|
||||||
|
with
|
||||||
|
| None ->
|
||||||
|
Loc.fail m.loc
|
||||||
|
"I can't determine what library/executable the files produced \
|
||||||
|
by this stanza are part of."
|
||||||
|
| Some cctx -> cctx
|
||||||
|
in
|
||||||
|
Menhir_rules.gen_rules cctx m
|
||||||
|
| _ -> ());
|
||||||
Modules_partitioner.emit_warnings modules_partitioner
|
Modules_partitioner.emit_warnings modules_partitioner
|
||||||
|
|
||||||
let gen_rules ~dir components : Build_system.extra_sub_directories_to_keep =
|
let gen_rules ~dir components : Build_system.extra_sub_directories_to_keep =
|
||||||
(match components with
|
(match components with
|
||||||
| ".js" :: rest -> Js_of_ocaml_rules.setup_separate_compilation_rules
|
| ".js" :: rest -> Js_of_ocaml_rules.setup_separate_compilation_rules
|
||||||
sctx rest
|
sctx rest
|
||||||
|
|
|
@ -185,7 +185,7 @@ include Sub_system.Register_end_point(
|
||||||
; syntax = OCaml
|
; syntax = OCaml
|
||||||
}
|
}
|
||||||
; intf = None
|
; intf = None
|
||||||
; obj_name = ""
|
; obj_name = name
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
|
|
||||||
|
@ -239,16 +239,19 @@ include Sub_system.Register_end_point(
|
||||||
>>>
|
>>>
|
||||||
Build.action_dyn ~targets:[target] ());
|
Build.action_dyn ~targets:[target] ());
|
||||||
|
|
||||||
Exe.build_and_link sctx
|
let cctx =
|
||||||
~dir:inline_test_dir
|
Compilation_context.create ()
|
||||||
~obj_dir:inline_test_dir
|
~super_context:sctx
|
||||||
|
~scope
|
||||||
|
~dir:inline_test_dir
|
||||||
|
~modules
|
||||||
|
~requires:runner_libs
|
||||||
|
~flags:(Ocaml_flags.of_list ["-w"; "-24"]);
|
||||||
|
in
|
||||||
|
Exe.build_and_link cctx
|
||||||
~program:{ name; main_module_name }
|
~program:{ name; main_module_name }
|
||||||
~modules
|
|
||||||
~scope
|
|
||||||
~linkages:[Exe.Linkage.native_or_custom (SC.context sctx)]
|
~linkages:[Exe.Linkage.native_or_custom (SC.context sctx)]
|
||||||
~requires:runner_libs
|
~link_flags:(Build.return ["-linkall"]);
|
||||||
~link_flags:(Build.return ["-linkall"])
|
|
||||||
~flags:(Ocaml_flags.of_list ["-w"; "-24"]);
|
|
||||||
|
|
||||||
let flags =
|
let flags =
|
||||||
let flags =
|
let flags =
|
||||||
|
|
131
src/jbuild.ml
131
src/jbuild.ml
|
@ -1217,27 +1217,23 @@ module Env = struct
|
||||||
"S-expression of the form (<profile> <fields>) expected"
|
"S-expression of the form (<profile> <fields>) expected"
|
||||||
end
|
end
|
||||||
|
|
||||||
module Stanza = struct
|
type Stanza.t +=
|
||||||
type t =
|
| Library of Library.t
|
||||||
| Library of Library.t
|
| Executables of Executables.t
|
||||||
| Executables of Executables.t
|
| Rule of Rule.t
|
||||||
| Rule of Rule.t
|
| Provides of Provides.t
|
||||||
| Provides of Provides.t
|
| Install of Install_conf.t
|
||||||
| Install of Install_conf.t
|
| Alias of Alias_conf.t
|
||||||
| Alias of Alias_conf.t
|
| Copy_files of Copy_files.t
|
||||||
| Copy_files of Copy_files.t
|
| Menhir of Menhir.t
|
||||||
| Menhir of Menhir.t
|
| Documentation of Documentation.t
|
||||||
| Documentation of Documentation.t
|
| Env of Env.t
|
||||||
| Env of Env.t
|
|
||||||
end
|
|
||||||
|
|
||||||
module Stanzas = struct
|
module Stanzas = struct
|
||||||
type t = Stanza.t list
|
type t = Stanza.t list
|
||||||
|
|
||||||
type syntax = OCaml | Plain
|
type syntax = OCaml | Plain
|
||||||
|
|
||||||
open Stanza
|
|
||||||
|
|
||||||
let rules l = List.map l ~f:(fun x -> Rule x)
|
let rules l = List.map l ~f:(fun x -> Rule x)
|
||||||
|
|
||||||
let execs (exe, install) =
|
let execs (exe, install) =
|
||||||
|
@ -1245,9 +1241,9 @@ module Stanzas = struct
|
||||||
| None -> [Executables exe]
|
| None -> [Executables exe]
|
||||||
| Some i -> [Executables exe; Install i]
|
| Some i -> [Executables exe; Install i]
|
||||||
|
|
||||||
exception Include_loop of Path.t * (Loc.t * Path.t) list
|
type Stanza.t += Include of Loc.t * string
|
||||||
|
|
||||||
let rec v1 project ~file ~include_stack : Stanza.t list Sexp.Of_sexp.t =
|
let t project : Stanza.t list Sexp.Of_sexp.t =
|
||||||
sum
|
sum
|
||||||
[ cstr "library" (Library.v1 project @> nil) (fun x -> [Library x])
|
[ cstr "library" (Library.v1 project @> nil) (fun x -> [Library x])
|
||||||
; cstr "executable" (Executables.v1_single project @> nil) execs
|
; cstr "executable" (Executables.v1_single project @> nil) execs
|
||||||
|
@ -1270,70 +1266,55 @@ module Stanzas = struct
|
||||||
(* Just for validation and error messages *)
|
(* Just for validation and error messages *)
|
||||||
; cstr "jbuild_version" (Jbuild_version.t @> nil) (fun _ -> [])
|
; cstr "jbuild_version" (Jbuild_version.t @> nil) (fun _ -> [])
|
||||||
; cstr "include" (cstr_loc (relative_file @> nil)) (fun loc fn ->
|
; cstr "include" (cstr_loc (relative_file @> nil)) (fun loc fn ->
|
||||||
let include_stack = (loc, file) :: include_stack in
|
[Include (loc, fn)])
|
||||||
let dir = Path.parent_exn file in
|
|
||||||
let file = Path.relative dir fn in
|
|
||||||
if not (Path.exists file) then
|
|
||||||
Loc.fail loc "File %s doesn't exist."
|
|
||||||
(Path.to_string_maybe_quoted file);
|
|
||||||
if List.exists include_stack ~f:(fun (_, f) -> f = file) then
|
|
||||||
raise (Include_loop (file, include_stack));
|
|
||||||
let sexps = Io.Sexp.load file ~mode:Many in
|
|
||||||
parse project sexps ~default_version:Jbuild_version.V1 ~file ~include_stack)
|
|
||||||
; cstr "documentation" (Documentation.v1 project @> nil)
|
; cstr "documentation" (Documentation.v1 project @> nil)
|
||||||
(fun d -> [Documentation d])
|
(fun d -> [Documentation d])
|
||||||
]
|
]
|
||||||
|
|
||||||
and select
|
exception Include_loop of Path.t * (Loc.t * Path.t) list
|
||||||
: Jbuild_version.t
|
|
||||||
-> Dune_project.t
|
|
||||||
-> file:Path.t
|
|
||||||
-> include_stack:(Loc.t * Path.t) list
|
|
||||||
-> Stanza.t list Sexp.Of_sexp.t = function
|
|
||||||
| V1 -> v1
|
|
||||||
|
|
||||||
and parse ~default_version ~file ~include_stack project sexps =
|
let rec parse t ~current_file ~include_stack sexps =
|
||||||
let versions, sexps =
|
List.concat_map sexps ~f:t
|
||||||
List.partition_map sexps ~f:(function
|
|> List.concat_map ~f:(function
|
||||||
| List (loc, [Atom (_, A "jbuild_version"); ver]) ->
|
| Include (loc, fn) ->
|
||||||
Left (Jbuild_version.t ver, loc)
|
let include_stack = (loc, current_file) :: include_stack in
|
||||||
| sexp -> Right sexp)
|
let dir = Path.parent_exn current_file in
|
||||||
|
let current_file = Path.relative dir fn in
|
||||||
|
if not (Path.exists current_file) then
|
||||||
|
Loc.fail loc "File %s doesn't exist."
|
||||||
|
(Path.to_string_maybe_quoted current_file);
|
||||||
|
if List.exists include_stack ~f:(fun (_, f) -> f = current_file) then
|
||||||
|
raise (Include_loop (current_file, include_stack));
|
||||||
|
let sexps = Io.Sexp.load current_file ~mode:Many in
|
||||||
|
parse t sexps ~current_file ~include_stack
|
||||||
|
| stanza -> [stanza])
|
||||||
|
|
||||||
|
let parse ~file project sexps =
|
||||||
|
let stanzas =
|
||||||
|
try
|
||||||
|
parse (t project) sexps ~include_stack:[] ~current_file:file
|
||||||
|
with
|
||||||
|
| Include_loop (_, []) -> assert false
|
||||||
|
| Include_loop (file, last :: rest) ->
|
||||||
|
let loc = fst (Option.value (List.last rest) ~default:last) in
|
||||||
|
let line_loc (loc, file) =
|
||||||
|
sprintf "%s:%d"
|
||||||
|
(Path.to_string_maybe_quoted file)
|
||||||
|
loc.Loc.start.pos_lnum
|
||||||
|
in
|
||||||
|
Loc.fail loc
|
||||||
|
"Recursive inclusion of jbuild files detected:\n\
|
||||||
|
File %s is included from %s%s"
|
||||||
|
(Path.to_string_maybe_quoted file)
|
||||||
|
(line_loc last)
|
||||||
|
(String.concat ~sep:""
|
||||||
|
(List.map rest ~f:(fun x ->
|
||||||
|
sprintf
|
||||||
|
"\n--> included from %s"
|
||||||
|
(line_loc x))))
|
||||||
in
|
in
|
||||||
let version =
|
match List.filter_map stanzas ~f:(function Env e -> Some e | _ -> None) with
|
||||||
match versions with
|
|
||||||
| [] -> default_version
|
|
||||||
| [(v, _)] -> v
|
|
||||||
| _ :: (_, loc) :: _ ->
|
|
||||||
Loc.fail loc "jbuild_version specified too many times"
|
|
||||||
in
|
|
||||||
let l =
|
|
||||||
List.concat_map sexps ~f:(select version project ~file ~include_stack)
|
|
||||||
in
|
|
||||||
match List.filter_map l ~f:(function Env e -> Some e | _ -> None) with
|
|
||||||
| _ :: e :: _ ->
|
| _ :: e :: _ ->
|
||||||
Loc.fail e.loc "The 'env' stanza cannot appear more than once"
|
Loc.fail e.loc "The 'env' stanza cannot appear more than once"
|
||||||
| _ -> l
|
| _ -> stanzas
|
||||||
|
|
||||||
let parse ?(default_version=Jbuild_version.latest_stable) ~file project sexps =
|
|
||||||
try
|
|
||||||
parse project sexps ~default_version ~include_stack:[] ~file
|
|
||||||
with
|
|
||||||
| Include_loop (_, []) -> assert false
|
|
||||||
| Include_loop (file, last :: rest) ->
|
|
||||||
let loc = fst (Option.value (List.last rest) ~default:last) in
|
|
||||||
let line_loc (loc, file) =
|
|
||||||
sprintf "%s:%d"
|
|
||||||
(Path.to_string_maybe_quoted file)
|
|
||||||
loc.Loc.start.pos_lnum
|
|
||||||
in
|
|
||||||
Loc.fail loc
|
|
||||||
"Recursive inclusion of jbuild files detected:\n\
|
|
||||||
File %s is included from %s%s"
|
|
||||||
(Path.to_string_maybe_quoted file)
|
|
||||||
(line_loc last)
|
|
||||||
(String.concat ~sep:""
|
|
||||||
(List.map rest ~f:(fun x ->
|
|
||||||
sprintf
|
|
||||||
"\n--> included from %s"
|
|
||||||
(line_loc x))))
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -352,19 +352,17 @@ module Env : sig
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
module Stanza : sig
|
type Stanza.t +=
|
||||||
type t =
|
| Library of Library.t
|
||||||
| Library of Library.t
|
| Executables of Executables.t
|
||||||
| Executables of Executables.t
|
| Rule of Rule.t
|
||||||
| Rule of Rule.t
|
| Provides of Provides.t
|
||||||
| Provides of Provides.t
|
| Install of Install_conf.t
|
||||||
| Install of Install_conf.t
|
| Alias of Alias_conf.t
|
||||||
| Alias of Alias_conf.t
|
| Copy_files of Copy_files.t
|
||||||
| Copy_files of Copy_files.t
|
| Menhir of Menhir.t
|
||||||
| Menhir of Menhir.t
|
| Documentation of Documentation.t
|
||||||
| Documentation of Documentation.t
|
| Env of Env.t
|
||||||
| Env of Env.t
|
|
||||||
end
|
|
||||||
|
|
||||||
module Stanzas : sig
|
module Stanzas : sig
|
||||||
type t = Stanza.t list
|
type t = Stanza.t list
|
||||||
|
@ -372,8 +370,7 @@ module Stanzas : sig
|
||||||
type syntax = OCaml | Plain
|
type syntax = OCaml | Plain
|
||||||
|
|
||||||
val parse
|
val parse
|
||||||
: ?default_version:Jbuild_version.t
|
: file:Path.t
|
||||||
-> file:Path.t
|
|
||||||
-> Dune_project.t
|
-> Dune_project.t
|
||||||
-> Sexp.Ast.t list
|
-> Sexp.Ast.t list
|
||||||
-> t
|
-> t
|
||||||
|
|
|
@ -4,7 +4,7 @@ open Jbuild
|
||||||
let filter_stanzas ~ignore_promoted_rules stanzas =
|
let filter_stanzas ~ignore_promoted_rules stanzas =
|
||||||
if ignore_promoted_rules then
|
if ignore_promoted_rules then
|
||||||
List.filter stanzas ~f:(function
|
List.filter stanzas ~f:(function
|
||||||
| Stanza.Rule { mode = Promote; _ } -> false
|
| Rule { mode = Promote; _ } -> false
|
||||||
| _ -> true)
|
| _ -> true)
|
||||||
else
|
else
|
||||||
stanzas
|
stanzas
|
||||||
|
|
|
@ -80,10 +80,8 @@ module Run (P : PARAMS) = struct
|
||||||
let menhir (args : args) =
|
let menhir (args : args) =
|
||||||
flags >>> Build.run menhir_binary ~dir ~context args
|
flags >>> Build.run menhir_binary ~dir ~context args
|
||||||
|
|
||||||
(* The function [rule] adds a rule and returns the list of its targets. *)
|
let rule : (unit, Action.t) Build.t -> unit =
|
||||||
|
SC.add_rule sctx ~mode:stanza.mode ~loc:stanza.loc
|
||||||
let rule : (unit, Action.t) Build.t -> Path.t list =
|
|
||||||
SC.add_rule_get_targets sctx ~mode:stanza.mode ~loc:stanza.loc
|
|
||||||
|
|
||||||
(* If there is no [base] clause, then a stanza that mentions several modules
|
(* If there is no [base] clause, then a stanza that mentions several modules
|
||||||
is equivalent to a list of stanzas, each of which mentions one module, so
|
is equivalent to a list of stanzas, each of which mentions one module, so
|
||||||
|
@ -119,7 +117,7 @@ module Run (P : PARAMS) = struct
|
||||||
|
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let process (stanza : stanza) : Path.t list =
|
let process (stanza : stanza) =
|
||||||
let base : string = Option.value_exn stanza.merge_into in
|
let base : string = Option.value_exn stanza.merge_into in
|
||||||
let args : args =
|
let args : args =
|
||||||
[ Dyn (fun flags -> As flags)
|
[ Dyn (fun flags -> As flags)
|
||||||
|
@ -132,8 +130,8 @@ module Run (P : PARAMS) = struct
|
||||||
|
|
||||||
(* The main side effect. *)
|
(* The main side effect. *)
|
||||||
|
|
||||||
let targets =
|
let () =
|
||||||
List.concat_map ~f:process stanzas
|
List.iter ~f:process stanzas
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -141,11 +139,22 @@ end
|
||||||
|
|
||||||
(* The final glue. *)
|
(* The final glue. *)
|
||||||
|
|
||||||
let gen_rules sctx ~dir ~scope stanza =
|
let targets (stanza : Jbuild.Menhir.t) =
|
||||||
|
let f m = [m ^ ".ml"; m ^ ".mli"] in
|
||||||
|
match stanza.merge_into with
|
||||||
|
| Some m -> f m
|
||||||
|
| None -> List.concat_map stanza.modules ~f
|
||||||
|
|
||||||
|
let module_names (stanza : Jbuild.Menhir.t) =
|
||||||
|
match stanza.merge_into with
|
||||||
|
| Some m -> [Module.Name.of_string m]
|
||||||
|
| None -> List.map stanza.modules ~f:Module.Name.of_string
|
||||||
|
|
||||||
|
let gen_rules cctx stanza =
|
||||||
let module R = Run(struct
|
let module R = Run(struct
|
||||||
let sctx = sctx
|
let sctx = Compilation_context.super_context cctx
|
||||||
let dir = dir
|
let dir = Compilation_context.dir cctx
|
||||||
let scope = scope
|
let scope = Compilation_context.scope cctx
|
||||||
let stanza = stanza
|
let stanza = stanza
|
||||||
end) in
|
end) in
|
||||||
R.targets
|
()
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
(** Menhir rules *)
|
(** Menhir rules *)
|
||||||
|
|
||||||
open Stdune
|
(** Return the list of targets that are generated by this stanza. This
|
||||||
|
list of targets is used by the code that computes the list of
|
||||||
|
modules in the directory. *)
|
||||||
|
val targets : Jbuild.Menhir.t -> string list
|
||||||
|
|
||||||
(** Generate the rules for a [(menhir ...)] stanza. Return the list of
|
(** Return the list of modules that are generated by this stanza. *)
|
||||||
targets that are generated by these rules. This list of targets is
|
val module_names : Jbuild.Menhir.t -> Module.Name.t list
|
||||||
used by the code that computes the list of modules in the
|
|
||||||
directory. *)
|
(** Generate the rules for a [(menhir ...)] stanza. *)
|
||||||
val gen_rules
|
val gen_rules
|
||||||
: Super_context.t
|
: Compilation_context.t
|
||||||
-> dir:Path.t
|
|
||||||
-> scope:Scope.t
|
|
||||||
-> Jbuild.Menhir.t
|
-> Jbuild.Menhir.t
|
||||||
-> Path.t list
|
-> unit
|
||||||
|
|
|
@ -2,6 +2,7 @@ open Import
|
||||||
open Build.O
|
open Build.O
|
||||||
open! No_io
|
open! No_io
|
||||||
|
|
||||||
|
module CC = Compilation_context
|
||||||
module SC = Super_context
|
module SC = Super_context
|
||||||
|
|
||||||
module Target : sig
|
module Target : sig
|
||||||
|
@ -18,9 +19,11 @@ end = struct
|
||||||
let file dir t = Path.append dir t
|
let file dir t = Path.append dir t
|
||||||
end
|
end
|
||||||
|
|
||||||
let build_cm sctx ?sandbox ~dynlink ~flags ~cm_kind ~dep_graphs
|
let build_cm cctx ?sandbox ?(dynlink=true) ~dep_graphs ~cm_kind (m : Module.t) =
|
||||||
~includes ~dir ~obj_dir ~alias_module (m : Module.t) =
|
let sctx = CC.super_context cctx in
|
||||||
let ctx = SC.context sctx in
|
let dir = CC.dir cctx in
|
||||||
|
let obj_dir = CC.obj_dir cctx in
|
||||||
|
let ctx = SC.context sctx in
|
||||||
Option.iter (Mode.of_cm_kind cm_kind |> Context.compiler ctx) ~f:(fun compiler ->
|
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 ->
|
Option.iter (Module.cm_source ~dir m cm_kind) ~f:(fun src ->
|
||||||
let ml_kind = Cm_kind.source cm_kind in
|
let ml_kind = Cm_kind.source cm_kind in
|
||||||
|
@ -89,16 +92,16 @@ let build_cm sctx ?sandbox ~dynlink ~flags ~cm_kind ~dep_graphs
|
||||||
SC.add_rule sctx ?sandbox
|
SC.add_rule sctx ?sandbox
|
||||||
(Build.paths extra_deps >>>
|
(Build.paths extra_deps >>>
|
||||||
other_cm_files >>>
|
other_cm_files >>>
|
||||||
Ocaml_flags.get_for_cm flags ~cm_kind >>>
|
Ocaml_flags.get_for_cm (CC.flags cctx) ~cm_kind >>>
|
||||||
Build.run ~context:ctx (Ok compiler)
|
Build.run ~context:ctx (Ok compiler)
|
||||||
[ Dyn (fun ocaml_flags -> As ocaml_flags)
|
[ Dyn (fun ocaml_flags -> As ocaml_flags)
|
||||||
; cmt_args
|
; cmt_args
|
||||||
; A "-I"; Path obj_dir
|
; A "-I"; Path obj_dir
|
||||||
; includes
|
; Cm_kind.Dict.get (CC.includes cctx) cm_kind
|
||||||
; As extra_args
|
; As extra_args
|
||||||
; if dynlink || cm_kind <> Cmx then As [] else A "-nodynlink"
|
; if dynlink || cm_kind <> Cmx then As [] else A "-nodynlink"
|
||||||
; A "-no-alias-deps"; opaque
|
; A "-no-alias-deps"; opaque
|
||||||
; (match alias_module with
|
; (match CC.alias_module cctx with
|
||||||
| None -> S []
|
| None -> S []
|
||||||
| Some (m : Module.t) ->
|
| Some (m : Module.t) ->
|
||||||
As ["-open"; Module.Name.to_string m.name])
|
As ["-open"; Module.Name.to_string m.name])
|
||||||
|
@ -107,51 +110,56 @@ let build_cm sctx ?sandbox ~dynlink ~flags ~cm_kind ~dep_graphs
|
||||||
; Hidden_targets hidden_targets
|
; Hidden_targets hidden_targets
|
||||||
])))
|
])))
|
||||||
|
|
||||||
let build_module sctx ?sandbox ~dynlink ~js_of_ocaml ~flags m ~scope ~dir
|
let build_module ?sandbox ?js_of_ocaml ?dynlink ~dep_graphs cctx m =
|
||||||
~obj_dir ~dep_graphs ~includes ~alias_module =
|
|
||||||
List.iter Cm_kind.all ~f:(fun cm_kind ->
|
List.iter Cm_kind.all ~f:(fun cm_kind ->
|
||||||
let includes = Cm_kind.Dict.get includes cm_kind in
|
build_cm cctx m ?sandbox ?dynlink ~dep_graphs ~cm_kind);
|
||||||
build_cm sctx ?sandbox ~dynlink ~flags ~dir ~obj_dir ~dep_graphs m ~cm_kind
|
Option.iter js_of_ocaml ~f:(fun js_of_ocaml ->
|
||||||
~includes ~alias_module);
|
(* Build *.cmo.js *)
|
||||||
(* Build *.cmo.js *)
|
let sctx = CC.super_context cctx in
|
||||||
let src = Module.cm_file_unsafe m ~obj_dir Cm_kind.Cmo in
|
let scope = CC.scope cctx in
|
||||||
let target =
|
let dir = CC.dir cctx in
|
||||||
Path.extend_basename (Module.cm_file_unsafe m ~obj_dir:dir Cm_kind.Cmo)
|
let obj_dir = CC.obj_dir cctx in
|
||||||
~suffix:".js"
|
let src = Module.cm_file_unsafe m ~obj_dir Cm_kind.Cmo in
|
||||||
in
|
let target =
|
||||||
SC.add_rules sctx
|
Path.extend_basename (Module.cm_file_unsafe m ~obj_dir:dir Cm_kind.Cmo)
|
||||||
(Js_of_ocaml_rules.build_cm sctx ~scope ~dir ~js_of_ocaml ~src ~target)
|
~suffix:".js"
|
||||||
|
in
|
||||||
|
SC.add_rules sctx
|
||||||
|
(Js_of_ocaml_rules.build_cm sctx ~scope ~dir ~js_of_ocaml ~src ~target))
|
||||||
|
|
||||||
let build_modules sctx ~dynlink ~js_of_ocaml ~flags ~scope ~dir ~obj_dir
|
let build_modules ?sandbox ?js_of_ocaml ?dynlink ~dep_graphs cctx =
|
||||||
~dep_graphs ~modules ~requires ~alias_module =
|
|
||||||
let includes : _ Cm_kind.Dict.t =
|
|
||||||
match requires with
|
|
||||||
| Error exn -> Cm_kind.Dict.make_all (Arg_spec.Dyn (fun _ -> raise exn))
|
|
||||||
| Ok libs ->
|
|
||||||
let iflags =
|
|
||||||
Lib.L.include_flags libs ~stdlib_dir:(SC.context sctx).stdlib_dir
|
|
||||||
in
|
|
||||||
let cmi_includes =
|
|
||||||
Arg_spec.S [ iflags
|
|
||||||
; Hidden_deps
|
|
||||||
(SC.Libs.file_deps sctx libs ~ext:".cmi")
|
|
||||||
]
|
|
||||||
in
|
|
||||||
let cmi_and_cmx_includes =
|
|
||||||
Arg_spec.S [ iflags
|
|
||||||
; Hidden_deps
|
|
||||||
(SC.Libs.file_deps sctx libs ~ext:".cmi-and-.cmx")
|
|
||||||
]
|
|
||||||
in
|
|
||||||
{ cmi = cmi_includes
|
|
||||||
; cmo = cmi_includes
|
|
||||||
; cmx = cmi_and_cmx_includes
|
|
||||||
}
|
|
||||||
in
|
|
||||||
Module.Name.Map.iter
|
Module.Name.Map.iter
|
||||||
(match alias_module with
|
(match CC.alias_module cctx with
|
||||||
| None -> modules
|
| None -> CC.modules cctx
|
||||||
| Some (m : Module.t) -> Module.Name.Map.remove modules m.name)
|
| Some (m : Module.t) -> Module.Name.Map.remove (CC.modules cctx) m.name)
|
||||||
~f:(fun m ->
|
~f:(build_module cctx ?sandbox ?js_of_ocaml ?dynlink ~dep_graphs)
|
||||||
build_module sctx m ~dynlink ~js_of_ocaml ~flags ~scope ~dir ~obj_dir
|
|
||||||
~dep_graphs ~includes ~alias_module)
|
let ocamlc_i ?sandbox ?(flags=[]) ~dep_graphs cctx (m : Module.t) ~output =
|
||||||
|
let sctx = CC.super_context cctx in
|
||||||
|
let dir = CC.dir cctx in
|
||||||
|
let obj_dir = CC.obj_dir cctx in
|
||||||
|
let ctx = SC.context sctx in
|
||||||
|
let src = Option.value_exn (Module.file ~dir m Impl) in
|
||||||
|
let dep_graph = Ml_kind.Dict.get dep_graphs Impl in
|
||||||
|
let cm_deps =
|
||||||
|
Build.dyn_paths
|
||||||
|
(Ocamldep.Dep_graph.deps_of dep_graph m >>^ fun deps ->
|
||||||
|
List.concat_map deps
|
||||||
|
~f:(fun m -> [Module.cm_file_unsafe m ~obj_dir Cmi]))
|
||||||
|
in
|
||||||
|
SC.add_rule sctx ?sandbox
|
||||||
|
(cm_deps >>>
|
||||||
|
Ocaml_flags.get_for_cm (CC.flags cctx) ~cm_kind:Cmo >>>
|
||||||
|
Build.run ~context:ctx (Ok ctx.ocamlc)
|
||||||
|
[ Dyn (fun ocaml_flags -> As ocaml_flags)
|
||||||
|
; A "-I"; Path obj_dir
|
||||||
|
; Cm_kind.Dict.get (CC.includes cctx) Cmo
|
||||||
|
; (match CC.alias_module cctx with
|
||||||
|
| None -> S []
|
||||||
|
| Some (m : Module.t) ->
|
||||||
|
As ["-open"; Module.Name.to_string m.name])
|
||||||
|
; As flags
|
||||||
|
; A "-i"; Ml_kind.flag Impl; Dep src
|
||||||
|
]
|
||||||
|
>>^ (fun act -> Action.with_stdout_to output act)
|
||||||
|
>>> Build.action_dyn () ~targets:[output])
|
||||||
|
|
|
@ -4,31 +4,28 @@ open Import
|
||||||
|
|
||||||
(** Setup rules to build a single module. *)
|
(** Setup rules to build a single module. *)
|
||||||
val build_module
|
val build_module
|
||||||
: Super_context.t
|
: ?sandbox:bool
|
||||||
-> ?sandbox:bool
|
-> ?js_of_ocaml:Jbuild.Js_of_ocaml.t
|
||||||
-> dynlink:bool
|
-> ?dynlink:bool
|
||||||
-> js_of_ocaml:Jbuild.Js_of_ocaml.t
|
|
||||||
-> flags:Ocaml_flags.t
|
|
||||||
-> Module.t
|
|
||||||
-> scope:Scope.t
|
|
||||||
-> dir:Path.t
|
|
||||||
-> obj_dir:Path.t
|
|
||||||
-> dep_graphs:Ocamldep.Dep_graphs.t
|
-> dep_graphs:Ocamldep.Dep_graphs.t
|
||||||
-> includes:string list Arg_spec.t Cm_kind.Dict.t
|
-> Compilation_context.t
|
||||||
-> alias_module:Module.t option
|
-> Module.t
|
||||||
-> unit
|
-> unit
|
||||||
|
|
||||||
(** Setup rules to build all of [modules] *)
|
(** Setup rules to build all of the modules in the compilation context. *)
|
||||||
val build_modules
|
val build_modules
|
||||||
: Super_context.t
|
: ?sandbox:bool
|
||||||
-> dynlink:bool
|
-> ?js_of_ocaml:Jbuild.Js_of_ocaml.t
|
||||||
-> js_of_ocaml:Jbuild.Js_of_ocaml.t
|
-> ?dynlink:bool
|
||||||
-> flags:Ocaml_flags.t
|
|
||||||
-> scope:Scope.t
|
|
||||||
-> dir:Path.t
|
|
||||||
-> obj_dir:Path.t
|
|
||||||
-> dep_graphs:Ocamldep.Dep_graphs.t
|
-> dep_graphs:Ocamldep.Dep_graphs.t
|
||||||
-> modules:Module.t Module.Name.Map.t
|
-> Compilation_context.t
|
||||||
-> requires:Lib.t list Or_exn.t
|
-> unit
|
||||||
-> alias_module:Module.t option
|
|
||||||
|
val ocamlc_i
|
||||||
|
: ?sandbox:bool
|
||||||
|
-> ?flags:string list
|
||||||
|
-> dep_graphs:Ocamldep.Dep_graphs.t
|
||||||
|
-> Compilation_context.t
|
||||||
|
-> Module.t
|
||||||
|
-> output:Path.t
|
||||||
-> unit
|
-> unit
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
open Import
|
open Import
|
||||||
|
|
||||||
type t =
|
type 'a t =
|
||||||
{ all_modules : Module.t Module.Name.Map.t
|
{ mutable used : ('a * Loc.t list) Module.Name.Map.t
|
||||||
; mutable used : Loc.t list Module.Name.Map.t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let create ~all_modules =
|
let create () =
|
||||||
{ all_modules
|
{ used = Module.Name.Map.empty
|
||||||
; used = Module.Name.Map.empty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let acknowledge t ~loc ~modules =
|
let acknowledge t part ~loc ~modules =
|
||||||
let already_used =
|
let already_used =
|
||||||
Module.Name.Map.merge modules t.used ~f:(fun _name x l ->
|
Module.Name.Map.merge modules t.used ~f:(fun _name x l ->
|
||||||
Option.some_if (Option.is_some x && Option.is_some l) ())
|
Option.some_if (Option.is_some x && Option.is_some l) ())
|
||||||
|
@ -18,14 +16,20 @@ let acknowledge t ~loc ~modules =
|
||||||
|> Module.Name.Set.of_list
|
|> Module.Name.Set.of_list
|
||||||
in
|
in
|
||||||
t.used <-
|
t.used <-
|
||||||
Module.Name.Map.merge modules t.used ~f:(fun _name x l ->
|
Module.Name.Map.merge modules t.used ~f:(fun _name x y ->
|
||||||
match x with
|
match x with
|
||||||
| None -> l
|
| None -> y
|
||||||
| Some _ -> Some (loc :: Option.value l ~default:[]));
|
| Some _ ->
|
||||||
|
Some (part,
|
||||||
|
loc :: match y with
|
||||||
|
| None -> []
|
||||||
|
| Some (_, l) -> l));
|
||||||
already_used
|
already_used
|
||||||
|
|
||||||
|
let find t name = Option.map (Module.Name.Map.find t.used name) ~f:fst
|
||||||
|
|
||||||
let emit_warnings t =
|
let emit_warnings t =
|
||||||
Module.Name.Map.iteri t.used ~f:(fun name locs ->
|
Module.Name.Map.iteri t.used ~f:(fun name (_, locs) ->
|
||||||
match locs with
|
match locs with
|
||||||
| [] | [_] -> ()
|
| [] | [_] -> ()
|
||||||
| loc :: _ ->
|
| loc :: _ ->
|
||||||
|
|
|
@ -2,24 +2,26 @@
|
||||||
|
|
||||||
open! Stdune
|
open! Stdune
|
||||||
|
|
||||||
type t
|
type 'a t
|
||||||
|
|
||||||
val create
|
val create : unit -> 'a t
|
||||||
: all_modules:Module.t Module.Name.Map.t
|
|
||||||
-> t
|
|
||||||
|
|
||||||
(** [acknowledge t ~loc ~modules] registers the fact that [modules]
|
(** [acknowledge t partition ~loc ~modules] registers the fact that [modules]
|
||||||
are associated with [loc].
|
are associated with [loc].
|
||||||
|
|
||||||
Returns the set of modules that are already used at another
|
Returns the set of modules that are already used at another
|
||||||
location.
|
location.
|
||||||
*)
|
*)
|
||||||
val acknowledge
|
val acknowledge
|
||||||
: t
|
: 'a t
|
||||||
|
-> 'a
|
||||||
-> loc:Loc.t
|
-> loc:Loc.t
|
||||||
-> modules:Module.t Module.Name.Map.t
|
-> modules:Module.t Module.Name.Map.t
|
||||||
-> Module.Name.Set.t
|
-> Module.Name.Set.t
|
||||||
|
|
||||||
|
(** Find which partition a module is part of *)
|
||||||
|
val find : 'a t -> Module.Name.t -> 'a option
|
||||||
|
|
||||||
(** To be called after processing a directory. Emit warnings about
|
(** To be called after processing a directory. Emit warnings about
|
||||||
detected problems *)
|
detected problems *)
|
||||||
val emit_warnings : t -> unit
|
val emit_warnings : _ t -> unit
|
||||||
|
|
138
src/ocamldep.ml
138
src/ocamldep.ml
|
@ -1,6 +1,7 @@
|
||||||
open Import
|
open Import
|
||||||
open Build.O
|
open Build.O
|
||||||
|
|
||||||
|
module CC = Compilation_context
|
||||||
module SC = Super_context
|
module SC = Super_context
|
||||||
|
|
||||||
module Dep_graph = struct
|
module Dep_graph = struct
|
||||||
|
@ -66,8 +67,16 @@ let parse_module_names ~(unit : Module.t) ~modules words =
|
||||||
else
|
else
|
||||||
Module.Name.Map.find modules m)
|
Module.Name.Map.find modules m)
|
||||||
|
|
||||||
let parse_deps ~dir ~file ~unit
|
let is_alias_module cctx (m : Module.t) =
|
||||||
~modules ~alias_module ~lib_interface_module lines =
|
match CC.alias_module cctx with
|
||||||
|
| None -> false
|
||||||
|
| Some alias -> alias.name = m.name
|
||||||
|
|
||||||
|
let parse_deps cctx ~file ~unit lines =
|
||||||
|
let dir = CC.dir cctx in
|
||||||
|
let alias_module = CC.alias_module cctx in
|
||||||
|
let lib_interface_module = CC.lib_interface_module cctx in
|
||||||
|
let modules = CC.modules cctx in
|
||||||
let invalid () =
|
let invalid () =
|
||||||
die "ocamldep returned unexpected output for %s:\n\
|
die "ocamldep returned unexpected output for %s:\n\
|
||||||
%s"
|
%s"
|
||||||
|
@ -94,12 +103,7 @@ let parse_deps ~dir ~file ~unit
|
||||||
(match lib_interface_module with
|
(match lib_interface_module with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some (m : Module.t) ->
|
| Some (m : Module.t) ->
|
||||||
let is_alias_module =
|
if unit.name <> m.name && not (is_alias_module cctx unit) &&
|
||||||
match alias_module with
|
|
||||||
| None -> false
|
|
||||||
| Some (m : Module.t) -> unit.name = m.name
|
|
||||||
in
|
|
||||||
if unit.name <> m.name && not is_alias_module &&
|
|
||||||
List.exists deps ~f:(fun x -> Module.name x = m.name) then
|
List.exists deps ~f:(fun x -> Module.name x = m.name) then
|
||||||
die "Module %a in directory %s depends on %a.\n\
|
die "Module %a in directory %s depends on %a.\n\
|
||||||
This doesn't make sense to me.\n\
|
This doesn't make sense to me.\n\
|
||||||
|
@ -116,66 +120,70 @@ let parse_deps ~dir ~file ~unit
|
||||||
| None -> deps
|
| None -> deps
|
||||||
| Some m -> m :: deps
|
| Some m -> m :: deps
|
||||||
|
|
||||||
let rules ~(ml_kind:Ml_kind.t) ~dir ~modules
|
let deps_of cctx ~ml_kind ~already_used unit =
|
||||||
?(already_used=Module.Name.Set.empty)
|
let sctx = CC.super_context cctx in
|
||||||
~alias_module ~lib_interface_module sctx =
|
let dir = CC.dir cctx in
|
||||||
let is_alias_module (m : Module.t) =
|
if is_alias_module cctx unit then
|
||||||
match alias_module with
|
Build.return []
|
||||||
| None -> false
|
else
|
||||||
| Some (alias : Module.t) -> alias.name = m.name
|
match Module.file ~dir unit ml_kind with
|
||||||
in
|
| None -> Build.return []
|
||||||
let per_module =
|
| Some file ->
|
||||||
Module.Name.Map.map modules ~f:(fun unit ->
|
let all_deps_path file =
|
||||||
match Module.file ~dir unit ml_kind with
|
Path.extend_basename file ~suffix:".all-deps"
|
||||||
| _ when is_alias_module unit -> Build.return []
|
in
|
||||||
| None -> Build.return []
|
let context = SC.context sctx in
|
||||||
| Some file ->
|
let all_deps_file = all_deps_path file in
|
||||||
let all_deps_path file =
|
let ocamldep_output = Path.extend_basename file ~suffix:".d" in
|
||||||
Path.extend_basename file ~suffix:".all-deps"
|
if not (Module.Name.Set.mem already_used unit.name) then
|
||||||
in
|
begin
|
||||||
let context = SC.context sctx in
|
SC.add_rule sctx
|
||||||
let all_deps_file = all_deps_path file in
|
( Build.run ~context (Ok context.ocamldep)
|
||||||
let ocamldep_output = Path.extend_basename file ~suffix:".d" in
|
[A "-modules"; Ml_kind.flag ml_kind; Dep file]
|
||||||
if not (Module.Name.Set.mem already_used unit.name) then
|
~stdout_to:ocamldep_output
|
||||||
begin
|
);
|
||||||
SC.add_rule sctx
|
let build_paths dependencies =
|
||||||
( Build.run ~context (Ok context.ocamldep)
|
let dependency_file_path m =
|
||||||
[A "-modules"; Ml_kind.flag ml_kind; Dep file]
|
let path =
|
||||||
~stdout_to:ocamldep_output
|
if is_alias_module cctx m then
|
||||||
);
|
None
|
||||||
let build_paths dependencies =
|
else
|
||||||
let dependency_file_path m =
|
|
||||||
let path =
|
|
||||||
match Module.file ~dir m Ml_kind.Intf with
|
match Module.file ~dir m Ml_kind.Intf with
|
||||||
| _ when is_alias_module m -> None
|
|
||||||
| Some _ as x -> x
|
| Some _ as x -> x
|
||||||
| None -> Module.file ~dir m Ml_kind.Impl
|
| None -> Module.file ~dir m Ml_kind.Impl
|
||||||
in
|
|
||||||
Option.map path ~f:all_deps_path
|
|
||||||
in
|
in
|
||||||
List.filter_map dependencies ~f:dependency_file_path
|
Option.map path ~f:all_deps_path
|
||||||
in
|
in
|
||||||
SC.add_rule sctx
|
List.filter_map dependencies ~f:dependency_file_path
|
||||||
( Build.lines_of ocamldep_output
|
in
|
||||||
>>^ parse_deps
|
SC.add_rule sctx
|
||||||
~dir ~file ~unit ~modules ~alias_module
|
( Build.lines_of ocamldep_output
|
||||||
~lib_interface_module
|
>>^ parse_deps cctx ~file ~unit
|
||||||
>>^ (fun modules ->
|
>>^ (fun modules ->
|
||||||
(build_paths modules,
|
(build_paths modules,
|
||||||
List.map modules ~f:(fun m ->
|
List.map modules ~f:(fun m ->
|
||||||
Module.Name.to_string (Module.name m))
|
Module.Name.to_string (Module.name m))
|
||||||
))
|
))
|
||||||
>>> Build.merge_files_dyn ~target:all_deps_file)
|
>>> Build.merge_files_dyn ~target:all_deps_file)
|
||||||
end;
|
end;
|
||||||
Build.memoize (Path.to_string all_deps_file)
|
Build.memoize (Path.to_string all_deps_file)
|
||||||
( Build.lines_of all_deps_file
|
( Build.lines_of all_deps_file
|
||||||
>>^ parse_module_names ~unit ~modules))
|
>>^ parse_module_names ~unit ~modules:(CC.modules cctx))
|
||||||
in
|
|
||||||
{ Dep_graph.
|
|
||||||
dir
|
|
||||||
; per_module
|
|
||||||
}
|
|
||||||
|
|
||||||
let rules ~dir ~modules ?already_used ~alias_module ~lib_interface_module sctx =
|
let rules_generic ?(already_used=Module.Name.Set.empty) cctx ~modules =
|
||||||
Ml_kind.Dict.of_func (rules sctx ~dir ~modules ?already_used ~alias_module
|
Ml_kind.Dict.of_func
|
||||||
~lib_interface_module)
|
(fun ~ml_kind ->
|
||||||
|
let per_module =
|
||||||
|
Module.Name.Map.map modules
|
||||||
|
~f:(deps_of cctx ~already_used ~ml_kind)
|
||||||
|
in
|
||||||
|
{ Dep_graph.
|
||||||
|
dir = CC.dir cctx
|
||||||
|
; per_module
|
||||||
|
})
|
||||||
|
|
||||||
|
let rules ?already_used cctx =
|
||||||
|
rules_generic ?already_used cctx ~modules:(CC.modules cctx)
|
||||||
|
|
||||||
|
let rules_for_auxiliary_module cctx (m : Module.t) =
|
||||||
|
rules_generic cctx ~modules:(Module.Name.Map.singleton m.name m)
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
(** ocamldep management *)
|
(** ocamldep management *)
|
||||||
|
|
||||||
open Stdune
|
|
||||||
|
|
||||||
module Dep_graph : sig
|
module Dep_graph : sig
|
||||||
type t
|
type t
|
||||||
|
|
||||||
|
@ -22,23 +20,18 @@ module Dep_graphs : sig
|
||||||
val dummy : Module.t -> t
|
val dummy : Module.t -> t
|
||||||
end
|
end
|
||||||
|
|
||||||
(** Generate ocamldep rules for the given modules. [item] is either
|
(** Generate ocamldep rules for all the modules in the context.
|
||||||
the internal name of a library of the first name of a list of
|
|
||||||
executables.
|
|
||||||
|
|
||||||
For wrapped libraries, [lib_interface_module] is the main module
|
|
||||||
of the library.
|
|
||||||
|
|
||||||
[already_used] represents the modules that are used by another
|
[already_used] represents the modules that are used by another
|
||||||
stanzas in the same directory. No [.d] rule will be generated for
|
stanzas in the same directory. No [.d] rule will be generated for
|
||||||
such modules.
|
such modules. *)
|
||||||
|
|
||||||
Return arrows that evaluate to the dependency graphs. *)
|
|
||||||
val rules
|
val rules
|
||||||
: dir:Path.t
|
: ?already_used:Module.Name.Set.t
|
||||||
-> modules:Module.t Module.Name.Map.t
|
-> Compilation_context.t
|
||||||
-> ?already_used:Module.Name.Set.t
|
-> Dep_graphs.t
|
||||||
-> alias_module:Module.t option
|
|
||||||
-> lib_interface_module:Module.t option
|
(** Compute the dependencies of an auxiliary module. *)
|
||||||
-> Super_context.t
|
val rules_for_auxiliary_module
|
||||||
|
: Compilation_context.t
|
||||||
|
-> Module.t
|
||||||
-> Dep_graphs.t
|
-> Dep_graphs.t
|
||||||
|
|
|
@ -471,7 +471,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
SC.stanzas sctx
|
SC.stanzas sctx
|
||||||
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
||||||
List.filter_map w.stanzas ~f:(function
|
List.filter_map w.stanzas ~f:(function
|
||||||
| Jbuild.Stanza.Documentation (d : Jbuild.Documentation.t) ->
|
| Documentation (d : Jbuild.Documentation.t) ->
|
||||||
Some (d.package.name, (w.ctx_dir, d))
|
Some (d.package.name, (w.ctx_dir, d))
|
||||||
| _ ->
|
| _ ->
|
||||||
None
|
None
|
||||||
|
@ -494,7 +494,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
SC.stanzas sctx
|
SC.stanzas sctx
|
||||||
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
||||||
List.filter_map w.stanzas ~f:(function
|
List.filter_map w.stanzas ~f:(function
|
||||||
| Jbuild.Stanza.Library (l : Library.t) ->
|
| Jbuild.Library (l : Library.t) ->
|
||||||
Some ((w.ctx_dir, Library.best_name l), l)
|
Some ((w.ctx_dir, Library.best_name l), l)
|
||||||
| _ ->
|
| _ ->
|
||||||
None
|
None
|
||||||
|
@ -532,7 +532,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
(SC.stanzas sctx
|
(SC.stanzas sctx
|
||||||
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
||||||
List.filter_map w.stanzas ~f:(function
|
List.filter_map w.stanzas ~f:(function
|
||||||
| Jbuild.Stanza.Library (l : Jbuild.Library.t) ->
|
| Jbuild.Library (l : Jbuild.Library.t) ->
|
||||||
begin match l.public with
|
begin match l.public with
|
||||||
| Some _ -> None
|
| Some _ -> None
|
||||||
| None ->
|
| None ->
|
||||||
|
@ -541,7 +541,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
Lib.DB.find_even_when_hidden (Scope.libs scope) l.name)
|
Lib.DB.find_even_when_hidden (Scope.libs scope) l.name)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
| (_ : Jbuild.Stanza.t) -> None
|
| _ -> None
|
||||||
))
|
))
|
||||||
|> List.map ~f:(fun (lib : Lib.t) ->
|
|> List.map ~f:(fun (lib : Lib.t) ->
|
||||||
Build_system.Alias.stamp_file (Dep.alias (Lib lib)))
|
Build_system.Alias.stamp_file (Dep.alias (Lib lib)))
|
||||||
|
|
|
@ -293,9 +293,11 @@ let lint_module sctx ~dir ~dep_kind ~lint ~lib_name ~scope = Staged.stage (
|
||||||
fun ~(source : Module.t) ~ast ->
|
fun ~(source : Module.t) ~ast ->
|
||||||
Per_module.get lint source.name ~source ~ast)
|
Per_module.get lint source.name ~source ~ast)
|
||||||
|
|
||||||
(* Generate rules to build the .pp files and return a new module map
|
type t = (Module.t -> lint:bool -> Module.t) Per_module.t
|
||||||
where all filenames point to the .pp files *)
|
|
||||||
let pp_and_lint_modules sctx ~dir ~dep_kind ~modules ~lint ~preprocess
|
let dummy = Per_module.for_all (fun m ~lint:_ -> m)
|
||||||
|
|
||||||
|
let make sctx ~dir ~dep_kind ~lint ~preprocess
|
||||||
~preprocessor_deps ~lib_name ~scope =
|
~preprocessor_deps ~lib_name ~scope =
|
||||||
let preprocessor_deps =
|
let preprocessor_deps =
|
||||||
Build.memoize "preprocessor deps" preprocessor_deps
|
Build.memoize "preprocessor deps" preprocessor_deps
|
||||||
|
@ -303,62 +305,65 @@ let pp_and_lint_modules sctx ~dir ~dep_kind ~modules ~lint ~preprocess
|
||||||
let lint_module =
|
let lint_module =
|
||||||
Staged.unstage (lint_module sctx ~dir ~dep_kind ~lint ~lib_name ~scope)
|
Staged.unstage (lint_module sctx ~dir ~dep_kind ~lint ~lib_name ~scope)
|
||||||
in
|
in
|
||||||
let preprocess =
|
Per_module.map preprocess ~f:(function
|
||||||
Per_module.map preprocess ~f:(function
|
| Preprocess.No_preprocessing ->
|
||||||
| Preprocess.No_preprocessing ->
|
(fun m ~lint ->
|
||||||
(fun m ->
|
let ast = setup_reason_rules sctx ~dir m in
|
||||||
let ast = setup_reason_rules sctx ~dir m in
|
if lint then lint_module ~ast ~source:m;
|
||||||
lint_module ~ast ~source:m;
|
ast)
|
||||||
ast)
|
| Action (loc, action) ->
|
||||||
| Action (loc, action) ->
|
(fun m ~lint ->
|
||||||
(fun m ->
|
let ast =
|
||||||
let ast =
|
pped_module m ~dir ~f:(fun _kind src dst ->
|
||||||
pped_module m ~dir ~f:(fun _kind src dst ->
|
|
||||||
SC.add_rule sctx
|
|
||||||
(preprocessor_deps
|
|
||||||
>>>
|
|
||||||
Build.path src
|
|
||||||
>>^ (fun _ -> [src])
|
|
||||||
>>>
|
|
||||||
SC.Action.run sctx
|
|
||||||
(Redirect
|
|
||||||
(Stdout,
|
|
||||||
target_var,
|
|
||||||
Chdir (root_var,
|
|
||||||
action)))
|
|
||||||
~loc
|
|
||||||
~dir
|
|
||||||
~dep_kind
|
|
||||||
~targets:(Static [dst])
|
|
||||||
~scope))
|
|
||||||
|> setup_reason_rules sctx ~dir in
|
|
||||||
lint_module ~ast ~source:m;
|
|
||||||
ast)
|
|
||||||
| Pps { pps; flags } ->
|
|
||||||
let ppx_exe = get_ppx_driver sctx ~scope pps in
|
|
||||||
let uses_ppx_driver = uses_ppx_driver ~pps in
|
|
||||||
let args : _ Arg_spec.t =
|
|
||||||
S [ As flags
|
|
||||||
; A "--dump-ast"
|
|
||||||
; As (cookie_library_name lib_name)
|
|
||||||
; As (if uses_ppx_driver then ["-diff-cmd"; "-"] else [])
|
|
||||||
]
|
|
||||||
in
|
|
||||||
(fun m ->
|
|
||||||
let ast = setup_reason_rules sctx ~dir m in
|
|
||||||
lint_module ~ast ~source:m;
|
|
||||||
pped_module ast ~dir ~f:(fun kind src dst ->
|
|
||||||
SC.add_rule sctx
|
SC.add_rule sctx
|
||||||
(promote_correction ~uses_ppx_driver
|
(preprocessor_deps
|
||||||
(Option.value_exn (Module.file m ~dir kind))
|
>>>
|
||||||
(preprocessor_deps
|
Build.path src
|
||||||
>>>
|
>>^ (fun _ -> [src])
|
||||||
Build.run ~context:(SC.context sctx)
|
>>>
|
||||||
(Ok ppx_exe)
|
SC.Action.run sctx
|
||||||
[ args
|
(Redirect
|
||||||
; A "-o"; Target dst
|
(Stdout,
|
||||||
; Ml_kind.ppx_driver_flag kind; Dep src
|
target_var,
|
||||||
])))))
|
Chdir (root_var,
|
||||||
in
|
action)))
|
||||||
Module.Name.Map.map modules ~f:(fun (m : Module.t) ->
|
~loc
|
||||||
Per_module.get preprocess m.name m)
|
~dir
|
||||||
|
~dep_kind
|
||||||
|
~targets:(Static [dst])
|
||||||
|
~scope))
|
||||||
|
|> setup_reason_rules sctx ~dir in
|
||||||
|
if lint then lint_module ~ast ~source:m;
|
||||||
|
ast)
|
||||||
|
| Pps { pps; flags } ->
|
||||||
|
let ppx_exe = get_ppx_driver sctx ~scope pps in
|
||||||
|
let uses_ppx_driver = uses_ppx_driver ~pps in
|
||||||
|
let args : _ Arg_spec.t =
|
||||||
|
S [ As flags
|
||||||
|
; A "--dump-ast"
|
||||||
|
; As (cookie_library_name lib_name)
|
||||||
|
; As (if uses_ppx_driver then ["-diff-cmd"; "-"] else [])
|
||||||
|
]
|
||||||
|
in
|
||||||
|
(fun m ~lint ->
|
||||||
|
let ast = setup_reason_rules sctx ~dir m in
|
||||||
|
if lint then lint_module ~ast ~source:m;
|
||||||
|
pped_module ast ~dir ~f:(fun kind src dst ->
|
||||||
|
SC.add_rule sctx
|
||||||
|
(promote_correction ~uses_ppx_driver
|
||||||
|
(Option.value_exn (Module.file m ~dir kind))
|
||||||
|
(preprocessor_deps
|
||||||
|
>>>
|
||||||
|
Build.run ~context:(SC.context sctx)
|
||||||
|
(Ok ppx_exe)
|
||||||
|
[ args
|
||||||
|
; A "-o"; Target dst
|
||||||
|
; Ml_kind.ppx_driver_flag kind; Dep src
|
||||||
|
])))))
|
||||||
|
|
||||||
|
let pp_modules t ?(lint=true) modules =
|
||||||
|
Module.Name.Map.map modules ~f:(fun (m : Module.t) ->
|
||||||
|
Per_module.get t m.name m ~lint)
|
||||||
|
|
||||||
|
let pp_module_as t ?(lint=true) name m =
|
||||||
|
Per_module.get t name m ~lint
|
||||||
|
|
|
@ -2,19 +2,38 @@
|
||||||
|
|
||||||
open! Import
|
open! Import
|
||||||
|
|
||||||
(** Setup pre-processing and linting rules and return the list of
|
(** Preprocessing object *)
|
||||||
pre-processed modules *)
|
type t
|
||||||
val pp_and_lint_modules
|
|
||||||
|
val dummy : t
|
||||||
|
|
||||||
|
val make
|
||||||
: Super_context.t
|
: Super_context.t
|
||||||
-> dir:Path.t
|
-> dir:Path.t
|
||||||
-> dep_kind:Build.lib_dep_kind
|
-> dep_kind:Build.lib_dep_kind
|
||||||
-> modules:Module.t Module.Name.Map.t
|
|
||||||
-> lint:Jbuild.Preprocess_map.t
|
-> lint:Jbuild.Preprocess_map.t
|
||||||
-> preprocess:Jbuild.Preprocess_map.t
|
-> preprocess:Jbuild.Preprocess_map.t
|
||||||
-> preprocessor_deps:(unit, Path.t list) Build.t
|
-> preprocessor_deps:(unit, Path.t list) Build.t
|
||||||
-> lib_name:string option
|
-> lib_name:string option
|
||||||
-> scope:Scope.t
|
-> scope:Scope.t
|
||||||
-> Module.t Module.Name.Map.t
|
-> t
|
||||||
|
|
||||||
|
(** Setup the preprocessing rules for the following modules and
|
||||||
|
returns the translated modules *)
|
||||||
|
val pp_modules
|
||||||
|
: t
|
||||||
|
-> ?lint:bool
|
||||||
|
-> Module.t Module.Name.Map.t
|
||||||
|
-> Module.t Module.Name.Map.t
|
||||||
|
|
||||||
|
(** Preprocess a single module, using the configuration for the given
|
||||||
|
module name. *)
|
||||||
|
val pp_module_as
|
||||||
|
: t
|
||||||
|
-> ?lint:bool
|
||||||
|
-> Module.Name.t
|
||||||
|
-> Module.t
|
||||||
|
-> Module.t
|
||||||
|
|
||||||
(** Get a path to a cached ppx driver *)
|
(** Get a path to a cached ppx driver *)
|
||||||
val get_ppx_driver
|
val get_ppx_driver
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
type t = ..
|
|
@ -0,0 +1,3 @@
|
||||||
|
(** Stanza in dune/jbuild files *)
|
||||||
|
|
||||||
|
type t = ..
|
|
@ -60,7 +60,7 @@ let internal_lib_names t =
|
||||||
List.fold_left t.stanzas ~init:String.Set.empty
|
List.fold_left t.stanzas ~init:String.Set.empty
|
||||||
~f:(fun acc { Dir_with_jbuild. stanzas; _ } ->
|
~f:(fun acc { Dir_with_jbuild. stanzas; _ } ->
|
||||||
List.fold_left stanzas ~init:acc ~f:(fun acc -> function
|
List.fold_left stanzas ~init:acc ~f:(fun acc -> function
|
||||||
| Stanza.Library lib ->
|
| Library lib ->
|
||||||
String.Set.add
|
String.Set.add
|
||||||
(match lib.public with
|
(match lib.public with
|
||||||
| None -> acc
|
| None -> acc
|
||||||
|
@ -331,7 +331,7 @@ let create
|
||||||
List.iter stanzas
|
List.iter stanzas
|
||||||
~f:(fun { Dir_with_jbuild. ctx_dir; scope; stanzas; _ } ->
|
~f:(fun { Dir_with_jbuild. ctx_dir; scope; stanzas; _ } ->
|
||||||
List.iter stanzas ~f:(function
|
List.iter stanzas ~f:(function
|
||||||
| Stanza.Env config ->
|
| Env config ->
|
||||||
let inherit_from =
|
let inherit_from =
|
||||||
if ctx_dir = Scope.root scope then
|
if ctx_dir = Scope.root scope then
|
||||||
None
|
None
|
||||||
|
|
23
src/utop.ml
23
src/utop.ml
|
@ -62,7 +62,7 @@ let setup sctx ~dir ~(libs : Library.t list) ~scope =
|
||||||
; syntax = Module.Syntax.OCaml
|
; syntax = Module.Syntax.OCaml
|
||||||
}
|
}
|
||||||
; intf = None
|
; intf = None
|
||||||
; obj_name = "" } in
|
; obj_name = exe_name } in
|
||||||
let utop_exe_dir = utop_exe_dir ~dir in
|
let utop_exe_dir = utop_exe_dir ~dir in
|
||||||
let requires =
|
let requires =
|
||||||
let open Result.O in
|
let open Result.O in
|
||||||
|
@ -70,16 +70,19 @@ let setup sctx ~dir ~(libs : Library.t list) ~scope =
|
||||||
("utop" :: List.map libs ~f:(fun (lib : Library.t) -> lib.name))
|
("utop" :: List.map libs ~f:(fun (lib : Library.t) -> lib.name))
|
||||||
>>= Lib.closure
|
>>= Lib.closure
|
||||||
in
|
in
|
||||||
Exe.build_and_link sctx
|
let cctx =
|
||||||
~dir:utop_exe_dir
|
Compilation_context.create ()
|
||||||
~obj_dir:utop_exe_dir
|
~super_context:sctx
|
||||||
|
~scope
|
||||||
|
~dir:utop_exe_dir
|
||||||
|
~modules
|
||||||
|
~requires
|
||||||
|
~flags:(Ocaml_flags.append_common
|
||||||
|
(Ocaml_flags.default ~profile:(Super_context.profile sctx))
|
||||||
|
["-w"; "-24"])
|
||||||
|
in
|
||||||
|
Exe.build_and_link cctx
|
||||||
~program:{ name = exe_name ; main_module_name }
|
~program:{ name = exe_name ; main_module_name }
|
||||||
~modules
|
|
||||||
~scope
|
|
||||||
~linkages:[Exe.Linkage.custom]
|
~linkages:[Exe.Linkage.custom]
|
||||||
~requires
|
|
||||||
~flags:(Ocaml_flags.append_common
|
|
||||||
(Ocaml_flags.default ~profile:(Super_context.profile sctx))
|
|
||||||
["-w"; "-24"])
|
|
||||||
~link_flags:(Build.return ["-linkall"; "-warn-error"; "-31"]);
|
~link_flags:(Build.return ["-linkall"; "-warn-error"; "-31"]);
|
||||||
add_module_rules sctx ~dir:utop_exe_dir requires
|
add_module_rules sctx ~dir:utop_exe_dir requires
|
||||||
|
|
Loading…
Reference in New Issue