Move ocamldep stuff to Ocamldep

This commit is contained in:
Jeremie Dimino 2017-04-28 14:19:21 +01:00
parent 6a40b7602c
commit c6080880b3
3 changed files with 132 additions and 106 deletions

View File

@ -16,108 +16,6 @@ module Gen(P : Params) = struct
let ctx = SC.context sctx
(* +-----------------------------------------------------------------+
| ocamldep stuff |
+-----------------------------------------------------------------+ *)
let parse_deps ~dir lines ~modules ~alias_module =
List.map lines ~f:(fun line ->
match String.index line ':' with
| None -> die "`ocamldep` in %s returned invalid line: %S" (Path.to_string dir) line
| Some i ->
let unit =
let basename =
String.sub line ~pos:0 ~len:i
|> Filename.basename
in
let module_basename =
match String.index basename '.' with
| None -> basename
| Some i -> String.sub basename ~pos:0 ~len:i
in
String.capitalize_ascii module_basename
in
let deps =
String.extract_blank_separated_words (String.sub line ~pos:(i + 1)
~len:(String.length line - (i + 1)))
|> List.filter ~f:(fun m -> m <> unit && String_map.mem m modules)
in
let deps =
match alias_module with
| None -> deps
| Some (m : Module.t) -> m.name :: deps
in
(unit, deps))
|> String_map.of_alist
|> function
| Ok x -> begin
match alias_module with
| None -> x
| Some m -> String_map.add x ~key:m.name ~data:[]
end
| Error (unit, _, _) ->
die
"`ocamldep` in %s returned %s several times" (Path.to_string dir) unit
module Ocamldep_vfile =
Vfile_kind.Make
(struct type t = string list String_map.t end)
(functor (C : Sexp.Combinators) -> struct
open C
let t = string_map (list string)
end)
let ocamldep_rules ~ml_kind ~dir ~item ~modules ~alias_module =
let suffix = Ml_kind.suffix ml_kind in
let vdepends =
let fn = Path.relative dir (sprintf "%s.depends%s.sexp" item suffix) in
Build.Vspec.T (fn, (module Ocamldep_vfile))
in
let files =
List.filter_map (String_map.values modules) ~f:(fun m -> Module.file ~dir m ml_kind)
|> List.map ~f:(fun fn ->
match ml_kind, Filename.extension (Path.to_string fn) with
| Impl, ".ml" -> Arg_spec.Dep fn
| Intf, ".mli" -> Dep fn
| Impl, _ -> S [A "-impl"; Dep fn]
| Intf, _ -> S [A "-intf"; Dep fn])
in
let ocamldep_output =
Path.relative dir (sprintf "%s.depends%s.ocamldep-output" item suffix)
in
SC.add_rule sctx
(Build.run ~context:ctx (Dep ctx.ocamldep) [A "-modules"; S files]
~stdout_to:ocamldep_output);
SC.add_rule sctx
(Build.lines_of ocamldep_output
>>^ parse_deps ~dir ~modules ~alias_module
>>> Build.store_vfile vdepends);
Build.vpath vdepends
module Dep_closure =
Top_closure.Make(String)(struct
type t = string
type graph = Path.t * t list String_map.t
let key t = t
let deps t (dir, map) = Utils.find_deps ~dir map t
end)
let dep_closure ~dir dep_graph names =
match Dep_closure.top_closure (dir, dep_graph) names with
| Ok names -> names
| Error cycle ->
die "dependency cycle between modules in %s:\n %s" (Path.to_string dir)
(String.concat cycle ~sep:"\n-> ")
let names_to_top_closed_cm_files ~dir ~dep_graph ~modules ~mode names =
let cm_kind = Mode.cm_kind mode in
List.map (dep_closure ~dir dep_graph names) ~f:(fun name ->
let m = Utils.find_module ~dir modules name in
Module.cm_file m ~dir cm_kind)
let ocamldep_rules ~dir ~item ~modules ~alias_module =
Ml_kind.Dict.of_func (ocamldep_rules ~dir ~item ~modules ~alias_module)
(* +-----------------------------------------------------------------+
| User actions |
+-----------------------------------------------------------------+ *)
@ -769,7 +667,7 @@ module Gen(P : Params) = struct
(Build.fanout
(dep_graph >>>
Build.arr (fun dep_graph ->
names_to_top_closed_cm_files
Ocamldep.names_to_top_closed_cm_files
~dir
~dep_graph
~modules
@ -927,7 +825,7 @@ module Gen(P : Params) = struct
| Some m -> String_map.add modules ~key:m.name ~data:m
in
let dep_graph = ocamldep_rules ~dir ~item:lib.name ~modules ~alias_module in
let dep_graph = Ocamldep.rules sctx ~dir ~item:lib.name ~modules ~alias_module in
Option.iter alias_module ~f:(fun m ->
SC.add_rule sctx
@ -1081,7 +979,7 @@ module Gen(P : Params) = struct
>>> Build.dyn_paths (Build.arr (Lib.archive_files ~mode ~ext_lib:ctx.ext_lib)))
(dep_graph
>>> Build.arr (fun dep_graph ->
names_to_top_closed_cm_files
Ocamldep.names_to_top_closed_cm_files
~dir
~dep_graph
~modules
@ -1118,7 +1016,7 @@ module Gen(P : Params) = struct
~lib_name:None
in
let item = List.hd exes.names in
let dep_graph = ocamldep_rules ~dir ~item ~modules ~alias_module:None in
let dep_graph = Ocamldep.rules sctx ~dir ~item ~modules ~alias_module:None in
let requires, real_requires =
requires ~dir ~dep_kind ~item

103
src/ocamldep.ml Normal file
View File

@ -0,0 +1,103 @@
open Import
open Build.O
module SC = Super_context
let parse_deps ~dir lines ~modules ~alias_module =
List.map lines ~f:(fun line ->
match String.index line ':' with
| None -> die "`ocamldep` in %s returned invalid line: %S" (Path.to_string dir) line
| Some i ->
let unit =
let basename =
String.sub line ~pos:0 ~len:i
|> Filename.basename
in
let module_basename =
match String.index basename '.' with
| None -> basename
| Some i -> String.sub basename ~pos:0 ~len:i
in
String.capitalize_ascii module_basename
in
let deps =
String.extract_blank_separated_words (String.sub line ~pos:(i + 1)
~len:(String.length line - (i + 1)))
|> List.filter ~f:(fun m -> m <> unit && String_map.mem m modules)
in
let deps =
match alias_module with
| None -> deps
| Some (m : Module.t) -> m.name :: deps
in
(unit, deps))
|> String_map.of_alist
|> function
| Ok x -> begin
match alias_module with
| None -> x
| Some m -> String_map.add x ~key:m.name ~data:[]
end
| Error (unit, _, _) ->
die
"`ocamldep` in %s returned %s several times" (Path.to_string dir) unit
module Ocamldep_vfile =
Vfile_kind.Make
(struct type t = string list String_map.t end)
(functor (C : Sexp.Combinators) -> struct
open C
let t = string_map (list string)
end)
let rules sctx ~ml_kind ~dir ~item ~modules ~alias_module =
let suffix = Ml_kind.suffix ml_kind in
let vdepends =
let fn = Path.relative dir (sprintf "%s.depends%s.sexp" item suffix) in
Build.Vspec.T (fn, (module Ocamldep_vfile))
in
let files =
List.filter_map (String_map.values modules) ~f:(fun m -> Module.file ~dir m ml_kind)
|> List.map ~f:(fun fn ->
match ml_kind, Filename.extension (Path.to_string fn) with
| Impl, ".ml" -> Arg_spec.Dep fn
| Intf, ".mli" -> Dep fn
| Impl, _ -> S [A "-impl"; Dep fn]
| Intf, _ -> S [A "-intf"; Dep fn])
in
let ocamldep_output =
Path.relative dir (sprintf "%s.depends%s.ocamldep-output" item suffix)
in
let ctx = SC.context sctx in
SC.add_rule sctx
(Build.run ~context:ctx (Dep ctx.ocamldep) [A "-modules"; S files]
~stdout_to:ocamldep_output);
SC.add_rule sctx
(Build.lines_of ocamldep_output
>>^ parse_deps ~dir ~modules ~alias_module
>>> Build.store_vfile vdepends);
Build.vpath vdepends
module Dep_closure =
Top_closure.Make(String)(struct
type t = string
type graph = Path.t * t list String_map.t
let key t = t
let deps t (dir, map) = Utils.find_deps ~dir map t
end)
let dep_closure ~dir dep_graph names =
match Dep_closure.top_closure (dir, dep_graph) names with
| Ok names -> names
| Error cycle ->
die "dependency cycle between modules in %s:\n %s" (Path.to_string dir)
(String.concat cycle ~sep:"\n-> ")
let names_to_top_closed_cm_files ~dir ~dep_graph ~modules ~mode names =
let cm_kind = Mode.cm_kind mode in
List.map (dep_closure ~dir dep_graph names) ~f:(fun name ->
let m = Utils.find_module ~dir modules name in
Module.cm_file m ~dir cm_kind)
let rules sctx ~dir ~item ~modules ~alias_module =
Ml_kind.Dict.of_func (rules sctx ~dir ~item ~modules ~alias_module)

25
src/ocamldep.mli Normal file
View File

@ -0,0 +1,25 @@
(** ocamldep managenemt *)
open Import
(** 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.
Return arrows that evaluate to the dependency graphs.
*)
val rules
: Super_context.t
-> dir:Path.t
-> 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
(** Close and convert a list of module names to a list of .cm file names *)
val names_to_top_closed_cm_files
: dir:Path.t
-> dep_graph:string list String_map.t
-> modules:Module.t String_map.t
-> mode:Mode.t
-> string list
-> Path.t list