binary_distribution: improve deps_to_relocate (#48484)

This commit is contained in:
Harmen Stoppels 2025-01-10 11:32:11 +01:00 committed by GitHub
parent 93cd216603
commit 7edb525599
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 25 deletions

View File

@ -591,32 +591,18 @@ def file_matches(f: IO[bytes], regex: llnl.util.lang.PatternBytes) -> bool:
f.seek(0) f.seek(0)
def deps_to_relocate(spec): def specs_to_relocate(spec: spack.spec.Spec) -> List[spack.spec.Spec]:
"""Return the transitive link and direct run dependencies of the spec. """Return the set of specs that may be referenced in the install prefix of the provided spec.
We currently include non-external transitive link and direct run dependencies."""
This is a special traversal for dependencies we need to consider when relocating a package. specs = [
Package binaries, scripts, and other files may refer to the prefixes of dependencies, so
we need to rewrite those locations when dependencies are in a different place at install time
than they were at build time.
This traversal covers transitive link dependencies and direct run dependencies because:
1. Spack adds RPATHs for transitive link dependencies so that packages can find needed
dependency libraries.
2. Packages may call any of their *direct* run dependencies (and may bake their paths into
binaries or scripts), so we also need to search for run dependency prefixes when relocating.
This returns a deduplicated list of transitive link dependencies and direct run dependencies.
"""
deps = [
s s
for s in itertools.chain( for s in itertools.chain(
spec.traverse(root=True, deptype="link"), spec.dependencies(deptype="run") spec.traverse(root=True, deptype="link", order="breadth", key=traverse.by_dag_hash),
spec.dependencies(deptype="run"),
) )
if not s.external if not s.external
] ]
return llnl.util.lang.dedupe(deps, key=lambda s: s.dag_hash()) return list(llnl.util.lang.dedupe(specs, key=lambda s: s.dag_hash()))
def get_buildinfo_dict(spec): def get_buildinfo_dict(spec):
@ -630,7 +616,7 @@ def get_buildinfo_dict(spec):
# "relocate_binaries": [], # "relocate_binaries": [],
# "relocate_links": [], # "relocate_links": [],
"hardlinks_deduped": True, "hardlinks_deduped": True,
"hash_to_prefix": {d.dag_hash(): str(d.prefix) for d in deps_to_relocate(spec)}, "hash_to_prefix": {d.dag_hash(): str(d.prefix) for d in specs_to_relocate(spec)},
} }
@ -1112,7 +1098,7 @@ def _exists_in_buildcache(spec: spack.spec.Spec, tmpdir: str, out_url: str) -> E
def prefixes_to_relocate(spec): def prefixes_to_relocate(spec):
prefixes = [s.prefix for s in deps_to_relocate(spec)] prefixes = [s.prefix for s in specs_to_relocate(spec)]
prefixes.append(spack.hooks.sbang.sbang_install_path()) prefixes.append(spack.hooks.sbang.sbang_install_path())
prefixes.append(str(spack.store.STORE.layout.root)) prefixes.append(str(spack.store.STORE.layout.root))
return prefixes return prefixes
@ -2234,7 +2220,7 @@ def relocate_package(spec):
# An analog in this algorithm is any spec that shares a name or provides the same virtuals # An analog in this algorithm is any spec that shares a name or provides the same virtuals
# in the context of the relevant root spec. This ensures that the analog for a spec s # in the context of the relevant root spec. This ensures that the analog for a spec s
# is the spec that s replaced when we spliced. # is the spec that s replaced when we spliced.
relocation_specs = deps_to_relocate(spec) relocation_specs = specs_to_relocate(spec)
build_spec_ids = set(id(s) for s in spec.build_spec.traverse(deptype=dt.ALL & ~dt.BUILD)) build_spec_ids = set(id(s) for s in spec.build_spec.traverse(deptype=dt.ALL & ~dt.BUILD))
for s in relocation_specs: for s in relocation_specs:
analog = s analog = s

View File

@ -48,7 +48,7 @@ def rewire_node(spec, explicit):
# spec # spec
prefix_to_prefix = {spec.build_spec.prefix: spec.prefix} prefix_to_prefix = {spec.build_spec.prefix: spec.prefix}
build_spec_ids = set(id(s) for s in spec.build_spec.traverse(deptype=dt.ALL & ~dt.BUILD)) build_spec_ids = set(id(s) for s in spec.build_spec.traverse(deptype=dt.ALL & ~dt.BUILD))
for s in bindist.deps_to_relocate(spec): for s in bindist.specs_to_relocate(spec):
analog = s analog = s
if id(s) not in build_spec_ids: if id(s) not in build_spec_ids:
analogs = [ analogs = [