From 520b71e89bc321a67b6c84d346b0be7d4f0ebaad Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sun, 26 Jan 2020 16:10:03 -0800 Subject: concretizer: handle virtual spec constraints better Specs like hdf5 ^mpi were unsatisfiable because we added a requierment for `node("mpi").`. This can't be resolved because "mpi" is not a package. - [x] Introduce `virtual_node()`, which says *some* provider must be in the DAG. --- lib/spack/spack/solver/asp.py | 11 +++++++---- lib/spack/spack/solver/concretize.lp | 4 ++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index a7ca8b0ac5..3ed46328e4 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -360,7 +360,7 @@ class AspGenerator(object): self.fact( fn.variant_default_value(pkg.name, name, variant.default)) else: - self.rule(self._not(single), fn.node(pkg.name)) + self.fact(self._not(single)) defaults = variant.default.split(',') for val in sorted(defaults): self.fact(fn.variant_default_value(pkg.name, name, val)) @@ -706,9 +706,12 @@ class AspGenerator(object): self.fact(fn.root(spec.name)) for dep in spec.traverse(): self.h2('Spec: %s' % str(dep)) - self.fact(fn.node(dep.name)) - for clause in self.spec_clauses(dep): - self.rule(clause, fn.node(dep.name)) + + if dep.virtual: + self.fact(fn.virtual_node(dep.name)) + else: + for clause in self.spec_clauses(dep): + self.fact(clause) self.out.write('\n') display_lp = pkgutil.get_data('spack.solver', 'display.lp') diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index dccf4a2750..b2e698b5ff 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -33,6 +33,9 @@ depends_on(P, D, T) :- declared_dependency(P, D, T), not virtual(D), node(P). 1 { depends_on(P, Q, T) : provides_virtual(Q, V) } 1 :- declared_dependency(P, V, T), virtual(V), node(P). +% if a virtual was required by some root spec, one provider is in the DAG +1 { node(P) : provides_virtual(P, V) } 1 :- virtual_node(V). + % for any virtual, there can be at most one provider in the DAG provider(P, V) :- node(P), provides_virtual(P, V). 0 { provider(P, V) : node(P) } 1 :- virtual(V). @@ -66,6 +69,7 @@ node(D) :- node(P), depends_on(P, D). #defined depends_on/3. #defined declared_dependency/3. #defined virtual/1. +#defined virtual_node/1. #defined provides_virtual/2. #defined pkg_provider_preference/4. #defined default_provider_preference/3. -- cgit v1.2.3-70-g09d2