Report an error for invalid dependency between modules in wrapped libraries

Report an error when in a wrapped library, a module that is not the
toplevel module depends on the toplevel module. This doesn't make as
such a module would in theory be inaccessible from the outside

If this causes compilation failures of released packages, we'll need
to turn this into a warning.
This commit is contained in:
Jeremie Dimino 2017-06-09 12:24:34 +01:00
parent 017e0abbe8
commit 572774490a
4 changed files with 34 additions and 7 deletions

View File

@ -4,6 +4,10 @@
- Fix the error message when there are more than one `<package>.opam` - Fix the error message when there are more than one `<package>.opam`
file for a given pacakge file for a given pacakge
- Report an error when in a wrapped library, a module that is not the
toplevel module depends on the toplevel module. This doesn't make as
such a module would in theory be inaccessible from the outside
1.0+beta10 (08/06/2017) 1.0+beta10 (08/06/2017)
----------------------- -----------------------

View File

@ -233,7 +233,13 @@ module Gen(P : Params) = struct
| Some m -> String_map.add modules ~key:m.name ~data:m | Some m -> String_map.add modules ~key:m.name ~data:m
in in
let dep_graph = Ocamldep.rules sctx ~dir ~item:lib.name ~modules ~alias_module in let dep_graph =
Ocamldep.rules sctx ~dir ~item:lib.name ~modules ~alias_module
~lib_interface_module:(if lib.wrapped then
String_map.find main_module_name modules
else
None)
in
Option.iter alias_module ~f:(fun m -> Option.iter alias_module ~f:(fun m ->
SC.add_rule sctx SC.add_rule sctx
@ -465,7 +471,10 @@ module Gen(P : Params) = struct
~scope ~scope
in in
let item = List.hd exes.names in let item = List.hd exes.names in
let dep_graph = Ocamldep.rules sctx ~dir ~item ~modules ~alias_module:None in let dep_graph =
Ocamldep.rules sctx ~dir ~item ~modules ~alias_module:None
~lib_interface_module:None
in
let requires, real_requires = let requires, real_requires =
SC.Libs.requires sctx ~dir ~dep_kind ~item SC.Libs.requires sctx ~dir ~dep_kind ~item

View File

@ -5,7 +5,7 @@ module SC = Super_context
type dep_graph = (unit, string list String_map.t) Build.t Ml_kind.Dict.t type dep_graph = (unit, string list String_map.t) Build.t Ml_kind.Dict.t
let parse_deps ~dir lines ~modules ~alias_module = let parse_deps ~dir lines ~modules ~alias_module ~lib_interface_module =
List.map lines ~f:(fun line -> List.map lines ~f:(fun line ->
match String.index line ':' with match String.index line ':' with
| None -> die "`ocamldep` in %s returned invalid line: %S" (Path.to_string dir) line | None -> die "`ocamldep` in %s returned invalid line: %S" (Path.to_string dir) line
@ -27,6 +27,17 @@ let parse_deps ~dir lines ~modules ~alias_module =
~len:(String.length line - (i + 1))) ~len:(String.length line - (i + 1)))
|> List.filter ~f:(fun m -> m <> unit && String_map.mem m modules) |> List.filter ~f:(fun m -> m <> unit && String_map.mem m modules)
in in
(match lib_interface_module with
| None -> ()
| Some (m : Module.t) ->
if unit <> m.name && List.mem m.name ~set:deps then
die "Module %s in directory %s depends on %s.\n\
This doesn't make sense to me.\n\
\n\
%s is the main module of the library and is the only module exposed \n\
outside of the library. Consequently it should be the one dependending \n\
on all the other modules in the library."
unit (Path.to_string dir) m.name m.name);
let deps = let deps =
match alias_module with match alias_module with
| None -> deps | None -> deps
@ -44,7 +55,7 @@ let parse_deps ~dir lines ~modules ~alias_module =
die die
"`ocamldep` in %s returned %s several times" (Path.to_string dir) unit "`ocamldep` in %s returned %s several times" (Path.to_string dir) unit
let rules sctx ~ml_kind ~dir ~item ~modules ~alias_module = let rules sctx ~ml_kind ~dir ~item ~modules ~alias_module ~lib_interface_module =
let suffix = Ml_kind.suffix ml_kind in let suffix = Ml_kind.suffix ml_kind in
let files = let files =
List.filter_map (String_map.values modules) ~f:(fun m -> Module.file ~dir m ml_kind) List.filter_map (String_map.values modules) ~f:(fun m -> Module.file ~dir m ml_kind)
@ -64,7 +75,7 @@ let rules sctx ~ml_kind ~dir ~item ~modules ~alias_module =
~stdout_to:ocamldep_output); ~stdout_to:ocamldep_output);
Build.memoize (Path.to_string ocamldep_output) Build.memoize (Path.to_string ocamldep_output)
(Build.lines_of ocamldep_output (Build.lines_of ocamldep_output
>>^ parse_deps ~dir ~modules ~alias_module) >>^ parse_deps ~dir ~modules ~alias_module ~lib_interface_module)
module Dep_closure = module Dep_closure =
Top_closure.Make(String)(struct Top_closure.Make(String)(struct
@ -87,5 +98,5 @@ let names_to_top_closed_cm_files ~dir ~dep_graph ~modules ~mode names =
let m = Utils.find_module ~dir modules name in let m = Utils.find_module ~dir modules name in
Module.cm_file m ~dir cm_kind) Module.cm_file m ~dir cm_kind)
let rules sctx ~dir ~item ~modules ~alias_module = let rules sctx ~dir ~item ~modules ~alias_module ~lib_interface_module =
Ml_kind.Dict.of_func (rules sctx ~dir ~item ~modules ~alias_module) Ml_kind.Dict.of_func (rules sctx ~dir ~item ~modules ~alias_module ~lib_interface_module)

View File

@ -7,6 +7,8 @@ type dep_graph = (unit, string list String_map.t) Build.t Ml_kind.Dict.t
(** Generate ocamldep rules for the given modules. [item] is either the internal name of a (** Generate ocamldep rules for the given modules. [item] is either the internal name of a
library of the first name of a list of executables. library of the first name of a list of executables.
For wrapped libraries, [lib_interface_module] is the main module of the library.
Return arrows that evaluate to the dependency graphs. Return arrows that evaluate to the dependency graphs.
*) *)
val rules val rules
@ -15,6 +17,7 @@ val rules
-> item:string -> item:string
-> modules:Module.t String_map.t -> modules:Module.t String_map.t
-> alias_module:Module.t option -> alias_module:Module.t option
-> lib_interface_module:Module.t option
-> dep_graph -> dep_graph
(** Close and convert a list of module names to a list of .cm file names *) (** Close and convert a list of module names to a list of .cm file names *)