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:
parent
b326d59e10
commit
d7ffdd76f6
@ -696,6 +696,7 @@ def __init__(self):
|
|||||||
self.possible_virtuals = None
|
self.possible_virtuals = None
|
||||||
self.possible_compilers = []
|
self.possible_compilers = []
|
||||||
self.version_constraints = set()
|
self.version_constraints = set()
|
||||||
|
self.target_constraints = set()
|
||||||
self.providers_by_vspec_name = collections.defaultdict(list)
|
self.providers_by_vspec_name = collections.defaultdict(list)
|
||||||
self.virtual_constraints = set()
|
self.virtual_constraints = set()
|
||||||
self.compiler_version_constraints = set()
|
self.compiler_version_constraints = set()
|
||||||
@ -765,6 +766,16 @@ def spec_versions(self, spec):
|
|||||||
self.version_constraints.add((spec.name, spec.versions))
|
self.version_constraints.add((spec.name, spec.versions))
|
||||||
return [fn.version_satisfies(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):
|
def conflict_rules(self, pkg):
|
||||||
for trigger, constraints in pkg.conflicts.items():
|
for trigger, constraints in pkg.conflicts.items():
|
||||||
for constraint, _ in constraints:
|
for constraint, _ in constraints:
|
||||||
@ -1167,7 +1178,7 @@ class Body(object):
|
|||||||
if arch.os:
|
if arch.os:
|
||||||
clauses.append(f.node_os(spec.name, arch.os))
|
clauses.append(f.node_os(spec.name, arch.os))
|
||||||
if arch.target:
|
if arch.target:
|
||||||
clauses.append(f.node_target(spec.name, arch.target))
|
clauses.extend(self.target_ranges(spec, f.node_target))
|
||||||
|
|
||||||
# variants
|
# variants
|
||||||
for vname, variant in sorted(spec.variants.items()):
|
for vname, variant in sorted(spec.variants.items()):
|
||||||
@ -1438,6 +1449,45 @@ def define_compiler_version_constraints(self):
|
|||||||
)
|
)
|
||||||
self.gen.newline()
|
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):
|
def setup(self, driver, specs, tests=False):
|
||||||
"""Generate an ASP program with relevant constraints for specs.
|
"""Generate an ASP program with relevant constraints for specs.
|
||||||
|
|
||||||
@ -1561,6 +1611,9 @@ def setup(self, driver, specs, tests=False):
|
|||||||
self.gen.h1("Compiler Version Constraints")
|
self.gen.h1("Compiler Version Constraints")
|
||||||
self.define_compiler_version_constraints()
|
self.define_compiler_version_constraints()
|
||||||
|
|
||||||
|
self.gen.h1("Target Constraints")
|
||||||
|
self.define_target_constraints()
|
||||||
|
|
||||||
def virtual_spec_clauses(self, dep):
|
def virtual_spec_clauses(self, dep):
|
||||||
assert dep.virtual
|
assert dep.virtual
|
||||||
self.virtual_constraints.add(str(dep))
|
self.virtual_constraints.add(str(dep))
|
||||||
|
@ -938,3 +938,8 @@ def test_compiler_match_is_preferred_to_newer_version(self):
|
|||||||
|
|
||||||
assert 'openblas@0.2.13' in s
|
assert 'openblas@0.2.13' in s
|
||||||
assert s['openblas'].satisfies('%gcc@4.4.0')
|
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()
|
||||||
|
@ -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:')
|
Loading…
Reference in New Issue
Block a user