build_environment.py: deal with rpathing identical packages (#44219)
When multiple gcc-runtime packages exist in the same link sub-dag, only rpath the latest.
This commit is contained in:
		@@ -43,7 +43,7 @@
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from enum import Flag, auto
 | 
			
		||||
from itertools import chain
 | 
			
		||||
from typing import List, Set, Tuple
 | 
			
		||||
from typing import Dict, List, Set, Tuple
 | 
			
		||||
 | 
			
		||||
import llnl.util.tty as tty
 | 
			
		||||
from llnl.string import plural
 | 
			
		||||
@@ -730,12 +730,28 @@ def _static_to_shared_library(arch, compiler, static_lib, shared_lib=None, **kwa
 | 
			
		||||
    return compiler(*compiler_args, output=compiler_output)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_rpath_deps(pkg):
 | 
			
		||||
    """Return immediate or transitive RPATHs depending on the package."""
 | 
			
		||||
    if pkg.transitive_rpaths:
 | 
			
		||||
        return [d for d in pkg.spec.traverse(root=False, deptype=("link"))]
 | 
			
		||||
    else:
 | 
			
		||||
        return pkg.spec.dependencies(deptype="link")
 | 
			
		||||
def _get_rpath_deps_from_spec(
 | 
			
		||||
    spec: spack.spec.Spec, transitive_rpaths: bool
 | 
			
		||||
) -> List[spack.spec.Spec]:
 | 
			
		||||
    if not transitive_rpaths:
 | 
			
		||||
        return spec.dependencies(deptype=dt.LINK)
 | 
			
		||||
 | 
			
		||||
    by_name: Dict[str, spack.spec.Spec] = {}
 | 
			
		||||
 | 
			
		||||
    for dep in spec.traverse(root=False, deptype=dt.LINK):
 | 
			
		||||
        lookup = by_name.get(dep.name)
 | 
			
		||||
        if lookup is None:
 | 
			
		||||
            by_name[dep.name] = dep
 | 
			
		||||
        elif lookup.version < dep.version:
 | 
			
		||||
            by_name[dep.name] = dep
 | 
			
		||||
 | 
			
		||||
    return list(by_name.values())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_rpath_deps(pkg: spack.package_base.PackageBase) -> List[spack.spec.Spec]:
 | 
			
		||||
    """Return immediate or transitive dependencies (depending on the package) that need to be
 | 
			
		||||
    rpath'ed. If a package occurs multiple times, the newest version is kept."""
 | 
			
		||||
    return _get_rpath_deps_from_spec(pkg.spec, pkg.transitive_rpaths)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_rpaths(pkg):
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
 | 
			
		||||
import spack.build_environment
 | 
			
		||||
import spack.config
 | 
			
		||||
import spack.deptypes as dt
 | 
			
		||||
import spack.package_base
 | 
			
		||||
import spack.spec
 | 
			
		||||
import spack.util.spack_yaml as syaml
 | 
			
		||||
@@ -716,3 +717,21 @@ def test_build_system_globals_only_set_on_root_during_build(default_mock_concret
 | 
			
		||||
    for depth, spec in root.traverse(depth=True, root=True):
 | 
			
		||||
        for variable in build_variables:
 | 
			
		||||
            assert hasattr(spec.package.module, variable) == should_be_set(depth)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_rpath_with_duplicate_link_deps():
 | 
			
		||||
    """If we have two instances of one package in the same link sub-dag, only the newest version is
 | 
			
		||||
    rpath'ed. This is for runtime support without splicing."""
 | 
			
		||||
    runtime_1 = spack.spec.Spec("runtime@=1.0")
 | 
			
		||||
    runtime_2 = spack.spec.Spec("runtime@=2.0")
 | 
			
		||||
    child = spack.spec.Spec("child@=1.0")
 | 
			
		||||
    root = spack.spec.Spec("root@=1.0")
 | 
			
		||||
 | 
			
		||||
    root.add_dependency_edge(child, depflag=dt.LINK, virtuals=())
 | 
			
		||||
    root.add_dependency_edge(runtime_2, depflag=dt.LINK, virtuals=())
 | 
			
		||||
    child.add_dependency_edge(runtime_1, depflag=dt.LINK, virtuals=())
 | 
			
		||||
 | 
			
		||||
    rpath_deps = spack.build_environment._get_rpath_deps_from_spec(root, transitive_rpaths=True)
 | 
			
		||||
    assert child in rpath_deps
 | 
			
		||||
    assert runtime_2 in rpath_deps
 | 
			
		||||
    assert runtime_1 not in rpath_deps
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user