summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2024-01-16 11:50:33 +0100
committerGitHub <noreply@github.com>2024-01-16 11:50:33 +0100
commitf0c69ff3bfbb0edcc22e7058091d529b979cef75 (patch)
treedd690a231338e6adce356b68134e2e03614bb18c /lib
parentddae696cf8f2a130773f9b21490c95ed7a30b5c4 (diff)
downloadspack-f0c69ff3bfbb0edcc22e7058091d529b979cef75.tar.gz
spack-f0c69ff3bfbb0edcc22e7058091d529b979cef75.tar.bz2
spack-f0c69ff3bfbb0edcc22e7058091d529b979cef75.tar.xz
spack-f0c69ff3bfbb0edcc22e7058091d529b979cef75.zip
Fix a bug when a required provider is requested for multiple virtuals (#42088)
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/solver/asp.py7
-rw-r--r--lib/spack/spack/solver/concretize.lp12
-rw-r--r--lib/spack/spack/test/concretize_requirements.py23
3 files changed, 39 insertions, 3 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index bc9a3e2fd7..7df2e0ff8a 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -1747,9 +1747,10 @@ class SpackSolverSetup:
rules = self._rules_from_requirements(
virtual_str, requirements, kind=RequirementKind.VIRTUAL
)
- self.emit_facts_from_requirement_rules(rules)
- self.trigger_rules()
- self.effect_rules()
+ if rules:
+ self.emit_facts_from_requirement_rules(rules)
+ self.trigger_rules()
+ self.effect_rules()
def emit_facts_from_requirement_rules(self, rules: List[RequirementRule]):
"""Generate facts to enforce requirements.
diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp
index c56f2bcc66..c8d96eed9c 100644
--- a/lib/spack/spack/solver/concretize.lp
+++ b/lib/spack/spack/solver/concretize.lp
@@ -698,6 +698,18 @@ requirement_group_satisfied(node(ID, Package), X) :-
activate_requirement(node(ID, Package), X),
requirement_group(Package, X).
+% When we have a required provider, we need to ensure that the provider/2 facts respect
+% the requirement. This is particularly important for packages that could provide multiple
+% virtuals independently
+required_provider(Provider, Virtual)
+ :- requirement_group_member(ConditionID, Virtual, RequirementID),
+ condition_holds(ConditionID, _),
+ virtual(Virtual),
+ pkg_fact(Virtual, condition_effect(ConditionID, EffectID)),
+ imposed_constraint(EffectID, "node", Provider).
+
+:- provider(node(Y, Package), node(X, Virtual)), required_provider(Provider, Virtual), Package != Provider.
+
% TODO: the following two choice rules allow the solver to add compiler
% flags if their only source is from a requirement. This is overly-specific
% and should use a more-generic approach like in https://github.com/spack/spack/pull/37180
diff --git a/lib/spack/spack/test/concretize_requirements.py b/lib/spack/spack/test/concretize_requirements.py
index 7b8f825eae..3a6b2b75c4 100644
--- a/lib/spack/spack/test/concretize_requirements.py
+++ b/lib/spack/spack/test/concretize_requirements.py
@@ -1012,3 +1012,26 @@ def test_default_requirements_semantic_with_mv_variants(
for constraint in not_expected:
assert not s.satisfies(constraint), constraint
+
+
+@pytest.mark.regression("42084")
+def test_requiring_package_on_multiple_virtuals(concretize_scope, mock_packages):
+ update_packages_config(
+ """
+ packages:
+ all:
+ providers:
+ scalapack: [netlib-scalapack]
+ blas:
+ require: intel-parallel-studio
+ lapack:
+ require: intel-parallel-studio
+ scalapack:
+ require: intel-parallel-studio
+ """
+ )
+ s = Spec("dla-future").concretized()
+
+ assert s["blas"].name == "intel-parallel-studio"
+ assert s["lapack"].name == "intel-parallel-studio"
+ assert s["scalapack"].name == "intel-parallel-studio"