From 17ec2c301a519e40f1073496e8d15c8aa4c883d1 Mon Sep 17 00:00:00 2001 From: Antonio Nuno Monteiro Date: Mon, 1 Apr 2024 17:36:16 -0700 Subject: [PATCH] fix(ml-sources): check that a library is available before tracking it Since #10307, dune started allowing libraries to share the same name. Thus, checking `enabled_if` isn't enough for libraries; dune now needs to check whether the library is available before tracking it in ml_sources Signed-off-by: Antonio Nuno Monteiro --- src/dune_rules/ml_sources.ml | 44 ++++++++++-------- .../lib-collision-private-optional.t | 46 +++++++++++++++++++ 2 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 test/blackbox-tests/test-cases/lib-collision/lib-collision-private-optional.t diff --git a/src/dune_rules/ml_sources.ml b/src/dune_rules/ml_sources.ml index eedb18e6218f..eb8cc184e498 100644 --- a/src/dune_rules/ml_sources.ml +++ b/src/dune_rules/ml_sources.ml @@ -465,25 +465,33 @@ let modules_of_stanzas = | true -> (match Stanza.repr stanza with | Library.T lib -> - (* jeremiedimino: this [Resolve.get] means that if the user writes an - invalid [implements] field, we will get an error immediately even if - the library is not built. We should change this to carry the - [Or_exn.t] a bit longer. *) - let+ sources, modules = - let lookup_vlib = lookup_vlib ~loc:lib.buildable.loc in - make_lib_modules - ~expander - ~dir - ~libs - ~lookup_vlib - ~modules - ~lib - ~include_subdirs - ~version:lib.dune_version - >>= Resolve.read_memo + let* available = + let* db = libs in + let src_dir = Path.drop_optional_build_context_src_exn (Path.build dir) in + Lib.DB.available_by_lib_id db (Local (Library.to_lib_id ~src_dir lib)) in - let obj_dir = Library.obj_dir lib ~dir in - `Library { Modules.stanza = lib; sources; modules; dir; obj_dir } + if not available + then Memo.return `Skip + else + (* jeremiedimino: this [Resolve.get] means that if the user writes an + invalid [implements] field, we will get an error immediately even if + the library is not built. We should change this to carry the + [Or_exn.t] a bit longer. *) + let+ sources, modules = + let lookup_vlib = lookup_vlib ~loc:lib.buildable.loc in + make_lib_modules + ~expander + ~dir + ~libs + ~lookup_vlib + ~modules + ~lib + ~include_subdirs + ~version:lib.dune_version + >>= Resolve.read_memo + in + let obj_dir = Library.obj_dir lib ~dir in + `Library { Modules.stanza = lib; sources; modules; dir; obj_dir } | Executables.T exes -> make_executables ~dir ~expander ~modules ~project exes | Tests.T { exes; _ } -> make_executables ~dir ~expander ~modules ~project exes | Melange_stanzas.Emit.T mel -> diff --git a/test/blackbox-tests/test-cases/lib-collision/lib-collision-private-optional.t b/test/blackbox-tests/test-cases/lib-collision/lib-collision-private-optional.t new file mode 100644 index 000000000000..b767969d8b35 --- /dev/null +++ b/test/blackbox-tests/test-cases/lib-collision/lib-collision-private-optional.t @@ -0,0 +1,46 @@ +Private libraries using the same library name, in the same context, defined in +the same folder. One of them is unavailable because it's `(optional)` and a +dependency is missing. + + $ cat > dune-project << EOF + > (lang dune 3.13) + > EOF + + $ cat > dune << EOF + > (library + > (name foo) + > (libraries xxx) + > (optional)) + > (library + > (name foo)) + > EOF + $ cat > foo.ml << EOF + > let x = "hello" + > EOF + +Without any consumers of the libraries + + $ dune build + +With some consumer of the library + + $ cat > dune << EOF + > (library + > (name foo) + > (modules foo) + > (libraries xxx) + > (optional)) + > (library + > (modules foo) + > (name foo)) + > (executable + > (name main) + > (modules main) + > (libraries foo)) + > EOF + + $ cat > main.ml < let () = print_endline Foo.x + > EOF + + $ dune build