diff --git a/lib/spack/spack/binary_distribution.py b/lib/spack/spack/binary_distribution.py index 8439f25fc01cc2..e3a99051cabb5f 100644 --- a/lib/spack/spack/binary_distribution.py +++ b/lib/spack/spack/binary_distribution.py @@ -2189,7 +2189,12 @@ def relocate_package(spec): old_spack_prefix = str(buildinfo.get("spackprefix")) old_rel_prefix = buildinfo.get("relative_prefix") old_prefix = os.path.join(old_layout_root, old_rel_prefix) - rel = buildinfo.get("relative_rpaths", False) + + # Warn about old style tarballs created with the now removed --rel flag. + if buildinfo.get("relative_rpaths", False): + tty.warn( + f"Tarball for {spec} uses relative rpaths, " "which can cause library loading issues." + ) # In the past prefix_to_hash was the default and externals were not dropped, so prefixes # were not unique. @@ -2267,19 +2272,11 @@ def relocate_package(spec): tty.debug("Relocating package from", "%s to %s." % (old_layout_root, new_layout_root)) - # Old archives maybe have hardlinks repeated. + # Old archives may have hardlinks repeated. dedupe_hardlinks_if_necessary(workdir, buildinfo) - def is_backup_file(file): - return file.endswith("~") - # Text files containing the prefix text - text_names = list() - for filename in buildinfo["relocate_textfiles"]: - text_name = os.path.join(workdir, filename) - # Don't add backup files generated by filter_file during install step. - if not is_backup_file(text_name): - text_names.append(text_name) + text_names = [os.path.join(workdir, f) for f in buildinfo["relocate_textfiles"]] # If we are not installing back to the same install tree do the relocation if old_prefix != new_prefix: @@ -2290,29 +2287,11 @@ def is_backup_file(file): # do the relocation of path in binaries platform = spack.platforms.by_name(spec.platform) if "macho" in platform.binary_formats: - relocate.relocate_macho_binaries( - files_to_relocate, - old_layout_root, - new_layout_root, - prefix_to_prefix_bin, - rel, - old_prefix, - new_prefix, - ) - elif "elf" in platform.binary_formats and not rel: + relocate.relocate_macho_binaries(files_to_relocate, prefix_to_prefix_bin) + elif "elf" in platform.binary_formats: # The new ELF dynamic section relocation logic only handles absolute to # absolute relocation. - relocate.new_relocate_elf_binaries(files_to_relocate, prefix_to_prefix_bin) - elif "elf" in platform.binary_formats and rel: - relocate.relocate_elf_binaries( - files_to_relocate, - old_layout_root, - new_layout_root, - prefix_to_prefix_bin, - rel, - old_prefix, - new_prefix, - ) + relocate.relocate_elf_binaries(files_to_relocate, prefix_to_prefix_bin) # Relocate links to the new install prefix links = [os.path.join(workdir, f) for f in buildinfo.get("relocate_links", [])] diff --git a/lib/spack/spack/relocate.py b/lib/spack/spack/relocate.py index 979bbd7d56b033..9ba36ab5610c4a 100644 --- a/lib/spack/spack/relocate.py +++ b/lib/spack/spack/relocate.py @@ -54,144 +54,11 @@ def _patchelf() -> Optional[executable.Executable]: return spack.bootstrap.ensure_patchelf_in_path_or_raise() -def _elf_rpaths_for(path): - """Return the RPATHs for an executable or a library. - - Args: - path (str): full path to the executable or library - - Return: - RPATHs as a list of strings. Returns an empty array - on ELF parsing errors, or when the ELF file simply - has no rpaths. - """ - return elf.get_rpaths(path) or [] - - -def _make_relative(reference_file, path_root, paths): - """Return a list where any path in ``paths`` that starts with - ``path_root`` is made relative to the directory in which the - reference file is stored. - - After a path is made relative it is prefixed with the ``$ORIGIN`` - string. - - Args: - reference_file (str): file from which the reference directory - is computed - path_root (str): root of the relative paths - paths: (list) paths to be examined - - Returns: - List of relative paths - """ - start_directory = os.path.dirname(reference_file) - pattern = re.compile(path_root) - relative_paths = [] - - for path in paths: - if pattern.match(path): - rel = os.path.relpath(path, start=start_directory) - path = os.path.join("$ORIGIN", rel) - - relative_paths.append(path) - - return relative_paths - - -def _normalize_relative_paths(start_path, relative_paths): - """Normalize the relative paths with respect to the original path name - of the file (``start_path``). - - The paths that are passed to this function existed or were relevant - on another filesystem, so os.path.abspath cannot be used. - - A relative path may contain the signifier $ORIGIN. Assuming that - ``start_path`` is absolute, this implies that the relative path - (relative to start_path) should be replaced with an absolute path. - - Args: - start_path (str): path from which the starting directory - is extracted - relative_paths (str): list of relative paths as obtained by a - call to :ref:`_make_relative` - - Returns: - List of normalized paths - """ - normalized_paths = [] - pattern = re.compile(re.escape("$ORIGIN")) - start_directory = os.path.dirname(start_path) - - for path in relative_paths: - if path.startswith("$ORIGIN"): - sub = pattern.sub(start_directory, path) - path = os.path.normpath(sub) - normalized_paths.append(path) - - return normalized_paths - - def _decode_macho_data(bytestring): return bytestring.rstrip(b"\x00").decode("ascii") -def macho_make_paths_relative(path_name, old_layout_root, rpaths, deps, idpath): - """ - Return a dictionary mapping the original rpaths to the relativized rpaths. - This dictionary is used to replace paths in mach-o binaries. - Replace old_dir with relative path from dirname of path name - in rpaths and deps; idpath is replaced with @rpath/libname. - """ - paths_to_paths = dict() - if idpath: - paths_to_paths[idpath] = os.path.join("@rpath", "%s" % os.path.basename(idpath)) - for rpath in rpaths: - if re.match(old_layout_root, rpath): - rel = os.path.relpath(rpath, start=os.path.dirname(path_name)) - paths_to_paths[rpath] = os.path.join("@loader_path", "%s" % rel) - else: - paths_to_paths[rpath] = rpath - for dep in deps: - if re.match(old_layout_root, dep): - rel = os.path.relpath(dep, start=os.path.dirname(path_name)) - paths_to_paths[dep] = os.path.join("@loader_path", "%s" % rel) - else: - paths_to_paths[dep] = dep - return paths_to_paths - - -def macho_make_paths_normal(orig_path_name, rpaths, deps, idpath): - """ - Return a dictionary mapping the relativized rpaths to the original rpaths. - This dictionary is used to replace paths in mach-o binaries. - Replace '@loader_path' with the dirname of the origname path name - in rpaths and deps; idpath is replaced with the original path name - """ - rel_to_orig = dict() - if idpath: - rel_to_orig[idpath] = orig_path_name - - for rpath in rpaths: - if re.match("@loader_path", rpath): - norm = os.path.normpath( - re.sub(re.escape("@loader_path"), os.path.dirname(orig_path_name), rpath) - ) - rel_to_orig[rpath] = norm - else: - rel_to_orig[rpath] = rpath - for dep in deps: - if re.match("@loader_path", dep): - norm = os.path.normpath( - re.sub(re.escape("@loader_path"), os.path.dirname(orig_path_name), dep) - ) - rel_to_orig[dep] = norm - else: - rel_to_orig[dep] = dep - return rel_to_orig - - -def macho_find_paths(orig_rpaths, deps, idpath, old_layout_root, prefix_to_prefix): +def macho_find_paths(orig_rpaths, deps, idpath, prefix_to_prefix): """ Inputs original rpaths from mach-o binaries @@ -207,13 +74,12 @@ def macho_find_paths(orig_rpaths, deps, idpath, old_layout_root, prefix_to_prefi # Sort from longest path to shortest, to ensure we try /foo/bar/baz before /foo/bar prefix_iteration_order = sorted(prefix_to_prefix, key=len, reverse=True) for orig_rpath in orig_rpaths: - if orig_rpath.startswith(old_layout_root): - for old_prefix in prefix_iteration_order: - new_prefix = prefix_to_prefix[old_prefix] - if orig_rpath.startswith(old_prefix): - new_rpath = re.sub(re.escape(old_prefix), new_prefix, orig_rpath) - paths_to_paths[orig_rpath] = new_rpath - break + for old_prefix in prefix_iteration_order: + new_prefix = prefix_to_prefix[old_prefix] + if orig_rpath.startswith(old_prefix): + new_rpath = re.sub(re.escape(old_prefix), new_prefix, orig_rpath) + paths_to_paths[orig_rpath] = new_rpath + break else: paths_to_paths[orig_rpath] = orig_rpath @@ -348,9 +214,7 @@ def _set_elf_rpaths_and_interpreter( return None -def relocate_macho_binaries( - path_names, old_layout_root, new_layout_root, prefix_to_prefix, rel, old_prefix, new_prefix -): +def relocate_macho_binaries(path_names, prefix_to_prefix): """ Use macholib python package to get the rpaths, depedent libraries and library identity for libraries from the MachO object. Modify them @@ -363,77 +227,15 @@ def relocate_macho_binaries( # Corner case where macho object file ended up in the path name list if path_name.endswith(".o"): continue - if rel: - # get the relativized paths - rpaths, deps, idpath = macholib_get_paths(path_name) - # get the file path name in the original prefix - orig_path_name = re.sub(re.escape(new_prefix), old_prefix, path_name) - # get the mapping of the relativized paths to the original - # normalized paths - rel_to_orig = macho_make_paths_normal(orig_path_name, rpaths, deps, idpath) - # replace the relativized paths with normalized paths - modify_macho_object(path_name, rpaths, deps, idpath, rel_to_orig) - # get the normalized paths in the mach-o binary - rpaths, deps, idpath = macholib_get_paths(path_name) - # get the mapping of paths in old prefix to path in new prefix - paths_to_paths = macho_find_paths( - rpaths, deps, idpath, old_layout_root, prefix_to_prefix - ) - # replace the old paths with new paths - modify_macho_object(path_name, rpaths, deps, idpath, paths_to_paths) - # get the new normalized path in the mach-o binary - rpaths, deps, idpath = macholib_get_paths(path_name) - # get the mapping of paths to relative paths in the new prefix - paths_to_paths = macho_make_paths_relative( - path_name, new_layout_root, rpaths, deps, idpath - ) - # replace the new paths with relativized paths in the new prefix - modify_macho_object(path_name, rpaths, deps, idpath, paths_to_paths) - else: - # get the paths in the old prefix - rpaths, deps, idpath = macholib_get_paths(path_name) - # get the mapping of paths in the old prerix to the new prefix - paths_to_paths = macho_find_paths( - rpaths, deps, idpath, old_layout_root, prefix_to_prefix - ) - # replace the old paths with new paths - modify_macho_object(path_name, rpaths, deps, idpath, paths_to_paths) - - -def _transform_rpaths(orig_rpaths, orig_root, new_prefixes): - """Return an updated list of RPATHs where each entry in the original list - starting with the old root is relocated to another place according to the - mapping passed as argument. - - Args: - orig_rpaths (list): list of the original RPATHs - orig_root (str): original root to be substituted - new_prefixes (dict): dictionary that maps the original prefixes to - where they should be relocated - - Returns: - List of paths - """ - new_rpaths = [] - for orig_rpath in orig_rpaths: - # If the original RPATH doesn't start with the target root - # append it verbatim and proceed - if not orig_rpath.startswith(orig_root): - new_rpaths.append(orig_rpath) - continue - - # Otherwise inspect the mapping and transform + append any prefix - # that starts with a registered key - # avoiding duplicates - for old_prefix, new_prefix in new_prefixes.items(): - if orig_rpath.startswith(old_prefix): - new_rpath = re.sub(re.escape(old_prefix), new_prefix, orig_rpath) - if new_rpath not in new_rpaths: - new_rpaths.append(new_rpath) - return new_rpaths + # get the paths in the old prefix + rpaths, deps, idpath = macholib_get_paths(path_name) + # get the mapping of paths in the old prerix to the new prefix + paths_to_paths = macho_find_paths(rpaths, deps, idpath, prefix_to_prefix) + # replace the old paths with new paths + modify_macho_object(path_name, rpaths, deps, idpath, paths_to_paths) -def new_relocate_elf_binaries(binaries, prefix_to_prefix): +def relocate_elf_binaries(binaries, prefix_to_prefix): """Take a list of binaries, and an ordered dictionary of prefix to prefix mapping, and update the rpaths accordingly.""" @@ -452,98 +254,6 @@ def new_relocate_elf_binaries(binaries, prefix_to_prefix): _set_elf_rpaths_and_interpreter(path, rpaths=rpaths, interpreter=interpreter) -def relocate_elf_binaries( - binaries, orig_root, new_root, new_prefixes, rel, orig_prefix, new_prefix -): - """Relocate the binaries passed as arguments by changing their RPATHs. - - Use patchelf to get the original RPATHs and then replace them with - rpaths in the new directory layout. - - New RPATHs are determined from a dictionary mapping the prefixes in the - old directory layout to the prefixes in the new directory layout if the - rpath was in the old layout root, i.e. system paths are not replaced. - - Args: - binaries (list): list of binaries that might need relocation, located - in the new prefix - orig_root (str): original root to be substituted - new_root (str): new root to be used, only relevant for relative RPATHs - new_prefixes (dict): dictionary that maps the original prefixes to - where they should be relocated - rel (bool): True if the RPATHs are relative, False if they are absolute - orig_prefix (str): prefix where the executable was originally located - new_prefix (str): prefix where we want to relocate the executable - """ - for new_binary in binaries: - orig_rpaths = _elf_rpaths_for(new_binary) - # TODO: Can we deduce `rel` from the original RPATHs? - if rel: - # Get the file path in the original prefix - orig_binary = re.sub(re.escape(new_prefix), orig_prefix, new_binary) - - # Get the normalized RPATHs in the old prefix using the file path - # in the orig prefix - orig_norm_rpaths = _normalize_relative_paths(orig_binary, orig_rpaths) - # Get the normalize RPATHs in the new prefix - new_norm_rpaths = _transform_rpaths(orig_norm_rpaths, orig_root, new_prefixes) - # Get the relative RPATHs in the new prefix - new_rpaths = _make_relative(new_binary, new_root, new_norm_rpaths) - # check to see if relative rpaths are changed before rewriting - if sorted(new_rpaths) != sorted(orig_rpaths): - _set_elf_rpaths_and_interpreter(new_binary, new_rpaths) - else: - new_rpaths = _transform_rpaths(orig_rpaths, orig_root, new_prefixes) - _set_elf_rpaths_and_interpreter(new_binary, new_rpaths) - - -def make_link_relative(new_links, orig_links): - """Compute the relative target from the original link and - make the new link relative. - - Args: - new_links (list): new links to be made relative - orig_links (list): original links - """ - for new_link, orig_link in zip(new_links, orig_links): - target = readlink(orig_link) - relative_target = os.path.relpath(target, os.path.dirname(orig_link)) - os.unlink(new_link) - symlink(relative_target, new_link) - - -def make_macho_binaries_relative(cur_path_names, orig_path_names, old_layout_root): - """ - Replace old RPATHs with paths relative to old_dir in binary files - """ - if not sys.platform == "darwin": - return - - for cur_path, orig_path in zip(cur_path_names, orig_path_names): - (rpaths, deps, idpath) = macholib_get_paths(cur_path) - paths_to_paths = macho_make_paths_relative( - orig_path, old_layout_root, rpaths, deps, idpath - ) - modify_macho_object(cur_path, rpaths, deps, idpath, paths_to_paths) - - -def make_elf_binaries_relative(new_binaries, orig_binaries, orig_layout_root): - """Replace the original RPATHs in the new binaries making them - relative to the original layout root. - - Args: - new_binaries (list): new binaries whose RPATHs is to be made relative - orig_binaries (list): original binaries - orig_layout_root (str): path to be used as a base for making - RPATHs relative - """ - for new_binary, orig_binary in zip(new_binaries, orig_binaries): - orig_rpaths = _elf_rpaths_for(new_binary) - if orig_rpaths: - new_rpaths = _make_relative(orig_binary, orig_layout_root, orig_rpaths) - _set_elf_rpaths_and_interpreter(new_binary, new_rpaths) - - def warn_if_link_cant_be_relocated(link, target): if not os.path.isabs(target): return diff --git a/lib/spack/spack/rewiring.py b/lib/spack/spack/rewiring.py index 91ae5241d93b04..f552c68f24fab7 100644 --- a/lib/spack/spack/rewiring.py +++ b/lib/spack/spack/rewiring.py @@ -77,25 +77,9 @@ def rewire_node(spec, explicit): ] if bins_to_relocate: if "macho" in platform.binary_formats: - relocate.relocate_macho_binaries( - bins_to_relocate, - str(spack.store.STORE.layout.root), - str(spack.store.STORE.layout.root), - prefix_to_prefix, - False, - spec.build_spec.prefix, - spec.prefix, - ) + relocate.relocate_macho_binaries(bins_to_relocate, prefix_to_prefix) if "elf" in platform.binary_formats: - relocate.relocate_elf_binaries( - bins_to_relocate, - str(spack.store.STORE.layout.root), - str(spack.store.STORE.layout.root), - prefix_to_prefix, - False, - spec.build_spec.prefix, - spec.prefix, - ) + relocate.relocate_elf_binaries(bins_to_relocate, prefix_to_prefix) relocate.relocate_text_bin(binaries=bins_to_relocate, prefixes=prefix_to_prefix) shutil.rmtree(tempdir) install_manifest = os.path.join( diff --git a/lib/spack/spack/test/packaging.py b/lib/spack/spack/test/packaging.py index 405845f61a6504..4b5f41ade6b37b 100644 --- a/lib/spack/spack/test/packaging.py +++ b/lib/spack/spack/test/packaging.py @@ -31,13 +31,7 @@ from spack.fetch_strategy import URLFetchStrategy from spack.installer import PackageInstaller from spack.paths import mock_gpg_keys_path -from spack.relocate import ( - macho_find_paths, - macho_make_paths_normal, - macho_make_paths_relative, - relocate_links, - relocate_text, -) +from spack.relocate import macho_find_paths, relocate_links, relocate_text from spack.spec import Spec pytestmark = pytest.mark.not_on_windows("does not run on windows") @@ -301,7 +295,6 @@ def test_replace_paths(tmpdir): os.path.join(oldlibdir_local, libfile_loco), ], os.path.join(oldlibdir_cc, libfile_c), - old_spack_dir, prefix2prefix, ) assert out_dict == { @@ -325,7 +318,6 @@ def test_replace_paths(tmpdir): os.path.join(oldlibdir_local, libfile_loco), ], None, - old_spack_dir, prefix2prefix, ) assert out_dict == { @@ -349,7 +341,6 @@ def test_replace_paths(tmpdir): f"@rpath/{libfile_loco}", ], None, - old_spack_dir, prefix2prefix, ) @@ -369,7 +360,6 @@ def test_replace_paths(tmpdir): [oldlibdir_a, oldlibdir_b, oldlibdir_d, oldlibdir_local], [f"@rpath/{libfile_a}", f"@rpath/{libfile_b}", f"@rpath/{libfile_loco}"], None, - old_spack_dir, prefix2prefix, ) assert out_dict == { @@ -383,91 +373,6 @@ def test_replace_paths(tmpdir): } -def test_macho_make_paths(): - out = macho_make_paths_relative( - "/Users/Shared/spack/pkgC/lib/libC.dylib", - "/Users/Shared/spack", - ("/Users/Shared/spack/pkgA/lib", "/Users/Shared/spack/pkgB/lib", "/usr/local/lib"), - ( - "/Users/Shared/spack/pkgA/libA.dylib", - "/Users/Shared/spack/pkgB/libB.dylib", - "/usr/local/lib/libloco.dylib", - ), - "/Users/Shared/spack/pkgC/lib/libC.dylib", - ) - assert out == { - "/Users/Shared/spack/pkgA/lib": "@loader_path/../../pkgA/lib", - "/Users/Shared/spack/pkgB/lib": "@loader_path/../../pkgB/lib", - "/usr/local/lib": "/usr/local/lib", - "/Users/Shared/spack/pkgA/libA.dylib": "@loader_path/../../pkgA/libA.dylib", - "/Users/Shared/spack/pkgB/libB.dylib": "@loader_path/../../pkgB/libB.dylib", - "/usr/local/lib/libloco.dylib": "/usr/local/lib/libloco.dylib", - "/Users/Shared/spack/pkgC/lib/libC.dylib": "@rpath/libC.dylib", - } - - out = macho_make_paths_normal( - "/Users/Shared/spack/pkgC/lib/libC.dylib", - ("@loader_path/../../pkgA/lib", "@loader_path/../../pkgB/lib", "/usr/local/lib"), - ( - "@loader_path/../../pkgA/libA.dylib", - "@loader_path/../../pkgB/libB.dylib", - "/usr/local/lib/libloco.dylib", - ), - "@rpath/libC.dylib", - ) - - assert out == { - "@rpath/libC.dylib": "/Users/Shared/spack/pkgC/lib/libC.dylib", - "@loader_path/../../pkgA/lib": "/Users/Shared/spack/pkgA/lib", - "@loader_path/../../pkgB/lib": "/Users/Shared/spack/pkgB/lib", - "/usr/local/lib": "/usr/local/lib", - "@loader_path/../../pkgA/libA.dylib": "/Users/Shared/spack/pkgA/libA.dylib", - "@loader_path/../../pkgB/libB.dylib": "/Users/Shared/spack/pkgB/libB.dylib", - "/usr/local/lib/libloco.dylib": "/usr/local/lib/libloco.dylib", - } - - out = macho_make_paths_relative( - "/Users/Shared/spack/pkgC/bin/exeC", - "/Users/Shared/spack", - ("/Users/Shared/spack/pkgA/lib", "/Users/Shared/spack/pkgB/lib", "/usr/local/lib"), - ( - "/Users/Shared/spack/pkgA/libA.dylib", - "/Users/Shared/spack/pkgB/libB.dylib", - "/usr/local/lib/libloco.dylib", - ), - None, - ) - - assert out == { - "/Users/Shared/spack/pkgA/lib": "@loader_path/../../pkgA/lib", - "/Users/Shared/spack/pkgB/lib": "@loader_path/../../pkgB/lib", - "/usr/local/lib": "/usr/local/lib", - "/Users/Shared/spack/pkgA/libA.dylib": "@loader_path/../../pkgA/libA.dylib", - "/Users/Shared/spack/pkgB/libB.dylib": "@loader_path/../../pkgB/libB.dylib", - "/usr/local/lib/libloco.dylib": "/usr/local/lib/libloco.dylib", - } - - out = macho_make_paths_normal( - "/Users/Shared/spack/pkgC/bin/exeC", - ("@loader_path/../../pkgA/lib", "@loader_path/../../pkgB/lib", "/usr/local/lib"), - ( - "@loader_path/../../pkgA/libA.dylib", - "@loader_path/../../pkgB/libB.dylib", - "/usr/local/lib/libloco.dylib", - ), - None, - ) - - assert out == { - "@loader_path/../../pkgA/lib": "/Users/Shared/spack/pkgA/lib", - "@loader_path/../../pkgB/lib": "/Users/Shared/spack/pkgB/lib", - "/usr/local/lib": "/usr/local/lib", - "@loader_path/../../pkgA/libA.dylib": "/Users/Shared/spack/pkgA/libA.dylib", - "@loader_path/../../pkgB/libB.dylib": "/Users/Shared/spack/pkgB/libB.dylib", - "/usr/local/lib/libloco.dylib": "/usr/local/lib/libloco.dylib", - } - - @pytest.fixture() def mock_download(monkeypatch): """Mock a failing download strategy.""" @@ -561,10 +466,6 @@ def test_macho_relocation_with_changing_projection(relocation_dict): """ original_rpath = "/foo/bar/baz/abcdef" result = macho_find_paths( - [original_rpath], - deps=[], - idpath=None, - old_layout_root="/foo", - prefix_to_prefix=relocation_dict, + [original_rpath], deps=[], idpath=None, prefix_to_prefix=relocation_dict ) assert result[original_rpath] == "/a/b/c/abcdef" diff --git a/lib/spack/spack/test/relocate.py b/lib/spack/spack/test/relocate.py index e88b61affe9d95..eccf30075c234b 100644 --- a/lib/spack/spack/test/relocate.py +++ b/lib/spack/spack/test/relocate.py @@ -1,8 +1,6 @@ # Copyright Spack Project Developers. See COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) -import os -import os.path import re import shutil @@ -114,49 +112,6 @@ def _copy_somewhere(orig_binary): return _copy_somewhere -@pytest.mark.parametrize( - "start_path,path_root,paths,expected", - [ - ( - "/usr/bin/test", - "/usr", - ["/usr/lib", "/usr/lib64", "/opt/local/lib"], - [ - os.path.join("$ORIGIN", "..", "lib"), - os.path.join("$ORIGIN", "..", "lib64"), - "/opt/local/lib", - ], - ) - ], -) -def test_make_relative_paths(start_path, path_root, paths, expected): - relatives = spack.relocate._make_relative(start_path, path_root, paths) - assert relatives == expected - - -@pytest.mark.parametrize( - "start_path,relative_paths,expected", - [ - # $ORIGIN will be replaced with os.path.dirname('usr/bin/test') - # and then normalized - ( - "/usr/bin/test", - ["$ORIGIN/../lib", "$ORIGIN/../lib64", "/opt/local/lib"], - [ - os.sep + os.path.join("usr", "lib"), - os.sep + os.path.join("usr", "lib64"), - "/opt/local/lib", - ], - ), - # Relative path without $ORIGIN - ("/usr/bin/test", ["../local/lib"], ["../local/lib"]), - ], -) -def test_normalize_relative_paths(start_path, relative_paths, expected): - normalized = spack.relocate._normalize_relative_paths(start_path, relative_paths) - assert normalized == expected - - @pytest.mark.requires_executables("patchelf", "gcc") @skip_unless_linux def test_relocate_text_bin(binary_with_rpaths, prefix_like): @@ -182,61 +137,13 @@ def test_relocate_elf_binaries_absolute_paths(binary_with_rpaths, copy_binary, p new_binary = copy_binary(orig_binary) spack.relocate.relocate_elf_binaries( - binaries=[str(new_binary)], - orig_root=str(orig_binary.dirpath()), - new_root=None, # Not needed when relocating absolute paths - new_prefixes={str(orig_binary.dirpath()): "/foo"}, - rel=False, - # Not needed when relocating absolute paths - orig_prefix=None, - new_prefix=None, + binaries=[str(new_binary)], prefix_to_prefix={str(orig_binary.dirpath()): "/foo"} ) # Some compilers add rpaths so ensure changes included in final result assert "/foo/lib:/usr/lib64" in rpaths_for(new_binary) -@pytest.mark.requires_executables("patchelf", "gcc") -@skip_unless_linux -def test_relocate_elf_binaries_relative_paths(binary_with_rpaths, copy_binary): - # Create an executable, set some RPATHs, copy it to another location - orig_binary = binary_with_rpaths(rpaths=["lib", "lib64", "/opt/local/lib"]) - new_binary = copy_binary(orig_binary) - - spack.relocate.relocate_elf_binaries( - binaries=[str(new_binary)], - orig_root=str(orig_binary.dirpath()), - new_root=str(new_binary.dirpath()), - new_prefixes={str(orig_binary.dirpath()): "/foo"}, - rel=True, - orig_prefix=str(orig_binary.dirpath()), - new_prefix=str(new_binary.dirpath()), - ) - - # Some compilers add rpaths so ensure changes included in final result - assert "/foo/lib:/foo/lib64:/opt/local/lib" in rpaths_for(new_binary) - - -@pytest.mark.requires_executables("patchelf", "gcc") -@skip_unless_linux -def test_make_elf_binaries_relative(binary_with_rpaths, copy_binary, prefix_tmpdir): - orig_binary = binary_with_rpaths( - rpaths=[ - str(prefix_tmpdir.mkdir("lib")), - str(prefix_tmpdir.mkdir("lib64")), - "/opt/local/lib", - ] - ) - new_binary = copy_binary(orig_binary) - - spack.relocate.make_elf_binaries_relative( - [str(new_binary)], [str(orig_binary)], str(orig_binary.dirpath()) - ) - - # Some compilers add rpaths so ensure changes included in final result - assert "$ORIGIN/lib:$ORIGIN/lib64:/opt/local/lib" in rpaths_for(new_binary) - - @pytest.mark.requires_executables("patchelf", "gcc") @skip_unless_linux def test_relocate_text_bin_with_message(binary_with_rpaths, copy_binary, prefix_tmpdir):