diff options
author | Massimiliano Culpo <massimiliano.culpo@gmail.com> | 2020-11-27 20:53:39 +0100 |
---|---|---|
committer | Tamara Dahlgren <dahlgren1@llnl.gov> | 2021-02-17 17:07:17 -0800 |
commit | d7ffdd76f6703bc0f85b8c5239f11ac1f389e4e9 (patch) | |
tree | 42549af7696bd6814698a60268e6abdb57752545 /lib | |
parent | b326d59e10046f75b65c8fcbeb691faa5ea7a71a (diff) | |
download | spack-d7ffdd76f6703bc0f85b8c5239f11ac1f389e4e9.tar.gz spack-d7ffdd76f6703bc0f85b8c5239f11ac1f389e4e9.tar.bz2 spack-d7ffdd76f6703bc0f85b8c5239f11ac1f389e4e9.tar.xz spack-d7ffdd76f6703bc0f85b8c5239f11ac1f389e4e9.zip |
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.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/solver/asp.py | 55 | ||||
-rw-r--r-- | lib/spack/spack/test/concretize.py | 5 |
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() |