From 605835fe4258bbd87e2109c87ace6b921b5c3d1c Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Fri, 29 Sep 2023 16:40:21 +0200 Subject: Don't drop build deps on overwrite install (#40252) If you `spack install x ^y` where `y` is a pure build dep of `x`, and then uninstall `y`, and then `spack install --overwrite x ^y`, the build fails because `y` is not re-installed. Same can happen when you install a develop spec, run `spack gc`, modify sources, and install again; develop specs rely on overwrite install to work correctly. --- lib/spack/spack/installer.py | 9 +++++---- lib/spack/spack/test/installer.py | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py index 95fbae5847..99ab7d45bd 100644 --- a/lib/spack/spack/installer.py +++ b/lib/spack/spack/installer.py @@ -847,10 +847,11 @@ class BuildRequest: else: cache_only = self.install_args.get("dependencies_cache_only") - # Include build dependencies if pkg is not installed and cache_only - # is False, or if build depdencies are explicitly called for - # by include_build_deps. - if include_build_deps or not (cache_only or pkg.spec.installed): + # Include build dependencies if pkg is going to be built from sources, or + # if build deps are explicitly requested. + if include_build_deps or not ( + cache_only or pkg.spec.installed and not pkg.spec.dag_hash() in self.overwrite + ): depflag |= dt.BUILD if self.run_tests(pkg): depflag |= dt.TEST diff --git a/lib/spack/spack/test/installer.py b/lib/spack/spack/test/installer.py index 91f695dd70..6b42e591eb 100644 --- a/lib/spack/spack/test/installer.py +++ b/lib/spack/spack/test/installer.py @@ -20,6 +20,7 @@ import spack.compilers import spack.concretize import spack.config import spack.database +import spack.deptypes as dt import spack.installer as inst import spack.package_base import spack.package_prefs as prefs @@ -1388,6 +1389,26 @@ def test_single_external_implicit_install(install_mockery, explicit_args, is_exp assert spack.store.STORE.db.get_record(pkg).explicit == is_explicit +def test_overwrite_install_does_install_build_deps(install_mockery, mock_fetch): + """When overwrite installing something from sources, build deps should be installed.""" + s = spack.spec.Spec("dtrun3").concretized() + create_installer([(s, {})]).install() + + # Verify there is a pure build dep + edge = s.edges_to_dependencies(name="dtbuild3").pop() + assert edge.depflag == dt.BUILD + build_dep = edge.spec + + # Uninstall the build dep + build_dep.package.do_uninstall() + + # Overwrite install the root dtrun3 + create_installer([(s, {"overwrite": [s.dag_hash()]})]).install() + + # Verify that the build dep was also installed. + assert build_dep.installed + + @pytest.mark.parametrize("run_tests", [True, False]) def test_print_install_test_log_skipped(install_mockery, mock_packages, capfd, run_tests): """Confirm printing of install log skipped if not run/no failures.""" -- cgit v1.2.3-60-g2f50