ASP-based solver: model disjoint sets for multivalued variants (#22534)
* ASP-based solver: avoid adding values to variants when they're set fixes #22533 fixes #21911 Added a rule that prevents any value to slip in a variant when the variant is set explicitly. This is relevant for multi-valued variants, in particular for those that have disjoint sets of values. * Ensure disjoint sets have a clear semantics for external packages
This commit is contained in:
parent
b11dd0478a
commit
e7494b627b
4 changed files with 64 additions and 2 deletions
|
@ -593,11 +593,16 @@ def pkg_rules(self, pkg, tests):
|
|||
values = []
|
||||
elif isinstance(values, spack.variant.DisjointSetsOfValues):
|
||||
union = set()
|
||||
for s in values.sets:
|
||||
# Encode the disjoint sets in the logic program
|
||||
for sid, s in enumerate(values.sets):
|
||||
for value in s:
|
||||
self.gen.fact(fn.variant_value_from_disjoint_sets(
|
||||
pkg.name, name, value, sid
|
||||
))
|
||||
union.update(s)
|
||||
values = union
|
||||
|
||||
# make sure that every variant has at least one posisble value
|
||||
# make sure that every variant has at least one possible value
|
||||
if not values:
|
||||
values = [variant.default]
|
||||
|
||||
|
|
|
@ -344,6 +344,15 @@ 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).
|
||||
|
||||
% Some multi valued variants accept multiple values from disjoint sets.
|
||||
% Ensure that we respect that constraint and we don't pick values from more
|
||||
% than one set at once
|
||||
:- variant_value(Package, Variant, Value1),
|
||||
variant_value(Package, Variant, Value2),
|
||||
variant_value_from_disjoint_sets(Package, Variant, Value1, Set1),
|
||||
variant_value_from_disjoint_sets(Package, Variant, Value2, Set2),
|
||||
Set1 != Set2.
|
||||
|
||||
% 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)
|
||||
|
@ -403,6 +412,7 @@ variant_single_value(Package, "dev_path")
|
|||
#defined variant_possible_value/3.
|
||||
#defined variant_default_value_from_packages_yaml/3.
|
||||
#defined variant_default_value_from_package_py/3.
|
||||
#defined variant_value_from_disjoint_sets/4.
|
||||
|
||||
%-----------------------------------------------------------------------------
|
||||
% Platform semantics
|
||||
|
|
|
@ -1110,3 +1110,35 @@ def test_error_message_for_inconsistent_variants(self, spec_str):
|
|||
s = Spec(spec_str)
|
||||
with pytest.raises(RuntimeError, match='not found in package'):
|
||||
s.concretize()
|
||||
|
||||
@pytest.mark.regression('22533')
|
||||
@pytest.mark.parametrize('spec_str,variant_name,expected_values', [
|
||||
# Test the default value 'auto'
|
||||
('mvapich2', 'file_systems', ('auto',)),
|
||||
# Test setting a single value from the disjoint set
|
||||
('mvapich2 file_systems=lustre', 'file_systems', ('lustre',)),
|
||||
# Test setting multiple values from the disjoint set
|
||||
('mvapich2 file_systems=lustre,gpfs', 'file_systems',
|
||||
('lustre', 'gpfs')),
|
||||
])
|
||||
def test_mv_variants_disjoint_sets_from_spec(
|
||||
self, spec_str, variant_name, expected_values
|
||||
):
|
||||
s = Spec(spec_str).concretized()
|
||||
assert set(expected_values) == set(s.variants[variant_name].value)
|
||||
|
||||
@pytest.mark.regression('22533')
|
||||
def test_mv_variants_disjoint_sets_from_packages_yaml(self):
|
||||
external_mvapich2 = {
|
||||
'mvapich2': {
|
||||
'buildable': False,
|
||||
'externals': [{
|
||||
'spec': 'mvapich2@2.3.1 file_systems=nfs,ufs',
|
||||
'prefix': '/usr'
|
||||
}]
|
||||
}
|
||||
}
|
||||
spack.config.set('packages', external_mvapich2)
|
||||
|
||||
s = Spec('mvapich2').concretized()
|
||||
assert set(s.variants['file_systems'].value) == set(['ufs', 'nfs'])
|
||||
|
|
15
var/spack/repos/builtin.mock/packages/mvapich2/package.py
Normal file
15
var/spack/repos/builtin.mock/packages/mvapich2/package.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Copyright 2013-2021 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 Mvapich2(Package):
|
||||
homepage = "http://www.homepage.org"
|
||||
url = "http://www.someurl"
|
||||
|
||||
version('1.5', '9c5d5d4fe1e17dd12153f40bc5b6dbc0')
|
||||
|
||||
variant(
|
||||
'file_systems',
|
||||
description='List of the ROMIO file systems to activate',
|
||||
values=auto_or_any_combination_of('lustre', 'gpfs', 'nfs', 'ufs'),
|
||||
)
|
Loading…
Reference in a new issue