From 4a68030f5faaff88ff1ea51a7aa6a02b702605c2 Mon Sep 17 00:00:00 2001 From: Lucas Pluvinage Date: Tue, 22 Dec 2020 12:17:55 +0100 Subject: [PATCH 1/4] add tests for libexec Signed-off-by: Lucas Pluvinage --- test/blackbox-tests/test-cases/lib.t/run.t | 1 - .../blackbox-tests/test-cases/libexec.t/run.t | 318 ++++++++++++++++++ 2 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 test/blackbox-tests/test-cases/libexec.t/run.t diff --git a/test/blackbox-tests/test-cases/lib.t/run.t b/test/blackbox-tests/test-cases/lib.t/run.t index 99dfdaad53f..c2fbf33b6d0 100644 --- a/test/blackbox-tests/test-cases/lib.t/run.t +++ b/test/blackbox-tests/test-cases/lib.t/run.t @@ -1,6 +1,5 @@ ---------------------------------------------------------------------------------- Testsuite for the %{lib...} and %{lib-private...} variable. -TODO: Fix %{libexec} and %{libexec-private} variables and test them. $ cat >sdune <<'EOF' > #!/usr/bin/env bash diff --git a/test/blackbox-tests/test-cases/libexec.t/run.t b/test/blackbox-tests/test-cases/libexec.t/run.t new file mode 100644 index 00000000000..4ae1b4e3004 --- /dev/null +++ b/test/blackbox-tests/test-cases/libexec.t/run.t @@ -0,0 +1,318 @@ +---------------------------------------------------------------------------------- +Testsuite for the %{libexec...} and %{libexec-private...} variable. + + $ cat >sdune <<'EOF' + > #!/usr/bin/env bash + > DUNE_SANDBOX=symlink dune "$@" + > EOF + $ chmod +x sdune + $ cat >dune-workspace < (lang dune 2.0) + > (context (default (name host))) + > (context (default + > (name target) + > (host host))) + > EOF + +---------------------------------------------------------------------------------- +* Find a host-context public library using the %{libexec:...} variable + + $ echo "(lang dune 2.8)" > dune-project + $ mkdir -p src + $ cat >src/dune < (library + > (name private_lib) + > (enabled_if (= %{context_name} host)) + > (public_name public_lib) + > (modules a)) + > EOF + + $ cat >dune < (rule + > (alias find-a-from-host) + > (enabled_if (= %{context_name} host)) + > (action (echo "%{libexec:public_lib:a.ml}"))) + > (rule + > (alias find-a-from-target) + > (enabled_if (= %{context_name} target)) + > (action (echo "%{libexec:public_lib:a.ml}"))) + > EOF + + $ cat >src/a.ml < let a = "A" + > EOF + $ cat >src/a.mli < val a : string + > EOF + + $ touch public_lib.opam + $ ./sdune build @find-a-from-host + ../install/host/lib/public_lib/a.ml + + $ ./sdune build @find-a-from-target + ../install/host/lib/public_lib/a.ml + +---------------------------------------------------------------------------------- +* Error when finding a host-context public library by its private name using the %{libexec:...} variable + + $ cat >src/dune < (library + > (name private_lib) + > (enabled_if (= %{context_name} host)) + > (public_name public_lib) + > (modules a)) + > EOF + + $ cat >dune < (rule + > (alias find-a-from-host) + > (enabled_if (= %{context_name} host)) + > (action (echo "%{libexec:private_lib:a.ml}"))) + > (rule + > (alias find-a-from-target) + > (enabled_if (= %{context_name} target)) + > (action (echo "%{libexec:private_lib:a.ml}"))) + > EOF + + $ ./sdune build @find-a-from-host + File "dune", line 4, characters 18-43: + 4 | (action (echo "%{libexec:private_lib:a.ml}"))) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + Error: The library "private_lib" is not public. The variable "libexec" + expands to the file's installation path which is not defined for private + libraries. + [1] + + $ ./sdune build @find-a-from-target + File "dune", line 8, characters 18-43: + 8 | (action (echo "%{libexec:private_lib:a.ml}"))) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + Error: The library "private_lib" is not public. The variable "libexec" + expands to the file's installation path which is not defined for private + libraries. + [1] + +---------------------------------------------------------------------------------- +* Find a host-context private library using the %{libexec-private:...} variable + + $ cat >src/dune < (library + > (name private_lib) + > (enabled_if (= %{context_name} host)) + > (modules a)) + > EOF + + $ cat >dune < (rule + > (alias find-a-from-host) + > (enabled_if (= %{context_name} host)) + > (action (echo "%{libexec-private:private_lib:a.ml}"))) + > (rule + > (alias find-a-from-target) + > (enabled_if (= %{context_name} target)) + > (action (echo "%{libexec-private:private_lib:a.ml}"))) + > EOF + + $ ./sdune clean + $ ./sdune build @find-a-from-host + src/a.ml + $ ./sdune build @find-a-from-target + ../host/src/a.ml + +---------------------------------------------------------------------------------- +* The %{libexec-private:...} variable works with public library names too + + $ cat >src/dune < (library + > (name private_lib) + > (enabled_if (= %{context_name} host)) + > (public_name public_lib) + > (modules a)) + > EOF + + $ cat >dune < (rule + > (alias find-a-from-host) + > (enabled_if (= %{context_name} host)) + > (action (echo "%{libexec-private:public_lib:a.ml}"))) + > (rule + > (alias find-a-from-target) + > (enabled_if (= %{context_name} target)) + > (action (echo "%{libexec-private:public_lib:a.ml}"))) + > EOF + + $ ./sdune clean + $ ./sdune build @find-a-from-host + src/a.ml + $ ./sdune build @find-a-from-target + ../host/src/a.ml + +---------------------------------------------------------------------------------- +* The %{libexec-private:...} variable does not work with external libraries + + $ mkdir -p external + $ cat >external/dune-project < (lang dune 2.8) + > (name external_library) + > EOF + $ cat >external/dune < (library + > (name extlib) + > (public_name external_library)) + > EOF + + $ touch external/external_library.opam + $ ( cd external && ../sdune build @install && ../sdune install --prefix install | dune_cmd sanitize) + Installing install/lib/external_library/META + Installing install/lib/external_library/dune-package + Installing install/lib/external_library/extlib.a + Installing install/lib/external_library/extlib.cma + Installing install/lib/external_library/extlib.cmi + Installing install/lib/external_library/extlib.cmt + Installing install/lib/external_library/extlib.cmx + Installing install/lib/external_library/extlib.cmxa + Installing install/lib/external_library/extlib.cmxs + Installing install/lib/external_library/extlib.ml + Installing install/lib/external_library/opam + + $ cat >src/dune < (library + > (name private_lib) + > (public_name public_lib) + > (modules a)) + > (rule + > (alias find-a-from-host) + > (enabled_if (= %{context_name} host)) + > (action (echo "%{libexec-private:external_library:opam}"))) + > (rule + > (alias find-a-from-target) + > (enabled_if (= %{context_name} target)) + > (action (echo "%{libexec-private:external_library:opam}"))) + > EOF + + $ touch src/public_lib.opam + $ echo "(lang dune 2.8)" > src/dune-project + $ echo "(name test-lib)" >> src/dune-project + + $ export OCAMLPATH=$PWD/external/install/lib; ./sdune build @find-a-from-host --root=src --workspace=./dune-workspace + Entering directory 'src' + File "dune", line 8, characters 18-56: + 8 | (action (echo "%{libexec-private:external_library:opam}"))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Error: The variable "libexec-private" can only refer to libraries within the + same project. The current project's name is "test-lib", but the reference is + to an external library. + [1] + + $ export OCAMLPATH=$PWD/external/install/lib; ./sdune build @find-a-from-target --root=src --workspace=./dune-workspace + Entering directory 'src' + File "dune", line 12, characters 18-56: + 12 | (action (echo "%{libexec-private:external_library:opam}"))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Error: The variable "libexec-private" can only refer to libraries within the + same project. The current project's name is "test-lib", but the reference is + to an external library. + [1] + +---------------------------------------------------------------------------------- +* The %{libexec-private:...} is only allowed within the same project + + $ mkdir -p another + $ cat >another/dune < (library + > (name anotherlib) + > (enabled_if (= %{context_name} host)) + > (public_name another_library)) + > EOF + + $ cat >src/dune < (library + > (name private_lib) + > (enabled_if (= %{context_name} host)) + > (public_name public_lib) + > (modules a)) + > (rule + > (alias find-a-from-host) + > (enabled_if (= %{context_name} host)) + > (action (echo "%{libexec-private:another_library:file}"))) + > (rule + > (alias find-a-from-target) + > (enabled_if (= %{context_name} target)) + > (action (echo "%{libexec-private:another_library:file}"))) + > EOF + + $ touch another/another_library.opam + $ rm public_lib.opam + $ rm dune + $ echo "(lang dune 2.8)" > another/dune-project + $ echo "(name another-lib)" >> another/dune-project + + $ ./sdune build @find-a-from-host + File "src/dune", line 9, characters 18-55: + 9 | (action (echo "%{libexec-private:another_library:file}"))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Error: The variable "libexec-private" can only refer to libraries within the + same project. The current project's name is "test-lib", but the reference is + to "another-lib". + [1] + + $ ./sdune build @find-a-from-target + File "src/dune", line 13, characters 18-55: + 13 | (action (echo "%{libexec-private:another_library:file}"))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Error: The variable "libexec-private" can only refer to libraries within the + same project. The current project's name is "test-lib", but the reference is + to "another-lib". + [1] + +---------------------------------------------------------------------------------- +* libexec-private with --only-packages +In this test, two packages are defined in the same project, but we may not +access the artifacts through %{libexec-private} + + $ mkdir lib-private-only-packages + $ cd lib-private-only-packages + $ mkdir lib1 lib2 + $ cat >dune-project < (lang dune 2.8) + > (name lib-private-test) + > (package (name public_lib1)) + > (package (name public_lib2)) + > EOF + $ cat >lib1/dune < (library + > (name lib1) + > (enabled_if (= %{context_name} host)) + > (public_name public_lib1)) + > EOF + $ touch lib1/lib1.ml + $ cat >lib2/dune < (library + > (name lib2) + > (public_name public_lib2)) + > (rule + > (with-stdout-to lib2.ml (echo "let _ = {|%{libexec-private:lib1:lib1.ml}|}"))) + > EOF + $ cat >dune < (alias + > (name host) + > (enabled_if (= %{context_name} host)) + > (deps (alias_rec install))) + > (alias + > (name target) + > (enabled_if (= %{context_name} target)) + > (deps (alias_rec install))) + > EOF + +The build works in development: + $ dune build @host --workspace=../dune-workspace + +But will fail when we release it, as it will need to run with -p: + $ dune build @target --workspace=../dune-workspace --only-packages public_lib2 + File "lib2/dune", line 5, characters 44-73: + 5 | (with-stdout-to lib2.ml (echo "let _ = {|%{libexec-private:lib1:lib1.ml}|}"))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Error: Library "lib1" not found. + Hint: try: + dune external-lib-deps --missing --only-packages public_lib2 --workspace ../dune-workspace @target + [1] From 06404d931460a23dca5a8ff9d7e9077aee164f14 Mon Sep 17 00:00:00 2001 From: Lucas Pluvinage Date: Tue, 22 Dec 2020 11:39:11 +0100 Subject: [PATCH 2/4] add host info to expander Signed-off-by: Lucas Pluvinage --- src/dune_rules/expander.ml | 8 ++++++-- src/dune_rules/expander.mli | 2 ++ src/dune_rules/super_context.ml | 10 ++++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/dune_rules/expander.ml b/src/dune_rules/expander.ml index 9579cf45261..9cb550d8458 100644 --- a/src/dune_rules/expander.ml +++ b/src/dune_rules/expander.ml @@ -25,10 +25,12 @@ type t = ; hidden_env : Env.Var.Set.t ; env : Env.t ; lib_artifacts : Artifacts.Public_libs.t + ; lib_artifacts_host : Artifacts.Public_libs.t ; bin_artifacts_host : Artifacts.Bin.t ; ocaml_config : Value.t list String.Map.t Lazy.t ; bindings : Pform.Map.t ; scope : Scope.t + ; scope_host : Scope.t ; c_compiler : string ; context : Context.t ; expand_var : t -> Expanded.t String_with_vars.expander @@ -193,8 +195,8 @@ let static_expand let cc_cxx_bindings = Pform.Map.of_list_exn [ ("cc", Pform.Var.Cc); ("cxx", Pform.Var.Cxx) ] -let make ~scope ~(context : Context.t) ~lib_artifacts ~bin_artifacts_host - ~find_package = +let make ~scope ~scope_host ~(context : Context.t) ~lib_artifacts + ~lib_artifacts_host ~bin_artifacts_host ~find_package = let ocaml_config = lazy (make_ocaml_config context.ocaml_config) in let dir = context.build_dir in let bindings = @@ -209,7 +211,9 @@ let make ~scope ~(context : Context.t) ~lib_artifacts ~bin_artifacts_host ; ocaml_config ; bindings ; scope + ; scope_host ; lib_artifacts + ; lib_artifacts_host ; bin_artifacts_host ; expand_var = static_expand ; c_compiler diff --git a/src/dune_rules/expander.mli b/src/dune_rules/expander.mli index 3b3d78d9b4e..6d192f0fd3a 100644 --- a/src/dune_rules/expander.mli +++ b/src/dune_rules/expander.mli @@ -21,8 +21,10 @@ val context : t -> Context.t val make : scope:Scope.t + -> scope_host:Scope.t -> context:Context.t -> lib_artifacts:Artifacts.Public_libs.t + -> lib_artifacts_host:Artifacts.Public_libs.t -> bin_artifacts_host:Artifacts.Bin.t -> find_package:(Package.Name.t -> Package.t option) -> t diff --git a/src/dune_rules/super_context.ml b/src/dune_rules/super_context.ml index 334c5aac5a3..819f69719b1 100644 --- a/src/dune_rules/super_context.ml +++ b/src/dune_rules/super_context.ml @@ -532,16 +532,18 @@ let create ~(context : Context.t) ?host ~projects ~packages ~stanzas () = Artifacts.create context ~public_libs ~local_bins in let root_expander = - let artifacts_host = + let artifacts_host, context_host = match host with - | None -> artifacts - | Some host -> host.artifacts + | None -> (artifacts, context) + | Some host -> (host.artifacts, host.context) in let find_package = Package.Name.Map.find packages in Expander.make ~scope:(Scope.DB.find_by_dir scopes context.build_dir) + ~scope_host:(Scope.DB.find_by_dir scopes context_host.build_dir) ~context ~lib_artifacts:artifacts.public_libs - ~bin_artifacts_host:artifacts_host.bin ~find_package + ~bin_artifacts_host:artifacts_host.bin + ~lib_artifacts_host:artifacts_host.public_libs ~find_package in let dune_dir_locations_var : Stdune.Env.Var.t = "DUNE_DIR_LOCATIONS" in (* Add the section of the site mentioned in stanzas (it could be a site of an From 7d87f0399d1852160bbf70fc466e3a4b7502fec4 Mon Sep 17 00:00:00 2001 From: Lucas Pluvinage Date: Tue, 22 Dec 2020 12:21:01 +0100 Subject: [PATCH 3/4] fix libexec variables Signed-off-by: Lucas Pluvinage --- src/dune_rules/expander.ml | 32 +++++++++++++++++++++++++------- src/dune_rules/super_context.ml | 8 ++++---- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/dune_rules/expander.ml b/src/dune_rules/expander.ml index 9cb550d8458..5d4a855964d 100644 --- a/src/dune_rules/expander.ml +++ b/src/dune_rules/expander.ml @@ -380,10 +380,16 @@ let expand_and_record_generic acc ~dep_kind ~(dir : Path.Build.t) ~pform t | Macro (Lib { lib_exec; lib_private }, s) -> ( let lib, file = parse_lib_file ~loc s in Resolved_forms.add_lib_dep acc lib dep_kind; + let scope = + if lib_exec then + t.scope_host + else + t.scope + in match if lib_private then let open Result.O in - let* lib = Lib.DB.resolve (Scope.libs t.scope) (loc, lib) in + let* lib = Lib.DB.resolve (Scope.libs scope) (loc, lib) in let current_project = Scope.project t.scope and referenced_project = Lib.info lib |> Lib_info.status |> Lib_info.Status.project @@ -398,9 +404,13 @@ let expand_and_record_generic acc ~dep_kind ~(dir : Path.Build.t) ~pform t (User_error.E (User_error.make ~loc [ Pp.textf - "The variable \"lib-private\" can only refer to \ + "The variable \"lib%s-private\" can only refer to \ libraries within the same project. The current \ project's name is %S, but the reference is to %s." + ( if lib_exec then + "exec" + else + "" ) (Dune_project.Name.to_string_hum (Dune_project.name current_project)) ( match referenced_project with @@ -410,11 +420,15 @@ let expand_and_record_generic acc ~dep_kind ~(dir : Path.Build.t) ~pform t |> Dune_project.Name.to_string_hum |> String.quoted ) ])) else - Artifacts.Public_libs.file_of_lib t.lib_artifacts ~loc ~lib ~file + let artifacts = + if lib_exec then + t.lib_artifacts_host + else + t.lib_artifacts + in + Artifacts.Public_libs.file_of_lib artifacts ~loc ~lib ~file with | Ok path -> - (* TODO: The [exec = true] case is currently not handled correctly and - does not match the documentation. *) if (not lib_exec) || (not Sys.win32) || Filename.extension s = ".exe" then Static (path_exp path) else @@ -434,14 +448,18 @@ let expand_and_record_generic acc ~dep_kind ~(dir : Path.Build.t) ~pform t ( match lib_private with | true -> e | false -> - if Lib.DB.available (Scope.libs t.scope) lib then + if Lib.DB.available (Scope.libs scope) lib then User_error.E (User_error.make ~loc [ Pp.textf - "The library %S is not public. The variable \"lib\" \ + "The library %S is not public. The variable \"lib%s\" \ expands to the file's installation path which is not \ defined for private libraries." (Lib_name.to_string lib) + ( if lib_exec then + "exec" + else + "" ) ]) else e ) ) diff --git a/src/dune_rules/super_context.ml b/src/dune_rules/super_context.ml index 819f69719b1..d8061e73bfe 100644 --- a/src/dune_rules/super_context.ml +++ b/src/dune_rules/super_context.ml @@ -532,15 +532,15 @@ let create ~(context : Context.t) ?host ~projects ~packages ~stanzas () = Artifacts.create context ~public_libs ~local_bins in let root_expander = - let artifacts_host, context_host = + let scopes_host, artifacts_host, context_host = match host with - | None -> (artifacts, context) - | Some host -> (host.artifacts, host.context) + | None -> (scopes, artifacts, context) + | Some host -> (host.scopes, host.artifacts, host.context) in let find_package = Package.Name.Map.find packages in Expander.make ~scope:(Scope.DB.find_by_dir scopes context.build_dir) - ~scope_host:(Scope.DB.find_by_dir scopes context_host.build_dir) + ~scope_host:(Scope.DB.find_by_dir scopes_host context_host.build_dir) ~context ~lib_artifacts:artifacts.public_libs ~bin_artifacts_host:artifacts_host.bin ~lib_artifacts_host:artifacts_host.public_libs ~find_package From 3cc98a1031d750f37e8f624b3388215a7d88291d Mon Sep 17 00:00:00 2001 From: Lucas Pluvinage Date: Tue, 5 Jan 2021 11:34:44 +0100 Subject: [PATCH 4/4] update changes Signed-off-by: Lucas Pluvinage --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 6b1d01fc1de..6920ad9a21a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -108,6 +108,9 @@ Unreleased - Configurator: fix a bug introduced in 2.6.0 where the configurator V1 API doesn't work at all when used outside of dune. (#4046, @aalekseyev) +- Fix `libexec` and `libexec-private` variables. In cross-compilation settings, + they now point to the file in the host context. (#4058, fixes #4057, @TheLortex) + 2.7.1 (2/09/2020) -----------------