bugfix: allow imposed constraints to be overridden in special cases

In most cases, we want condition_holds(ID) to imply any imposed
constraints associated with the ID. However, the dependency relationship
in Spack is special because it's "extra" conditional -- a dependency
*condition* may hold, but we have decided that externals will not have
dependencies, so we need a way to avoid having imposed constraints appear
for nodes that don't exist.

This introduces a new rule that says that constraints are imposed
*unless* we define `do_not_impose(ID)`. This allows rules like
dependencies, which rely on more than just spec conditions, to cancel
imposed constraints.

We add one special case for this: dependencies of externals.
This commit is contained in:
Todd Gamblin 2021-03-13 16:03:50 -08:00 committed by Massimiliano Culpo
parent e7cba04b95
commit 3e570ce694

View file

@ -54,10 +54,14 @@ condition_holds(ID) :-
attr(Name, A1, A2) : condition_requirement(ID, Name, A1, A2); attr(Name, A1, A2) : condition_requirement(ID, Name, A1, A2);
attr(Name, A1, A2, A3) : condition_requirement(ID, Name, A1, A2, A3). attr(Name, A1, A2, A3) : condition_requirement(ID, Name, A1, A2, A3).
% condition_holds(ID) implies all imposed_constraints, unless do_not_impose(ID)
% is derived. This allows imposed constraints to be canceled in special cases.
impose(ID) :- condition_holds(ID), not do_not_impose(ID).
% conditions that hold impose constraints on other specs % conditions that hold impose constraints on other specs
attr(Name, A1) :- condition_holds(ID), imposed_constraint(ID, Name, A1). attr(Name, A1) :- impose(ID), imposed_constraint(ID, Name, A1).
attr(Name, A1, A2) :- condition_holds(ID), imposed_constraint(ID, Name, A1, A2). attr(Name, A1, A2) :- impose(ID), imposed_constraint(ID, Name, A1, A2).
attr(Name, A1, A2, A3) :- condition_holds(ID), imposed_constraint(ID, Name, A1, A2, A3). attr(Name, A1, A2, A3) :- impose(ID), imposed_constraint(ID, Name, A1, A2, A3).
#defined condition/1. #defined condition/1.
#defined condition_requirement/3. #defined condition_requirement/3.
@ -77,15 +81,21 @@ depends_on(Package, Dependency) :- depends_on(Package, Dependency, _).
dependency_holds(Package, Dependency, Type) :- dependency_holds(Package, Dependency, Type) :-
dependency_condition(ID, Package, Dependency), dependency_condition(ID, Package, Dependency),
dependency_type(ID, Type), dependency_type(ID, Type),
condition_holds(ID). condition_holds(ID),
not external(Package).
% We cut off dependencies of externals (as we don't really know them).
% Don't impose constraints on dependencies that don't exist.
do_not_impose(ID) :-
not dependency_holds(Package, Dependency, _),
dependency_condition(ID, Package, Dependency).
% declared dependencies are real if they're not virtual AND % declared dependencies are real if they're not virtual AND
% the package is not an external. % the package is not an external.
% They're only triggered if the associated dependnecy condition holds. % They're only triggered if the associated dependnecy condition holds.
depends_on(Package, Dependency, Type) depends_on(Package, Dependency, Type)
:- dependency_holds(Package, Dependency, Type), :- dependency_holds(Package, Dependency, Type),
not virtual(Dependency), not virtual(Dependency).
not external(Package).
% every root must be a node % every root must be a node
node(Package) :- root(Package). node(Package) :- root(Package).