From e7512bcb7b784d96388bbc333769479ca657b372 Mon Sep 17 00:00:00 2001 From: iarspider Date: Mon, 24 Oct 2022 23:32:46 +0200 Subject: Add filename to text_to_relocate only if it needs to be relocated (#31074) Scan the text files for relocatable prefixes *before* creating a tarball, to reduce the amount of work to be done during install from binary cache. Co-authored-by: Harmen Stoppels --- lib/spack/spack/binary_distribution.py | 24 +++++++++++++++++-- lib/spack/spack/relocate.py | 15 ++++++++---- lib/spack/spack/test/bindist.py | 13 ++++++++++- lib/spack/spack/test/relocate.py | 10 ++++++++ .../packages/needs-text-relocation/package.py | 27 ++++++++++++++++++++++ 5 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 var/spack/repos/builtin.mock/packages/needs-text-relocation/package.py diff --git a/lib/spack/spack/binary_distribution.py b/lib/spack/spack/binary_distribution.py index 7ae91dd6bf..3f74d91a9e 100644 --- a/lib/spack/spack/binary_distribution.py +++ b/lib/spack/spack/binary_distribution.py @@ -42,6 +42,7 @@ import spack.util.spack_yaml as syaml import spack.util.url as url_util import spack.util.web as web_util from spack.caches import misc_cache_location +from spack.relocate import utf8_path_to_binary_regex from spack.spec import Spec from spack.stage import Stage @@ -687,6 +688,15 @@ class BuildManifestVisitor(BaseDirectoryVisitor): return False +def file_matches_any_binary_regex(path, regexes): + with open(path, "rb") as f: + contents = f.read() + for regex in regexes: + if regex.search(contents): + return True + return False + + def get_buildfile_manifest(spec): """ Return a data structure with information about a build, including @@ -712,6 +722,15 @@ def get_buildfile_manifest(spec): root = spec.prefix visit_directory_tree(root, visitor) + # Collect a list of prefixes for this package and it's dependencies, Spack will + # look for them to decide if text file needs to be relocated or not + prefixes = [d.prefix for d in spec.traverse(root=True, deptype="all") if not d.external] + prefixes.append(spack.hooks.sbang.sbang_install_path()) + prefixes.append(str(spack.store.layout.root)) + + # Create a list regexes matching collected prefixes + compiled_prefixes = [utf8_path_to_binary_regex(prefix) for prefix in prefixes] + # Symlinks. # Obvious bugs: @@ -743,8 +762,9 @@ def get_buildfile_manifest(spec): continue elif relocate.needs_text_relocation(m_type, m_subtype): - data["text_to_relocate"].append(rel_path) - continue + if file_matches_any_binary_regex(abs_path, compiled_prefixes): + data["text_to_relocate"].append(rel_path) + continue data["other"].append(abs_path) diff --git a/lib/spack/spack/relocate.py b/lib/spack/spack/relocate.py index 3297965b6e..667e8de4e0 100644 --- a/lib/spack/spack/relocate.py +++ b/lib/spack/spack/relocate.py @@ -744,6 +744,14 @@ def relocate_links(links, orig_layout_root, orig_install_prefix, new_install_pre tty.warn(msg.format(link_target, abs_link, new_install_prefix)) +def utf8_path_to_binary_regex(prefix): + """Create a (binary) regex that matches the input path in utf8""" + prefix_bytes = re.escape(prefix).encode("utf-8") + prefix_rexp = re.compile(b"(?