concretizer: treat target ranges in directives correctly (#19988)

fixes #19981

This commit adds support for target ranges in directives,
for instance:

conflicts('+foo', when='target=x86_64:,aarch64:')

If any target in a spec body is not a known target the
following clause will be emitted:

node_target_satisfies(Package, TargetConstraint)

when traversing the spec and a definition of
the clause will then be printed at the end similarly
to what is done for package and compiler versions.
This commit is contained in:
Massimiliano Culpo 2020-11-27 20:53:39 +01:00 committed by GitHub
parent e6641065af
commit 8dd3797d32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 1 deletions

View file

@ -696,6 +696,7 @@ def __init__(self):
self.possible_virtuals = None
self.possible_compilers = []
self.version_constraints = set()
self.target_constraints = set()
self.providers_by_vspec_name = collections.defaultdict(list)
self.virtual_constraints = set()
self.compiler_version_constraints = set()
@ -765,6 +766,16 @@ def spec_versions(self, spec):
self.version_constraints.add((spec.name, spec.versions))
return [fn.version_satisfies(spec.name, spec.versions)]
def target_ranges(self, spec, single_target_fn):
target = spec.architecture.target
# Check if the target is a concrete target
if str(target) in archspec.cpu.TARGETS:
return [single_target_fn(spec.name, target)]
self.target_constraints.add((spec.name, target))
return [fn.node_target_satisfies(spec.name, target)]
def conflict_rules(self, pkg):
for trigger, constraints in pkg.conflicts.items():
for constraint, _ in constraints:
@ -1167,7 +1178,7 @@ class Body(object):
if arch.os:
clauses.append(f.node_os(spec.name, arch.os))
if arch.target:
clauses.append(f.node_target(spec.name, arch.target))
clauses.extend(self.target_ranges(spec, f.node_target))
# variants
for vname, variant in sorted(spec.variants.items()):
@ -1437,6 +1448,45 @@ def define_compiler_version_constraints(self):
)
self.gen.newline()
def define_target_constraints(self):
def _all_targets_satisfiying(single_constraint):
allowed_targets = []
t_min, _, t_max = single_constraint.partition(':')
for test_target in archspec.cpu.TARGETS.values():
# Check lower bound
if t_min and not t_min <= test_target:
continue
# Check upper bound
if t_max and not t_max >= test_target:
continue
allowed_targets.append(test_target)
return allowed_targets
cache = {}
for spec_name, target_constraint in sorted(self.target_constraints):
# Construct the list of allowed targets for this constraint
allowed_targets = []
for single_constraint in str(target_constraint).split(','):
if single_constraint not in cache:
cache[single_constraint] = _all_targets_satisfiying(
single_constraint
)
allowed_targets.extend(cache[single_constraint])
allowed_targets = [
fn.node_target(spec_name, t) for t in allowed_targets
]
self.gen.one_of_iff(
fn.node_target_satisfies(spec_name, target_constraint),
allowed_targets,
)
self.gen.newline()
def setup(self, driver, specs, tests=False):
"""Generate an ASP program with relevant constraints for specs.
@ -1560,6 +1610,9 @@ def setup(self, driver, specs, tests=False):
self.gen.h1("Compiler Version Constraints")
self.define_compiler_version_constraints()
self.gen.h1("Target Constraints")
self.define_target_constraints()
def virtual_spec_clauses(self, dep):
assert dep.virtual
self.virtual_constraints.add(str(dep))

View file

@ -938,3 +938,8 @@ def test_compiler_match_is_preferred_to_newer_version(self):
assert 'openblas@0.2.13' in s
assert s['openblas'].satisfies('%gcc@4.4.0')
@pytest.mark.regression('19981')
def test_target_ranges_in_conflicts(self):
with pytest.raises(spack.error.SpackError):
Spec('impossible-concretization').concretized()

View file

@ -0,0 +1,15 @@
# 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 ImpossibleConcretization(Package):
"""Package that should be impossible to concretize due to a conflict
with target ranges. See Issue 19981.
"""
homepage = "http://www.example.com"
url = "http://www.example.com/example-1.0.tar.gz"
version(1.0, 'foobarbaz')
conflicts('target=x86_64:')