diff options
author | Harmen Stoppels <me@harmenstoppels.nl> | 2024-05-30 07:31:28 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-30 07:31:28 +0200 |
commit | 39ace5fc45f67a870fef352ca5592892c54cf114 (patch) | |
tree | 15224215f9431a6b0cec0e8078a6b86383f76f9e /lib | |
parent | 0601d6a0c581fa249f2c20b2bfdfee11ae3a0e21 (diff) | |
download | spack-39ace5fc45f67a870fef352ca5592892c54cf114.tar.gz spack-39ace5fc45f67a870fef352ca5592892c54cf114.tar.bz2 spack-39ace5fc45f67a870fef352ca5592892c54cf114.tar.xz spack-39ace5fc45f67a870fef352ca5592892c54cf114.zip |
concretizer: enforce host compat when reuse only (#44428)
Fixes a bug in the concretizer where specs depending on a host
incompatible libc would be used. This bug triggers when nothing is
built.
In the case where everything is reused, there is no libc provider from
the perspective of the solver, there is only compatible_libc. This
commit ensures that we require a host compatible libc on any reused
spec, additionally to requiring compat with the chosen libc provider.
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/solver/asp.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/solver/libc_compatibility.lp | 12 | ||||
-rw-r--r-- | lib/spack/spack/test/concretize.py | 25 |
3 files changed, 35 insertions, 4 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 094ebaf170..49b5c626ce 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -2440,7 +2440,7 @@ class SpackSolverSetup: if using_libc_compatibility(): for libc in self.libcs: - self.gen.fact(fn.allowed_libc(libc.name, libc.version)) + self.gen.fact(fn.host_libc(libc.name, libc.version)) if not allow_deprecated: self.gen.fact(fn.deprecated_versions_not_allowed()) diff --git a/lib/spack/spack/solver/libc_compatibility.lp b/lib/spack/spack/solver/libc_compatibility.lp index 3e2c00e372..6c32493656 100644 --- a/lib/spack/spack/solver/libc_compatibility.lp +++ b/lib/spack/spack/solver/libc_compatibility.lp @@ -24,12 +24,20 @@ has_built_packages() :- build(X), not external(X). % A libc is needed in the DAG :- has_built_packages(), not provider(_, node(0, "libc")). -% The libc must be chosen among available ones +% Non-libc reused specs must be host libc compatible. In case we build packages, we get a +% host compatible libc provider from other rules. If nothing is built, there is no libc provider, +% since it's pruned from reusable specs, meaning we have to explicitly impose reused specs are host +% compatible. +:- attr("hash", node(R, ReusedPackage), Hash), + not provider(node(R, ReusedPackage), node(0, "libc")), + not attr("compatible_libc", node(R, ReusedPackage), _, _). + +% The libc provider must be one that a compiler can target :- has_built_packages(), provider(node(X, LibcPackage), node(0, "libc")), attr("node", node(X, LibcPackage)), attr("version", node(X, LibcPackage), LibcVersion), - not allowed_libc(LibcPackage, LibcVersion). + not host_libc(LibcPackage, LibcVersion). % A built node must depend on libc :- build(PackageNode), diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 0b4ce5b42a..b1cd35bff9 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -28,7 +28,7 @@ import spack.util.libc import spack.variant as vt from spack.concretize import find_spec from spack.spec import CompilerSpec, Spec -from spack.version import Version, ver +from spack.version import Version, VersionList, ver def check_spec(abstract, concrete): @@ -2570,6 +2570,29 @@ class TestConcretize: sombrero = result.specs[0] assert sombrero["externaltool"].dag_hash() == external_spec.dag_hash() + @pytest.mark.only_clingo("Original concretizer cannot reuse") + def test_cannot_reuse_host_incompatible_libc(self): + """Test whether reuse concretization correctly fails to reuse a spec with a host + incompatible libc.""" + if not spack.solver.asp.using_libc_compatibility(): + pytest.skip("This test requires libc nodes") + + # We install b@1 ^glibc@2.30, and b@0 ^glibc@2.28. The former is not host compatible, the + # latter is. + fst = Spec("b@1").concretized() + fst._mark_concrete(False) + fst.dependencies("glibc")[0].versions = VersionList(["=2.30"]) + fst._mark_concrete(True) + snd = Spec("b@0").concretized() + + # The spec b@1 ^glibc@2.30 is "more optimal" than b@0 ^glibc@2.28, but due to glibc + # incompatibility, it should not be reused. + solver = spack.solver.asp.Solver() + setup = spack.solver.asp.SpackSolverSetup() + result, _, _ = solver.driver.solve(setup, [Spec("b")], reuse=[fst, snd]) + assert len(result.specs) == 1 + assert result.specs[0] == snd + @pytest.fixture() def duplicates_test_repository(): |