summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/solver/asp.py55
-rw-r--r--lib/spack/spack/test/concretize.py5
2 files changed, 59 insertions, 1 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 4ea54663be..9c78546455 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -696,6 +696,7 @@ class SpackSolverSetup(object):
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 @@ class SpackSolverSetup(object):
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 SpackSolverSetup(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()):
@@ -1438,6 +1449,45 @@ class SpackSolverSetup(object):
)
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.
@@ -1561,6 +1611,9 @@ class SpackSolverSetup(object):
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))
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index 11c2764822..39799fc1bc 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -938,3 +938,8 @@ class TestConcretize(object):
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()