concretization for conditional dependencies
Signed-off-by: Gregory Becker <becker33@llnl.gov>
This commit is contained in:
parent
e24bd2ef3c
commit
89e0cf886d
@ -1416,12 +1416,17 @@ class ConstraintOrigin(enum.Enum):
|
||||
result.
|
||||
"""
|
||||
|
||||
CONDITIONAL_SPEC = 0
|
||||
DEPENDS_ON = 1
|
||||
REQUIRE = 2
|
||||
|
||||
@staticmethod
|
||||
def _SUFFIXES() -> Dict["ConstraintOrigin", str]:
|
||||
return {ConstraintOrigin.DEPENDS_ON: "_dep", ConstraintOrigin.REQUIRE: "_req"}
|
||||
return {
|
||||
ConstraintOrigin.CONDITIONAL_SPEC: "_cond",
|
||||
ConstraintOrigin.DEPENDS_ON: "_dep",
|
||||
ConstraintOrigin.REQUIRE: "_req",
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def append_type_suffix(pkg_id: str, kind: "ConstraintOrigin") -> str:
|
||||
@ -2613,6 +2618,10 @@ def _spec_clauses(
|
||||
if transitive:
|
||||
# TODO: Eventually distinguish 2 deps on the same pkg (build and link)
|
||||
for dspec in spec.edges_to_dependencies():
|
||||
# Ignore conditional dependencies, they are handled by caller
|
||||
if dspec.when != spack.spec.Spec():
|
||||
continue
|
||||
|
||||
dep = dspec.spec
|
||||
|
||||
if spec.concrete:
|
||||
@ -2674,22 +2683,13 @@ def _spec_clauses(
|
||||
# if it's concrete, then the hashes above take care of dependency
|
||||
# constraints, but expand the hashes if asked for.
|
||||
if not spec.concrete or expand_hashes:
|
||||
if dspec.when != spack.spec.Spec():
|
||||
# Are the non-attr things issued here a problem?
|
||||
dependency_clauses, _ = self.condition_clauses(
|
||||
required_spec=dspec.when,
|
||||
imposed_spec=dep,
|
||||
required_name=dspec.when.name or spec.name,
|
||||
msg=f"{spec.name} depends conditionally on {dep.name}",
|
||||
)
|
||||
else:
|
||||
dependency_clauses = self._spec_clauses(
|
||||
dep,
|
||||
body=body,
|
||||
expand_hashes=expand_hashes,
|
||||
concrete_build_deps=concrete_build_deps,
|
||||
context=context,
|
||||
)
|
||||
dependency_clauses = self._spec_clauses(
|
||||
dep,
|
||||
body=body,
|
||||
expand_hashes=expand_hashes,
|
||||
concrete_build_deps=concrete_build_deps,
|
||||
context=context,
|
||||
)
|
||||
if dspec.depflag == dt.BUILD:
|
||||
clauses.append(fn.attr("depends_on", spec.name, dep.name, "build"))
|
||||
if body is False:
|
||||
@ -3248,6 +3248,9 @@ def setup(
|
||||
self.gen.h1("Spec Constraints")
|
||||
self.literal_specs(specs)
|
||||
|
||||
self.trigger_rules()
|
||||
self.effect_rules()
|
||||
|
||||
self.gen.h1("Variant Values defined in specs")
|
||||
self.define_variant_values()
|
||||
|
||||
@ -3381,6 +3384,41 @@ def literal_specs(self, specs):
|
||||
cache[imposed_spec_key] = (effect_id, requirements)
|
||||
self.gen.fact(fn.pkg_fact(spec.name, fn.condition_effect(condition_id, effect_id)))
|
||||
|
||||
# Create subcondition with any conditional dependencies
|
||||
# self.spec_clauses does not do anything with conditional
|
||||
# dependencies
|
||||
for dspec in spec.traverse_edges():
|
||||
# Ignore unconditional deps
|
||||
if dspec.when == spack.spec.Spec():
|
||||
continue
|
||||
|
||||
# Cannot use "virtual_node" attr as key for condition
|
||||
# because reused specs do not track virtual nodes.
|
||||
# Instead, track whether the parent uses the virtual
|
||||
def virtual_handler(input_spec, requirements):
|
||||
ret = remove_facts("virtual_node")(input_spec, requirements)
|
||||
for edge in input_spec.traverse_edges(root=False, cover="edges"):
|
||||
if spack.repo.PATH.is_virtual(edge.spec.name):
|
||||
ret.append(fn.attr("uses_virtual", edge.parent.name, edge.spec.name))
|
||||
return ret
|
||||
|
||||
context = ConditionContext()
|
||||
context.source = ConstraintOrigin.append_type_suffix(
|
||||
dspec.parent.name, ConstraintOrigin.CONDITIONAL_SPEC
|
||||
)
|
||||
# Default is to remove node-like attrs, override here
|
||||
context.transform_required = virtual_handler
|
||||
context.transform_imposed = lambda x, y: y
|
||||
|
||||
subcondition_id = self.condition(
|
||||
dspec.when,
|
||||
dspec.spec,
|
||||
required_name=dspec.parent.name,
|
||||
context=context,
|
||||
msg=f"Conditional dependency in literal ^[when={dspec.when}]{dspec.spec}",
|
||||
)
|
||||
self.gen.fact(fn.subcondition(subcondition_id, condition_id))
|
||||
|
||||
if self.concretize_everything:
|
||||
self.gen.fact(fn.solve_literal(trigger_id))
|
||||
|
||||
@ -3833,6 +3871,7 @@ class SpecBuilder:
|
||||
r"^package_hash$",
|
||||
r"^root$",
|
||||
r"^track_dependencies$",
|
||||
r"^uses_virtual$",
|
||||
r"^variant_default_value_from_cli$",
|
||||
r"^virtual_node$",
|
||||
r"^virtual_on_incoming_edges$",
|
||||
|
@ -429,8 +429,23 @@ trigger_and_effect(Package, TriggerID, EffectID)
|
||||
|
||||
% condition_holds(ID, node(ID, Package)) implies all imposed_constraints, unless do_not_impose(ID, node(ID, Package))
|
||||
% is derived. This allows imposed constraints to be canceled in special cases.
|
||||
|
||||
% Effects of direct conditions hold if the trigger holds
|
||||
impose(EffectID, node(X, Package))
|
||||
:- trigger_and_effect(Package, TriggerID, EffectID),
|
||||
:- pkg_fact(Package, condition_effect(ConditionID, EffectID)),
|
||||
not subcondition(ConditionID, _),
|
||||
trigger_and_effect(Package, TriggerID, EffectID),
|
||||
trigger_node(TriggerID, _, node(X, Package)),
|
||||
trigger_condition_holds(TriggerID, node(X, Package)),
|
||||
not do_not_impose(EffectID, node(X, Package)).
|
||||
|
||||
% Effects of subconditions hold if the trigger holds and the
|
||||
% primary condition holds
|
||||
impose(EffectID, node(X, Package))
|
||||
:- pkg_fact(Package, condition_effect(SubconditionId, EffectID)),
|
||||
subcondition(SubconditionID, ConditionID),
|
||||
condition_holds(ConditionID, node(X, Package)),
|
||||
trigger_and_effect(Package, TriggerID, EffectID),
|
||||
trigger_node(TriggerID, _, node(X, Package)),
|
||||
trigger_condition_holds(TriggerID, node(X, Package)),
|
||||
not do_not_impose(EffectID, node(X, Package)).
|
||||
@ -645,6 +660,16 @@ virtual_condition_holds(node(Y, A2), Virtual)
|
||||
attr("virtual_on_edge", node(X, A1), node(Y, A2), Virtual),
|
||||
not build(node(X, A1)).
|
||||
|
||||
% Simplified virtual information for conditionl requirements in
|
||||
% conditional dependencies
|
||||
% Most specs track virtuals on edges
|
||||
attr("uses_virtual", PackageNode, Virtual) :-
|
||||
attr("virtual_on_edge", PackageNode, _, Virtual).
|
||||
|
||||
% Reused specs don't track a real edge to build-only deps
|
||||
attr("uses_virtual", PackageNode, Virtual) :-
|
||||
attr("virtual_on_build_edge", PackageNode, _, Virtual).
|
||||
|
||||
% we cannot have additional variant values when we are working with concrete specs
|
||||
:- attr("node", node(ID, Package)),
|
||||
attr("hash", node(ID, Package), Hash),
|
||||
@ -660,6 +685,7 @@ virtual_condition_holds(node(Y, A2), Virtual)
|
||||
internal_error("imposed hash without imposing all flag values").
|
||||
|
||||
#defined condition/2.
|
||||
#defined subcondition/2.
|
||||
#defined condition_requirement/3.
|
||||
#defined condition_requirement/4.
|
||||
#defined condition_requirement/5.
|
||||
|
Loading…
Reference in New Issue
Block a user