ASP-based solver: use edge properties for reused specs (#39508)
Since #34821 we are annotating virtual dependencies on DAG edges, and reconstructing virtuals in memory when we read a concrete spec from previous formats. Therefore, we can remove a TODO in asp.py, and rely on "virtual_on_edge" facts to be imposed.
This commit is contained in:
parent
9f1a30d3b5
commit
9ae1317e79
@ -1827,37 +1827,11 @@ class Body:
|
|||||||
# skip build dependencies of already-installed specs
|
# skip build dependencies of already-installed specs
|
||||||
if concrete_build_deps or dtype != "build":
|
if concrete_build_deps or dtype != "build":
|
||||||
clauses.append(fn.attr("depends_on", spec.name, dep.name, dtype))
|
clauses.append(fn.attr("depends_on", spec.name, dep.name, dtype))
|
||||||
|
for virtual_name in dspec.virtuals:
|
||||||
# TODO: We have to look up info from package.py here, but we'd
|
clauses.append(
|
||||||
# TODO: like to avoid this entirely. We should not need to look
|
fn.attr("virtual_on_edge", spec.name, dep.name, virtual_name)
|
||||||
# TODO: up potentially wrong info if we have virtual edge info.
|
)
|
||||||
try:
|
clauses.append(fn.attr("virtual_node", virtual_name))
|
||||||
try:
|
|
||||||
pkg = dep.package
|
|
||||||
|
|
||||||
except spack.repo.UnknownNamespaceError:
|
|
||||||
# Try to look up the package of the same name and use its
|
|
||||||
# providers. This is as good as we can do without edge info.
|
|
||||||
pkg_class = spack.repo.PATH.get_pkg_class(dep.name)
|
|
||||||
spec = spack.spec.Spec(f"{dep.name}@{dep.version}")
|
|
||||||
pkg = pkg_class(spec)
|
|
||||||
|
|
||||||
virtuals = pkg.virtuals_provided
|
|
||||||
|
|
||||||
except spack.repo.UnknownPackageError:
|
|
||||||
# Skip virtual node constriants for renamed/deleted packages,
|
|
||||||
# so their binaries can still be installed.
|
|
||||||
# NOTE: with current specs (which lack edge attributes) this
|
|
||||||
# can allow concretizations with two providers, but it's unlikely.
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Don't concretize with two providers of the same virtual.
|
|
||||||
# See above for exception for unknown packages.
|
|
||||||
# TODO: we will eventually record provider information on edges,
|
|
||||||
# TODO: which avoids the need for the package lookup above.
|
|
||||||
for virtual in virtuals:
|
|
||||||
clauses.append(fn.attr("virtual_node", virtual.name))
|
|
||||||
clauses.append(fn.provider(dep.name, virtual.name))
|
|
||||||
|
|
||||||
# imposing hash constraints for all but pure build deps of
|
# imposing hash constraints for all but pure build deps of
|
||||||
# already-installed concrete specs.
|
# already-installed concrete specs.
|
||||||
|
@ -113,6 +113,7 @@ unification_set(SetID, VirtualNode)
|
|||||||
% Node attributes that have multiple node arguments (usually, only the first argument is a node)
|
% Node attributes that have multiple node arguments (usually, only the first argument is a node)
|
||||||
multiple_nodes_attribute("node_flag_source").
|
multiple_nodes_attribute("node_flag_source").
|
||||||
multiple_nodes_attribute("depends_on").
|
multiple_nodes_attribute("depends_on").
|
||||||
|
multiple_nodes_attribute("virtual_on_edge").
|
||||||
|
|
||||||
% Map constraint on the literal ID to facts on the node
|
% Map constraint on the literal ID to facts on the node
|
||||||
attr(Name, node(min_dupe_id, A1)) :- literal(LiteralID, Name, A1), solve_literal(LiteralID).
|
attr(Name, node(min_dupe_id, A1)) :- literal(LiteralID, Name, A1), solve_literal(LiteralID).
|
||||||
@ -367,6 +368,18 @@ attr("node_flag_source", node(X, A1), A2, node(Y, A3))
|
|||||||
:- impose(ID, node(X, A1)),
|
:- impose(ID, node(X, A1)),
|
||||||
imposed_constraint(ID, "depends_on", A1, A2, A3).
|
imposed_constraint(ID, "depends_on", A1, A2, A3).
|
||||||
|
|
||||||
|
% Reconstruct virtual dependencies for reused specs
|
||||||
|
attr("virtual_on_edge", node(X, A1), node(Y, A2), Virtual)
|
||||||
|
:- impose(ID, node(X, A1)),
|
||||||
|
depends_on(node(X, A1), node(Y, A2)),
|
||||||
|
imposed_constraint(ID, "virtual_on_edge", A1, A2, Virtual),
|
||||||
|
not build(node(X, A1)).
|
||||||
|
|
||||||
|
virtual_condition_holds(node(Y, A2), Virtual)
|
||||||
|
:- impose(ID, node(X, A1)),
|
||||||
|
attr("virtual_on_edge", node(X, A1), node(Y, A2), Virtual),
|
||||||
|
not build(node(X, A1)).
|
||||||
|
|
||||||
% we cannot have additional variant values when we are working with concrete specs
|
% we cannot have additional variant values when we are working with concrete specs
|
||||||
:- attr("node", node(ID, Package)),
|
:- attr("node", node(ID, Package)),
|
||||||
attr("hash", node(ID, Package), Hash),
|
attr("hash", node(ID, Package), Hash),
|
||||||
|
@ -2099,6 +2099,21 @@ def test_virtuals_are_annotated_on_edges(self, spec_str, default_mock_concretiza
|
|||||||
edges = spec.edges_to_dependencies(name="callpath")
|
edges = spec.edges_to_dependencies(name="callpath")
|
||||||
assert len(edges) == 1 and edges[0].virtuals == ()
|
assert len(edges) == 1 and edges[0].virtuals == ()
|
||||||
|
|
||||||
|
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
|
||||||
|
@pytest.mark.db
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"spec_str,mpi_name",
|
||||||
|
[("mpileaks", "mpich"), ("mpileaks ^mpich2", "mpich2"), ("mpileaks ^zmpi", "zmpi")],
|
||||||
|
)
|
||||||
|
def test_virtuals_are_reconstructed_on_reuse(self, spec_str, mpi_name, database):
|
||||||
|
"""Tests that when we reuse a spec, virtual on edges are reconstructed correctly"""
|
||||||
|
with spack.config.override("concretizer:reuse", True):
|
||||||
|
spec = Spec(spec_str).concretized()
|
||||||
|
assert spec.installed
|
||||||
|
mpi_edges = spec.edges_to_dependencies(mpi_name)
|
||||||
|
assert len(mpi_edges) == 1
|
||||||
|
assert "mpi" in mpi_edges[0].virtuals
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def duplicates_test_repository():
|
def duplicates_test_repository():
|
||||||
|
Loading…
Reference in New Issue
Block a user