concretizer: treat conditional providers correctly (#20086)

refers #20040

This modification emits rules like:

provides_virtual("netlib-lapack","blas") :- variant_value("netlib-lapack","external-blas","False").

for packages that provide virtual dependencies conditionally instead
of a fact that doesn't account for the condition.
This commit is contained in:
Massimiliano Culpo
2020-11-25 22:03:42 +01:00
committed by GitHub
parent b33969598a
commit 983fb11dee
4 changed files with 49 additions and 1 deletions

View File

@@ -1322,13 +1322,18 @@ def virtual_providers(self):
self.gen.fact(fn.virtual(vspec))
all_providers = sorted(spack.repo.path.providers_for(vspec))
for idx, provider in enumerate(all_providers):
self.gen.fact(fn.provides_virtual(provider.name, vspec))
provides_atom = fn.provides_virtual(provider.name, vspec)
possible_provider_fn = fn.possible_provider(
vspec, provider.name, idx
)
item = (idx, provider, possible_provider_fn)
self.providers_by_vspec_name[vspec].append(item)
clauses = self.spec_clauses(provider, body=True)
clauses_but_node = [c for c in clauses if c.name != 'node']
if clauses_but_node:
self.gen.rule(provides_atom, AspAnd(*clauses_but_node))
else:
self.gen.fact(provides_atom)
for clause in clauses:
self.gen.rule(clause, possible_provider_fn)
self.gen.newline()

View File

@@ -883,3 +883,15 @@ def test_transitive_conditional_virtual_dependency(self):
# 'stuff' is provided by an external package, so check it's present
assert 'externalvirtual' in s
@pytest.mark.regression('20040')
def test_conditional_provides_or_depends_on(self):
if spack.config.get('config:concretizer') == 'original':
pytest.xfail('Known failure of the original concretizer')
# Check that we can concretize correctly a spec that can either
# provide a virtual or depend on it based on the value of a variant
s = Spec('conditional-provider +disable-v1').concretized()
assert 'v1-provider' in s
assert s['v1'].name == 'v1-provider'
assert s['v2'].name == 'conditional-provider'