concretizer: try hard to obtain all needed variant_possible_value()'s (#20102)

Track all the variant values mentioned when emitting constraints, validate them
and emit a fact that allows them as possible values.

This modification ensures that open-ended variants (variants accepting any string 
or any integer) are projected to the finite set of values that are relevant for this 
concretization.
This commit is contained in:
Andrew W Elble 2020-12-08 09:46:52 -05:00 committed by Tamara Dahlgren
parent 30a9e6462f
commit ab3f1b10db
7 changed files with 87 additions and 10 deletions

View File

@ -1104,7 +1104,14 @@ def preferred_variants(self, pkg_name):
if not isinstance(values, tuple):
values = (values,)
# perform validation of the variant and values
spec = spack.spec.Spec(pkg_name)
spec.update_variant_validate(variant_name, values)
for value in values:
self.variant_values_from_specs.add(
(pkg_name, variant.name, value)
)
self.gen.fact(fn.variant_default_value_from_packages_yaml(
pkg_name, variant.name, value
))
@ -1692,15 +1699,7 @@ def variant_value(self, pkg, name, value):
)
return
pkg_class = spack.repo.path.get_pkg_class(pkg)
variant = self._specs[pkg].variants.get(name)
if variant:
# it's multi-valued
variant.append(value)
else:
variant = pkg_class.variants[name].make_variant(value)
self._specs[pkg].variants[name] = variant
self._specs[pkg].update_variant_validate(name, value)
def version(self, pkg, version):
self._specs[pkg].versions = ver([version])

View File

@ -183,6 +183,9 @@ external_spec(Package, ID) :-
% if a variant is set to anything, it is considered 'set'.
variant_set(Package, Variant) :- variant_set(Package, Variant, _).
% A variant cannot have a value that is not also a possible value
:- variant_value(Package, Variant, Value), not variant_possible_value(Package, Variant, Value).
% variant_set is an explicitly set variant value. If it's not 'set',
% we revert to the default value. If it is set, we force the set value
variant_value(Package, Variant, Value)

View File

@ -2893,6 +2893,40 @@ def ensure_valid_variants(spec):
if not_existing:
raise vt.UnknownVariantError(spec, not_existing)
def update_variant_validate(self, variant_name, values):
"""If it is not already there, adds the variant named
`variant_name` to the spec `spec` based on the definition
contained in the package metadata. Validates the variant and
values before returning.
Used to add values to a variant without being sensitive to the
variant being single or multi-valued. If the variant already
exists on the spec it is assumed to be multi-valued and the
values are appended.
Args:
variant_name: the name of the variant to add or append to
values: the value or values (as a tuple) to add/append
to the variant
"""
if not isinstance(values, tuple):
values = (values,)
pkg_variant = self.package_class.variants[variant_name]
for value in values:
if self.variants.get(variant_name):
msg = ("Cannot append a value to a single-valued "
"variant with an already set value")
assert pkg_variant.multi, msg
self.variants[variant_name].append(value)
else:
variant = pkg_variant.make_variant(value)
self.variants[variant_name] = variant
pkg_variant.validate_or_raise(
self.variants[variant_name], self.package)
def constrain(self, other, deps=True):
"""Merge the constraints of other with self.

View File

@ -264,6 +264,10 @@ def concretize_multi_provider(self):
s.concretize()
assert s['mpi'].version == ver('1.10.3')
def test_concretize_dependent_with_singlevalued_variant_type(self):
s = Spec('singlevalue-variant-dependent-type')
s.concretize()
@pytest.mark.parametrize("spec,version", [
('dealii', 'develop'),
('xsdk', '0.4.0'),

View File

@ -82,7 +82,9 @@ class TestConcretizePreferences(object):
{'debug': True, 'opt': True, 'shared': False, 'static': False}),
# Check a multivalued variant with multiple values set
('multivalue-variant', ['foo=bar,baz', 'fee=bar'],
{'foo': ('bar', 'baz'), 'fee': 'bar'})
{'foo': ('bar', 'baz'), 'fee': 'bar'}),
('singlevalue-variant', ['fum=why'],
{'fum': 'why'})
])
def test_preferred_variants(
self, package_name, variant_value, expected_results

View File

@ -0,0 +1,16 @@
# 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 SinglevalueVariantDependentType(Package):
"""Simple package with one dependency that has a single-valued
variant with values=str"""
homepage = "http://www.example.com"
url = "http://www.example.com/archive-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef')
depends_on('singlevalue-variant fum=nope')

View File

@ -0,0 +1,19 @@
# 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 SinglevalueVariant(Package):
homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/mpileaks-1.0.tar.gz"
version(1.0, 'foobarbaz')
variant(
'fum',
description='Single-valued variant with type in values',
default='bar',
values=str,
multi=False
)