diff --git a/CHANGES.md b/CHANGES.md index 0bf915b057d..729420fdc72 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,9 @@ Unreleased - Fix plugins with dot in the name (#5182, @bobot, review @rgrinberg) +- Don't generate the dune-site build part when not needed (#4861, @bobot, + review @kit-ty-kate) + - Fix installation of implementations of virtual libraries (#5150, fix #3636, @rgrinberg) diff --git a/otherlibs/site/test/run.t b/otherlibs/site/test/run.t index 66474dbf20b..3731b09911e 100644 --- a/otherlibs/site/test/run.t +++ b/otherlibs/site/test/run.t @@ -3,26 +3,37 @@ Test embedding of sites locations information $ mkdir -p a b c - $ for i in a b d; do + $ mkdir -p a + + $ cat >a/dune-project < (lang dune 3.0) + > (generate_opam_files true) + > (using dune_site 0.1) + > (name a) + > (version 0.a) + > (package (name a) (sites (share data))) + > EOF + + $ for i in b d; do > mkdir -p $i > cat >$i/dune-project < (lang dune 2.9) + > (lang dune 3.0) > (generate_opam_files true) > (using dune_site 0.1) > (name $i) > (version 0.$i) - > (package (name $i) (sites (share data))) + > (package (name $i) (sites (share data)) (depends c)) > EOF > done $ for i in c; do > mkdir -p $i > cat >$i/dune-project < (lang dune 2.9) + > (lang dune 3.0) > (generate_opam_files true) > (using dune_site 0.1) > (name $i) - > (package (name $i) (sites (share data) (lib plugins))) + > (package (name $i) (sites (share data) (lib plugins)) (depends a)) > EOF > done @@ -139,7 +150,7 @@ Test with an opam like installation opam-version: "2.0" version: "0.a" depends: [ - "dune" {>= "2.9"} + "dune" {>= "3.0"} "odoc" {with-doc} ] build: [ @@ -159,9 +170,7 @@ Test with an opam like installation ["dune" "install" "-p" name "--create-install-files" name] ] - $ dune subst - - $ dune build -p a --promote-install-files=false @install @runtest @doc + $ dune build -p a --promote-install-files=false @install $ test -e a/a.install [1] @@ -378,11 +387,11 @@ Test %{version:installed-pkg} $ for i in f; do > mkdir -p $i > cat >$i/dune-project < (lang dune 2.9) + > (lang dune 3.0) > (using dune_site 0.1) > (name $i) > (version 0.$i) - > (package (name $i) (sites (share data) (lib plugins))) + > (package (name $i) (sites (share data) (lib plugins)) (allow_empty)) > EOF > done diff --git a/otherlibs/site/test/run_2_9.t b/otherlibs/site/test/run_2_9.t new file mode 100644 index 00000000000..2410ec00b80 --- /dev/null +++ b/otherlibs/site/test/run_2_9.t @@ -0,0 +1,443 @@ +Test embedding of sites locations information +----------------------------------- + + $ mkdir -p a b c + + $ for i in a b d; do + > mkdir -p $i + > cat >$i/dune-project < (lang dune 2.9) + > (generate_opam_files true) + > (using dune_site 0.1) + > (name $i) + > (version 0.$i) + > (package (name $i) (sites (share data))) + > EOF + > done + + $ for i in c; do + > mkdir -p $i + > cat >$i/dune-project < (lang dune 2.9) + > (generate_opam_files true) + > (using dune_site 0.1) + > (name $i) + > (package (name $i) (sites (share data) (lib plugins))) + > EOF + > done + + $ cat >a/dune < (library + > (public_name a) + > (libraries dune-site)) + > (generate_sites_module (module sites) (sites a)) + > EOF + + $ cat >a/a.ml < let v = "a" + > let () = Printf.printf "run a\n%!" + > let () = List.iter (Printf.printf "a: %s\n%!") Sites.Sites.data + > EOF + + $ cat >b/dune < (library + > (public_name b.b.b) + > (name b) + > (libraries c.register dune-site)) + > (generate_sites_module (module sites) (sites b)) + > (plugin (name c-plugins-b) (libraries b.b.b) (site (c plugins))) + > (install (section (site (b data))) (files info.txt)) + > EOF + + $ cat >b/b.ml < let v = "b" + > let () = Printf.printf "run b\n%!" + > let () = C_register.registered := "b"::!C_register.registered + > let () = List.iter (Printf.printf "b: %s\n%!") Sites.Sites.data + > let () = + > let test d = Sys.file_exists (Filename.concat d "info.txt") in + > let found = List.exists test Sites.Sites.data in + > Printf.printf "info.txt is found: %b\n%!" found + > EOF + + $ cat >b/info.txt < Lorem + > EOF + + $ cat >d/dune < (library + > (public_name d) + > (libraries c.register dune-site non-existent-library) + > (optional)) + > (generate_sites_module (module sites) (sites d)) + > (plugin (name c-plugins-d) (libraries d) (site (c plugins)) (optional)) + > (install (section (site (d data))) (files info.txt)) + > EOF + + $ cat >d/d.ml < let v = "d" + > let () = Printf.printf "run d\n%!" + > let () = C_register.registered := "d"::!C_register.registered + > let () = List.iter (Printf.printf "d: %s\n%!") Sites.Sites.data + > let () = + > let test d = Sys.file_exists (Filename.concat d "info.txt") in + > let found = List.exists test Sites.Sites.data in + > Printf.printf "info.txt is found: %d\n%!" found + > EOF + + $ cat >d/info.txt < Lorem + > EOF + + + $ cat >c/dune < (executable + > (public_name c) + > (promote (until-clean)) + > (modules c sites) + > (libraries a c.register dune-site dune-site.plugins)) + > (library + > (public_name c.register) + > (name c_register) + > (modules c_register)) + > (generate_sites_module (module sites) (sourceroot) (plugins (c plugins))) + > (rule + > (targets out.log) + > (deps (package c)) + > (action (with-stdout-to out.log (run %{bin:c})))) + > EOF + + $ cat >c/c_register.ml < let registered : string list ref = ref [] + > EOF + + $ cat >c/c.ml < let () = Printf.printf "run c: %s linked registered:%s.\n%!" + > A.v (String.concat "," !C_register.registered) + > let () = match Sites.sourceroot with + > | Some d -> Printf.printf "sourceroot is %S\n%!" d + > | None -> Printf.printf "no sourceroot\n%!" + > let () = List.iter (Printf.printf "c: %s\n%!") Sites.Sites.data + > let () = Printf.printf "b is available: %b\n%!" (Dune_site_plugins.V1.available "b") + > let () = Sites.Plugins.Plugins.load_all () + > let () = Printf.printf "run c: registered:%s.\n%!" (String.concat "," !C_register.registered) + > EOF + + $ cat > dune-project << EOF + > (lang dune 2.2) + > EOF + + +Test with an opam like installation +-------------------------------- + + $ dune build a/a.opam + + $ cat a/a.opam + # This file is generated by dune, edit dune-project instead + opam-version: "2.0" + version: "0.a" + depends: [ + "dune" {>= "2.9"} + "odoc" {with-doc} + ] + build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "--promote-install-files=false" + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] + ["dune" "install" "-p" name "--create-install-files" name] + ] + + $ dune build -p a --promote-install-files="false" @install + + $ test -e a/a.install + [1] + + $ dune install -p a --create-install-files a 2> /dev/null + + $ grep "_destdir" a/a.install -c + 7 + + $ grep "_build" a/a.install -c + 12 + +Build everything +---------------- + + $ dune build + +Test with a normal installation +-------------------------------- + + $ dune install --prefix _install 2> /dev/null + +Once installed, we have the sites information: + + $ OCAMLPATH=_install/lib:$OCAMLPATH _install/bin/c + run a + a: $TESTCASE_ROOT/_install/share/a/data + run c: a linked registered:. + no sourceroot + c: $TESTCASE_ROOT/_install/share/c/data + b is available: true + run b + b: $TESTCASE_ROOT/_install/share/b/data + info.txt is found: true + run c: registered:b. + +Test with a relocatable installation +-------------------------------- + + $ dune install --prefix _install_relocatable --relocatable 2> /dev/null + +Once installed, we have the sites information: + + $ _install_relocatable/bin/c + run a + a: $TESTCASE_ROOT/_install_relocatable/share/a/data + run c: a linked registered:. + no sourceroot + c: $TESTCASE_ROOT/_install_relocatable/share/c/data + b is available: true + run b + b: $TESTCASE_ROOT/_install_relocatable/share/b/data + info.txt is found: true + run c: registered:b. + +Test after moving a relocatable installation +-------------------------------- + + $ mv _install_relocatable _install_relocatable2 + +Once installed, we have the sites information: + + $ _install_relocatable2/bin/c + run a + a: $TESTCASE_ROOT/_install_relocatable2/share/a/data + run c: a linked registered:. + no sourceroot + c: $TESTCASE_ROOT/_install_relocatable2/share/c/data + b is available: true + run b + b: $TESTCASE_ROOT/_install_relocatable2/share/b/data + info.txt is found: true + run c: registered:b. + +Test substitution when promoting +-------------------------------- + +It is wrong that info.txt is not found, but to make it work it is an important +development because b is not promoted + + $ c/c.exe + run a + a: $TESTCASE_ROOT/_build/install/default/share/a/data + run c: a linked registered:. + sourceroot is "$TESTCASE_ROOT" + c: $TESTCASE_ROOT/_build/install/default/share/c/data + b is available: true + run b + info.txt is found: false + run c: registered:b. + +Test within dune rules +-------------------------------- + $ dune build c/out.log + + $ cat _build/default/c/out.log + run a + a: $TESTCASE_ROOT/_build/install/default/share/a/data + run c: a linked registered:. + sourceroot is "$TESTCASE_ROOT" + c: $TESTCASE_ROOT/_build/install/default/share/c/data + b is available: true + run b + b: $TESTCASE_ROOT/_build/install/default/share/b/data + info.txt is found: true + run c: registered:b. + + +Test with dune exec +-------------------------------- + $ dune exec -- c/c.exe + run a + a: $TESTCASE_ROOT/_build/install/default/share/a/data + run c: a linked registered:. + sourceroot is "$TESTCASE_ROOT" + c: $TESTCASE_ROOT/_build/install/default/share/c/data + b is available: true + run b + b: $TESTCASE_ROOT/_build/install/default/share/b/data + info.txt is found: true + run c: registered:b. + + +Test compiling an external plugin +--------------------------------- + $ mkdir e + $ cat >e/dune-project < (lang dune 2.8) + > (using dune_site 0.1) + > (name e) + > (package (name e) (sites (share data))) + > EOF + + $ cat >e/dune < (library + > (public_name e) + > (libraries c.register dune-site)) + > (generate_sites_module (module sites) (sites e)) + > (plugin (name c-plugins-e) (libraries e) (site (c plugins))) + > (install (section (site (e data))) (files info.txt)) + > (rule (alias runtest) (deps (package a) (package b) (package c) (package d) (package e)) + > (action (run %{bin:c}))) + > EOF + + $ cat >e/e.ml < let v = "e" + > let () = Printf.printf "run e\n%!" + > let () = C_register.registered := "e"::!C_register.registered + > let () = List.iter (Printf.printf "e: %s\n%!") Sites.Sites.data + > let () = + > let test d = Sys.file_exists (Filename.concat d "info.txt") in + > let found = List.exists test Sites.Sites.data in + > Printf.printf "info.txt is found: %b\n%!" found + > EOF + + $ cat >e/info.txt < Lorem + > EOF + + $ OCAMLPATH=$(pwd)/_install/lib:$OCAMLPATH dune build --root=e + Entering directory 'e' + + $ OCAMLPATH=$(pwd)/_install/lib:$OCAMLPATH PATH=$(pwd)/_install/bin:$PATH dune exec --root=e -- c + Entering directory 'e' + run a + a: $TESTCASE_ROOT/_install/share/a/data + run c: a linked registered:. + no sourceroot + c: $TESTCASE_ROOT/_install/share/c/data + b is available: true + run b + b: $TESTCASE_ROOT/_install/share/b/data + info.txt is found: true + run e + e: $TESTCASE_ROOT/e/_build/install/default/share/e/data + info.txt is found: true + run c: registered:e,b. + + $ OCAMLPATH=$(pwd)/_install/lib:$OCAMLPATH dune install --root=e --prefix $(pwd)/_install 2> /dev/null + + $ OCAMLPATH=_install/lib:$OCAMLPATH _install/bin/c + run a + a: $TESTCASE_ROOT/_install/share/a/data + run c: a linked registered:. + no sourceroot + c: $TESTCASE_ROOT/_install/share/c/data + b is available: true + run b + b: $TESTCASE_ROOT/_install/share/b/data + info.txt is found: true + run e + e: $TESTCASE_ROOT/_install/share/e/data + info.txt is found: true + run c: registered:e,b. + + $ OCAMLPATH=_install/lib:$OCAMLPATH dune build @runtest + run a + a: $TESTCASE_ROOT/_build/install/default/share/a/data + run c: a linked registered:. + sourceroot is "$TESTCASE_ROOT" + c: $TESTCASE_ROOT/_build/install/default/share/c/data + b is available: true + run b + b: $TESTCASE_ROOT/_build/install/default/share/b/data + info.txt is found: true + run e + e: $TESTCASE_ROOT/_build/install/default/share/e/data + info.txt is found: true + run c: registered:e,b. + +Test %{version:installed-pkg} +----------------------------- + + $ for i in f; do + > mkdir -p $i + > cat >$i/dune-project < (lang dune 2.9) + > (using dune_site 0.1) + > (name $i) + > (version 0.$i) + > (package (name $i) (sites (share data) (lib plugins))) + > EOF + > done + + $ cat >f/dune < (rule + > (target test.target) + > (action + > (with-stdout-to %{target} + > (progn + > (echo "a = %{version:a}\n") + > (echo "e = %{version:e}\n"))))) + > EOF + + $ OCAMLPATH=_install/lib:$OCAMLPATH dune build --root=f + Entering directory 'f' + $ cat $(pwd)/f/_build/default/test.target + a = 0.a + e = + + $ cat f/dune | sed 's/version:a/version:a.test/' > f/dune.tmp && mv f/dune.tmp f/dune + $ OCAMLPATH=_install/lib:$OCAMLPATH dune build --root=f + Entering directory 'f' + File "dune", line 6, characters 15-32: + 6 | (echo "a = %{version:a.test}\n") + ^^^^^^^^^^^^^^^^^ + Error: Library names are not allowed in this position. Only package names are + allowed + [1] + + $ rm f/dune + +Test error location +--------------------------------- + + $ cat >>a/dune < (install + > (section (site (non-existent foo))) + > (files a.ml) + > ) + > EOF + + $ dune build @install + File "a/dune", line 6, characters 16-34: + 6 | (section (site (non-existent foo))) + ^^^^^^^^^^^^^^^^^^ + Error: The package non-existent is not found + [1] + + $ cat >a/dune < (library + > (public_name a) + > (libraries dune-site)) + > (generate_sites_module (module sites) (sites non-existent)) + > EOF + + $ dune build + File "a/dune", line 4, characters 45-57: + 4 | (generate_sites_module (module sites) (sites non-existent)) + ^^^^^^^^^^^^ + Error: Unknown package + [1] diff --git a/src/dune_engine/dune_project.ml b/src/dune_engine/dune_project.ml index 805d70f48ca..76d529e1e5b 100644 --- a/src/dune_engine/dune_project.ml +++ b/src/dune_engine/dune_project.ml @@ -255,6 +255,8 @@ let to_dyn let find_extension_args t key = Univ_map.find t.extension_args key +let is_extension_set t key = Option.is_some (find_extension_args t key) + include Dune_lang.Versioned_file.Make (struct type t = Stanza.Parser.t list end) @@ -310,12 +312,15 @@ module Extension = struct let register_deleted ~name ~deleted_in = Table.add_exn extensions name (Deleted_in deleted_in) - let register_simple syntax stanzas = + let register_unit syntax stanzas = let unit_stanzas = let+ r = stanzas in ((), r) in - let (_ : unit t) = register syntax unit_stanzas Unit.to_dyn in + register syntax unit_stanzas Unit.to_dyn + + let register_simple syntax stanzas = + let (_ : unit t) = register_unit syntax stanzas in () let instantiate ~dune_lang_ver ~loc ~parse_args (name_loc, name) (ver_loc, ver) @@ -1007,10 +1012,10 @@ let executables_implicit_empty_intf t = t.executables_implicit_empty_intf let accept_alternative_dune_file_name t = t.accept_alternative_dune_file_name -let () = - let open Dune_lang.Decoder in - Extension.register_simple Action_plugin.syntax (return []); - Extension.register_simple Section.dune_site_syntax (return []) +let () = Extension.register_simple Action_plugin.syntax (return []) + +let dune_site_extension = + Extension.register_unit Section.dune_site_syntax (return []) let strict_package_deps t = t.strict_package_deps diff --git a/src/dune_engine/dune_project.mli b/src/dune_engine/dune_project.mli index 9735aa3365b..dcd52483d25 100644 --- a/src/dune_engine/dune_project.mli +++ b/src/dune_engine/dune_project.mli @@ -171,6 +171,8 @@ val get_exn : unit -> (t, 'k) Dune_lang.Decoder.parser written in dune-project. *) val find_extension_args : t -> 'a Extension.t -> 'a option +val is_extension_set : t -> 'a Extension.t -> bool + val set_parsing_context : t -> 'a Dune_lang.Decoder.t -> 'a Dune_lang.Decoder.t val implicit_transitive_deps : t -> bool @@ -195,3 +197,5 @@ val update_execution_parameters : t -> Execution_parameters.t -> Execution_parameters.t val encode : t -> Dune_lang.t list + +val dune_site_extension : unit Extension.t diff --git a/src/dune_engine/subst_config.ml b/src/dune_engine/subst_config.ml index a867e4f9eb8..d414ef37ddf 100644 --- a/src/dune_engine/subst_config.ml +++ b/src/dune_engine/subst_config.ml @@ -5,6 +5,10 @@ type t = | Disabled | Enabled +let is_enabled = function + | Enabled -> true + | Disabled -> false + let to_string = function | Disabled -> "disabled" | Enabled -> "enabled" diff --git a/src/dune_engine/subst_config.mli b/src/dune_engine/subst_config.mli index b6539d9a331..ba7c4116b78 100644 --- a/src/dune_engine/subst_config.mli +++ b/src/dune_engine/subst_config.mli @@ -2,6 +2,8 @@ type t = | Disabled | Enabled +val is_enabled : t -> bool + val to_dyn : t -> Dyn.t val encode : t Dune_lang.Encoder.t diff --git a/src/dune_rules/opam_create.ml b/src/dune_rules/opam_create.ml index 838a3e90fd6..c8250dec2ef 100644 --- a/src/dune_rules/opam_create.ml +++ b/src/dune_rules/opam_create.ml @@ -57,20 +57,41 @@ let default_build_command = [ "dune" "install" "-p" name "--create-install-files" name ] ] |})) - and from_3_0_without_subst = + and from_3_0 ~with_subst ~with_sites = + let subst = + if with_subst then + {| [ "dune" "subst" ] {dev} |} + else + "" + in + let promote_install_files = + if with_sites then + {| "--promote-install-files=false" |} + else + "" + in + let install = + if with_sites then + {| [ "dune" "install" "-p" name "--create-install-files" name ] |} + else + "" + in lazy (Opam_file.parse_value (Lexbuf.from_string ~fname:"" - {| + (Printf.sprintf + {| [ - [ "dune" "build" "-p" name "-j" jobs "--promote-install-files" "false" + %s + [ "dune" "build" "-p" name "-j" jobs %s "@install" "@runtest" {with-test} "@doc" {with-doc} ] - [ "dune" "install" "-p" name "--create-install-files" name ] + %s ] -|})) +|} + subst promote_install_files install))) in fun project -> Lazy.force @@ -83,9 +104,11 @@ let default_build_command = else if Dune_project.dune_version project < (3, 0) then from_2_9 else - match Dune_project.subst_config project with - | Disabled -> from_3_0_without_subst - | Enabled -> from_2_9) + from_3_0 + ~with_subst: + (Subst_config.is_enabled (Dune_project.subst_config project)) + ~with_sites: + Dune_project.(is_extension_set project dune_site_extension)) let package_fields { Package.synopsis diff --git a/test/blackbox-tests/test-cases/dune-init.t/run.t b/test/blackbox-tests/test-cases/dune-init.t/run.t index cd1980e8d28..33ffb22f015 100644 --- a/test/blackbox-tests/test-cases/dune-init.t/run.t +++ b/test/blackbox-tests/test-cases/dune-init.t/run.t @@ -371,12 +371,10 @@ And the opam file will be generated as expected name "-j" jobs - "--promote-install-files=false" "@install" "@runtest" {with-test} "@doc" {with-doc} ] - ["dune" "install" "-p" name "--create-install-files" name] ] dev-repo: "git+https://github.com/username/reponame.git" @@ -480,12 +478,10 @@ And the opam file will be generated as expected name "-j" jobs - "--promote-install-files=false" "@install" "@runtest" {with-test} "@doc" {with-doc} ] - ["dune" "install" "-p" name "--create-install-files" name] ] dev-repo: "git+https://github.com/username/reponame.git" diff --git a/test/blackbox-tests/test-cases/dune-project-meta/main.t/run.t b/test/blackbox-tests/test-cases/dune-project-meta/main.t/run.t index 775f4b0610d..4645d84e2a3 100644 --- a/test/blackbox-tests/test-cases/dune-project-meta/main.t/run.t +++ b/test/blackbox-tests/test-cases/dune-project-meta/main.t/run.t @@ -518,6 +518,32 @@ the doc dependencies: "odoc" {with-doc} ] + $ cat > dune-project < (lang dune 2.9) + > (name foo) + > (generate_opam_files true) + > (package (name foo)) + > EOF + + $ dune build foo.opam + $ grep -A16 ^build: foo.opam + build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "--promote-install-files=false" + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] + ["dune" "install" "-p" name "--create-install-files" name] + ] + $ cat > dune-project < (lang dune 3.0) > (name foo) @@ -536,13 +562,10 @@ the doc dependencies: name "-j" jobs - "--promote-install-files" - "false" "@install" "@runtest" {with-test} "@doc" {with-doc} ] - ["dune" "install" "-p" name "--create-install-files" name] ] $ cat > dune-project <