summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2024-05-23 14:37:48 +0200
committerGitHub <noreply@github.com>2024-05-23 14:37:48 +0200
commitf60e548a0dca17d44c259fa6c873fa7b683921e0 (patch)
tree62d474e4300ddac2690169894ce9e5a3ba9eaa0f /lib
parent04dc16a6b1060397a30166f520f4e67c5df36bd2 (diff)
downloadspack-f60e548a0dca17d44c259fa6c873fa7b683921e0.tar.gz
spack-f60e548a0dca17d44c259fa6c873fa7b683921e0.tar.bz2
spack-f60e548a0dca17d44c259fa6c873fa7b683921e0.tar.xz
spack-f60e548a0dca17d44c259fa6c873fa7b683921e0.zip
ASP-based solver: fix reusing externals on linux (#44316)
We need to tell clingo the libc compatibility of external nodes in buildcaches or stores, to allow reuse.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/solver/asp.py5
-rw-r--r--lib/spack/spack/solver/libc_compatibility.lp13
-rw-r--r--lib/spack/spack/test/concretize.py24
3 files changed, 36 insertions, 6 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 0083dbc070..094ebaf170 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -1939,6 +1939,11 @@ class SpackSolverSetup:
for virtual in virtuals:
clauses.append(fn.attr("virtual_on_incoming_edges", spec.name, virtual))
+ # If the spec is external and concrete, we allow all the libcs on the system
+ if spec.external and spec.concrete and using_libc_compatibility():
+ for libc in self.libcs:
+ clauses.append(fn.attr("compatible_libc", spec.name, libc.name, libc.version))
+
# add all clauses from dependencies
if transitive:
# TODO: Eventually distinguish 2 deps on the same pkg (build and link)
diff --git a/lib/spack/spack/solver/libc_compatibility.lp b/lib/spack/spack/solver/libc_compatibility.lp
index 28c7c57fda..3e2c00e372 100644
--- a/lib/spack/spack/solver/libc_compatibility.lp
+++ b/lib/spack/spack/solver/libc_compatibility.lp
@@ -10,12 +10,13 @@
%=============================================================================
% A package cannot be reused if the libc is not compatible with it
-:- provider(node(X, LibcPackage), node(0, "libc")),
- attr("version", node(X, LibcPackage), LibcVersion),
- attr("hash", node(R, ReusedPackage), Hash),
- % Libc packages can be reused without the "compatible_libc" attribute
- ReusedPackage != LibcPackage,
- not attr("compatible_libc", node(R, ReusedPackage), LibcPackage, LibcVersion).
+error(100, "Cannot reuse {0} since we cannot determine libc compatibility", ReusedPackage)
+ :- provider(node(X, LibcPackage), node(0, "libc")),
+ attr("version", node(X, LibcPackage), LibcVersion),
+ attr("hash", node(R, ReusedPackage), Hash),
+ % Libc packages can be reused without the "compatible_libc" attribute
+ ReusedPackage != LibcPackage,
+ not attr("compatible_libc", node(R, ReusedPackage), LibcPackage, LibcVersion).
% Check whether the DAG has any built package
has_built_packages() :- build(X), not external(X).
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index 797c865a4f..0b4ce5b42a 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -2546,6 +2546,30 @@ class TestConcretize:
assert result["deprecated-versions"].satisfies("@1.0.0")
+ @pytest.mark.regression("44085")
+ @pytest.mark.only_clingo("Use case not supported by the original concretizer")
+ def test_can_reuse_concrete_externals_for_dependents(self, mutable_config, tmp_path):
+ """Test that external specs that are in the DB can be reused. This means they are
+ preferred to concretizing another external from packages.yaml
+ """
+ packages_yaml = {
+ "externaltool": {"externals": [{"spec": "externaltool@2.0", "prefix": "/fake/path"}]}
+ }
+ mutable_config.set("packages", packages_yaml)
+ # Concretize with gcc@9 to get a suboptimal spec, since we have gcc@10 available
+ external_spec = Spec("externaltool@2 %gcc@9").concretized()
+ assert external_spec.external
+
+ root_specs = [Spec("sombrero")]
+ with spack.config.override("concretizer:reuse", True):
+ solver = spack.solver.asp.Solver()
+ setup = spack.solver.asp.SpackSolverSetup()
+ result, _, _ = solver.driver.solve(setup, root_specs, reuse=[external_spec])
+
+ assert len(result.specs) == 1
+ sombrero = result.specs[0]
+ assert sombrero["externaltool"].dag_hash() == external_spec.dag_hash()
+
@pytest.fixture()
def duplicates_test_repository():