summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/solver/asp.py41
-rw-r--r--lib/spack/spack/solver/concretize.lp37
2 files changed, 60 insertions, 18 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 9de674ab60..167baea0da 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -729,10 +729,17 @@ class SpackSolverSetup(object):
def package_dependencies_rules(self, pkg, tests):
"""Translate 'depends_on' directives into ASP logic."""
for name, conditions in sorted(pkg.dependencies.items()):
- for cond, dep in sorted(conditions.items()):
+ for cond_id, (cond, dep) in enumerate(sorted(conditions.items())):
named_cond = cond.copy()
named_cond.name = named_cond.name or pkg.name
+ # each independent condition has an id
+ self.gen.fact(
+ fn.dependency_condition(
+ dep.pkg.name, dep.spec.name, cond_id
+ )
+ )
+
for t in sorted(dep.type):
# Skip test dependencies if they're not requested at all
if t == 'test' and not tests:
@@ -743,22 +750,29 @@ class SpackSolverSetup(object):
and pkg.name not in tests):
continue
- if cond == spack.spec.Spec():
+ # there is a declared dependency of type t
+
+ # TODO: this ends up being redundant in the output --
+ # TODO: not sure if we really need it anymore.
+ # TODO: Look at simplifying the logic in concretize.lp
+ self.gen.fact(
+ fn.declared_dependency(dep.pkg.name, dep.spec.name, t))
+
+ # if it has conditions, declare them.
+ conditions = self.spec_clauses(named_cond, body=True)
+ for cond in conditions:
self.gen.fact(
- fn.declared_dependency(
- dep.pkg.name, dep.spec.name, t
+ fn.dep_cond(
+ dep.pkg.name, dep.spec.name, t, cond_id,
+ cond.name, *cond.args
)
)
- else:
- clauses = self.spec_clauses(named_cond, body=True)
-
- self.gen.rule(
- fn.declared_dependency(
- dep.pkg.name, dep.spec.name, t
- ), self.gen._and(*clauses)
- )
# add constraints on the dependency from dep spec.
+
+ # TODO: nest this in the type loop so that dependency
+ # TODO: constraints apply only for their deptypes and
+ # TODO: specific conditions.
if spack.repo.path.is_virtual(dep.spec.name):
self.virtual_constraints.add(str(dep.spec))
conditions = ([fn.real_node(pkg.name)] +
@@ -779,7 +793,8 @@ class SpackSolverSetup(object):
*self.spec_clauses(named_cond, body=True)
)
)
- self.gen.newline()
+
+ self.gen.newline()
def virtual_preferences(self, pkg_name, func):
"""Call func(vspec, provider, i) for each of pkg's provider prefs."""
diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp
index 0affb9f297..7c4e0d6d02 100644
--- a/lib/spack/spack/solver/concretize.lp
+++ b/lib/spack/spack/solver/concretize.lp
@@ -40,8 +40,7 @@ depends_on(Package, Dependency) :- depends_on(Package, Dependency, _).
% declared dependencies are real if they're not virtual AND
% the package is not an external
depends_on(Package, Dependency, Type)
- :- declared_dependency(Package, Dependency, Type),
- node(Package),
+ :- dependency_conditions(Package, Dependency, Type),
not virtual(Dependency),
not external(Package).
@@ -51,10 +50,38 @@ depends_on(Package, Dependency, Type)
depends_on(Package, Provider, Type)
: provides_virtual(Provider, Virtual)
} 1
- :- declared_dependency(Package, Virtual, Type),
+ :- dependency_conditions(Package, Virtual, Type),
virtual(Virtual),
- not external(Package),
- node(Package).
+ not external(Package).
+
+% if any individual condition below is true, trigger the dependency.
+dependency_conditions(P, D, T) :- dependency_conditions(P, D, T, _).
+
+% collect all the dependency condtions into a single conditional rule
+dependency_conditions(P, D, T, I) :-
+ node(Package)
+ : dep_cond(P, D, T, I, "node", Package);
+ version(Package, Version)
+ : dep_cond(P, D, T, I, "version", Package, Version);
+ version_satisfies(Package, Constraint)
+ : dep_cond(P, D, T, I, "version_satisfies", Package, Constraint);
+ node_platform(Package, Platform)
+ : dep_cond(P, D, T, I, "node_platform", Package, Platform);
+ node_os(Package, OS)
+ : dep_cond(P, D, T, I, "node_os", Package, OS);
+ node_target(Package, Target)
+ : dep_cond(P, D, T, I, "node_target", Package, Target);
+ variant_value(Package, Variant, Value)
+ : dep_cond(P, D, T, I, "variant_value", Package, Variant, Value);
+ node_compiler(Package, Compiler)
+ : dep_cond(P, D, T, I, "node_compiler", Package, Compiler);
+ node_compiler_version(Package, Compiler, Version)
+ : dep_cond(P, D, T, I, "node_compiler_version", Package, Compiler, Version);
+ node_flag(Package, FlagType, Flag)
+ : dep_cond(P, D, T, I, "node_flag", Package, FlagType, Flag);
+ dependency_condition(P, D, I);
+ declared_dependency(P, D, T);
+ node(P).
% if a virtual was required by some root spec, one provider is in the DAG
1 { node(Package) : provides_virtual(Package, Virtual) } 1