diff --git a/src/dune_rules/install_rules.ml b/src/dune_rules/install_rules.ml index 41e86d04de99..7d3f5ee3eac5 100644 --- a/src/dune_rules/install_rules.ml +++ b/src/dune_rules/install_rules.ml @@ -117,12 +117,16 @@ end = struct Install.Entry.Sourced.create ~loc entry in let* installable_modules = - let+ ml_sources = Dir_contents.ocaml dir_contents in - Ml_sources.modules ml_sources ~for_:(Library (Library.best_name lib)) - |> Modules.fold_no_vlib ~init:[] ~f:(fun m acc -> m :: acc) + let* ml_sources = Dir_contents.ocaml dir_contents in + let modules = + Ml_sources.modules ml_sources ~for_:(Library (Library.best_name lib)) + in + let+ impl = Virtual_rules.impl sctx ~lib ~scope in + let modules = Vimpl.impl_modules impl modules in + Modules.split_by_lib modules in let sources = - List.concat_map installable_modules ~f:(fun m -> + List.concat_map installable_modules.impl ~f:(fun m -> List.map (Module.sources m) ~f:(fun source -> (* We add the -gen suffix to a few files generated by dune, such as the alias module. *) @@ -153,7 +157,8 @@ end = struct Path.basename dir' |> inside_subdir |> Option.some in let virtual_library = Library.is_virtual lib in - List.concat_map installable_modules ~f:(fun m -> + let modules = + let common m = let cm_file kind = Obj_dir.Module.cm_file obj_dir m ~kind in let if_ b (cm_kind, f) = if b then @@ -163,7 +168,6 @@ end = struct else [] in - let cm_dir = cm_dir m in let open Cm_kind in [ if_ true (Cmi, cm_file Cmi) ; if_ native (Cmx, cm_file Cmx) @@ -171,13 +175,31 @@ end = struct ; if_ (native && virtual_library) (Cmx, Obj_dir.Module.o_file obj_dir m ~ext_obj) - ; List.filter_map Ml_kind.all ~f:(fun ml_kind -> - let open Option.O in - let+ cmt = Obj_dir.Module.cmt_file obj_dir m ~ml_kind in - (Cmi, cmt)) ] |> List.concat - |> List.map ~f:(fun (cm_kind, f) -> (cm_dir cm_kind, f))) + in + let set_dir m = + List.map ~f:(fun (cm_kind, p) -> (cm_dir m cm_kind, p)) + in + let modules_impl = + List.concat_map installable_modules.impl ~f:(fun m -> + common m + @ List.filter_map Ml_kind.all ~f:(fun ml_kind -> + let open Option.O in + let+ cmt = Obj_dir.Module.cmt_file obj_dir m ~ml_kind in + (Cm_kind.Cmi, cmt)) + |> set_dir m) + in + let modules_vlib = + List.concat_map installable_modules.vlib ~f:(fun m -> + if Module.kind m = Virtual then + [] + else + common m |> set_dir m) + in + modules_vlib @ modules_impl + in + modules in let* lib_files, dll_files = let+ lib_files = lib_files ~dir ~dir_contents ~lib_config info in diff --git a/src/dune_rules/modules.ml b/src/dune_rules/modules.ml index f2dbf2b798bf..94131a54cdbe 100644 --- a/src/dune_rules/modules.ml +++ b/src/dune_rules/modules.ml @@ -618,6 +618,29 @@ let rec fold_no_vlib t ~init ~f = | Wrapped w -> Wrapped.fold w ~init ~f | Impl { vlib = _; impl } -> fold_no_vlib impl ~f ~init +let rec map t ~f = + match t with + | Stdlib w -> Stdlib (Stdlib.map w ~f) + | Singleton m -> Singleton (f m) + | Unwrapped m -> Unwrapped (Module_name.Map.map m ~f) + | Wrapped w -> Wrapped (Wrapped.map w ~f) + | Impl { vlib; impl } -> Impl { vlib = map vlib ~f; impl = map impl ~f } + +type split_by_lib = + { vlib : Module.t list + ; impl : Module.t list + } + +let split_by_lib t = + let f m acc = m :: acc in + let init = [] in + match t with + | Impl { vlib; impl } -> + let vlib = fold_no_vlib vlib ~init ~f in + let impl = fold_no_vlib impl ~init ~f in + { vlib; impl } + | _ -> { impl = fold_no_vlib t ~init ~f; vlib = [] } + let compat_for_exn t m = match t with | Singleton _ diff --git a/src/dune_rules/modules.mli b/src/dune_rules/modules.mli index e2440dacb1d2..b275b82c6fb1 100644 --- a/src/dune_rules/modules.mli +++ b/src/dune_rules/modules.mli @@ -57,6 +57,8 @@ val fold_user_written : t -> f:(Module.t -> 'acc -> 'acc) -> init:'acc -> 'acc val map_user_written : t -> f:(Module.t -> Module.t Memo.Build.t) -> t Memo.Build.t +val map : t -> f:(Module.t -> Module.t) -> t + val fold_user_available : t -> f:(Module.t -> 'acc -> 'acc) -> init:'acc -> 'acc (** Returns all the compatibility modules. *) @@ -112,5 +114,12 @@ val as_singleton : t -> Module.t option val source_dirs : t -> Path.Set.t +type split_by_lib = + { vlib : Module.t list + ; impl : Module.t list + } + +val split_by_lib : t -> split_by_lib + (** [has_impl t] is true if there's at least one implementation in [t]*) val has_impl : t -> bool diff --git a/test/blackbox-tests/test-cases/virtual-libraries/dune-package-info.t/run.t b/test/blackbox-tests/test-cases/virtual-libraries/dune-package-info.t/run.t index 6538703acc9a..2096b542b127 100644 --- a/test/blackbox-tests/test-cases/virtual-libraries/dune-package-info.t/run.t +++ b/test/blackbox-tests/test-cases/virtual-libraries/dune-package-info.t/run.t @@ -14,6 +14,8 @@ Include variants and implementation information in dune-package impl/impl$ext_lib impl/impl.cma impl/impl.cmxa + impl/vlib.cmi + impl/vlib.cmx impl/vlib__Vmod.cmi impl/vlib__Vmod.cmt impl/vlib__Vmod.cmx diff --git a/test/blackbox-tests/test-cases/virtual-libraries/implements-external.t/run.t b/test/blackbox-tests/test-cases/virtual-libraries/implements-external.t/run.t index 350ce4918850..18a6a1307bdd 100644 --- a/test/blackbox-tests/test-cases/virtual-libraries/implements-external.t/run.t +++ b/test/blackbox-tests/test-cases/virtual-libraries/implements-external.t/run.t @@ -45,9 +45,6 @@ modules remain hidden. > Vlib.Foo.run () > EOF $ dune exec ./blah.exe - File "blah.ml", line 1, characters 0-12: - 1 | Vlib.Foo.run () - ^^^^^^^^^^^^ - Error: Unbound module Vlib - [1] + bar from vlib + Foo.run implemented $ cd .. diff --git a/test/blackbox-tests/test-cases/virtual-libraries/install-file.t/run.t b/test/blackbox-tests/test-cases/virtual-libraries/install-file.t/run.t index a1ed036ca993..abb35d6388e3 100644 --- a/test/blackbox-tests/test-cases/virtual-libraries/install-file.t/run.t +++ b/test/blackbox-tests/test-cases/virtual-libraries/install-file.t/run.t @@ -22,6 +22,8 @@ Install files for implementations and virtual libs have all the artifacts: "_build/install/default/lib/impl/impl.cma" "_build/install/default/lib/impl/impl.cmxa" "_build/install/default/lib/impl/opam" + "_build/install/default/lib/impl/vlib.cmi" + "_build/install/default/lib/impl/vlib.cmx" "_build/install/default/lib/impl/vlib__Foo.cmi" "_build/install/default/lib/impl/vlib__Foo.cmt" "_build/install/default/lib/impl/vlib__Foo.cmx" diff --git a/test/blackbox-tests/test-cases/virtual-libraries/vlib-default-impl.t/run.t b/test/blackbox-tests/test-cases/virtual-libraries/vlib-default-impl.t/run.t index 4f380d807537..0029c66bce0a 100644 --- a/test/blackbox-tests/test-cases/virtual-libraries/vlib-default-impl.t/run.t +++ b/test/blackbox-tests/test-cases/virtual-libraries/vlib-default-impl.t/run.t @@ -35,6 +35,8 @@ Check that default implementation data is installed in the dune package file. a$ext_obj a__X.cmi a__X.cmti + default-impl/a.cmi + default-impl/a.cmx default-impl/a__X.cmi default-impl/a__X.cmt default-impl/a__X.cmx