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 Tamara Dahlgren
parent ad84351c43
commit 8e1b5f734f
4 changed files with 49 additions and 1 deletions

View File

@ -1323,13 +1323,18 @@ def virtual_providers(self):
self.gen.fact(fn.virtual(vspec)) self.gen.fact(fn.virtual(vspec))
all_providers = sorted(spack.repo.path.providers_for(vspec)) all_providers = sorted(spack.repo.path.providers_for(vspec))
for idx, provider in enumerate(all_providers): 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( possible_provider_fn = fn.possible_provider(
vspec, provider.name, idx vspec, provider.name, idx
) )
item = (idx, provider, possible_provider_fn) item = (idx, provider, possible_provider_fn)
self.providers_by_vspec_name[vspec].append(item) self.providers_by_vspec_name[vspec].append(item)
clauses = self.spec_clauses(provider, body=True) 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: for clause in clauses:
self.gen.rule(clause, possible_provider_fn) self.gen.rule(clause, possible_provider_fn)
self.gen.newline() 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 # 'stuff' is provided by an external package, so check it's present
assert 'externalvirtual' in s 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'

View File

@ -0,0 +1,18 @@
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
class ConditionalProvider(Package):
"""Mimic the real netlib-lapack, that may be built on top of an
optimized blas.
"""
homepage = "https://dev.null"
version('1.0')
variant('disable-v1', default=False, description='nope')
provides('v2')
provides('v1', when='~disable-v1')
depends_on('v1', when='+disable-v1')

View File

@ -0,0 +1,13 @@
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
class V1Provider(Package):
"""Mimic the real netlib-lapack, that may be built on top of an
optimized blas.
"""
homepage = "https://dev.null"
version('1.0')
provides('v1')