binary caching: handle files misidentified as needing relocation (#6679)
* Only specify a file as needing relocation if it contains the spack root as a text string (this constraint also applies to binaries) * Don't fail if there is an error retrieving RPATH information from a binary (even if it is specified as requiring relocation)
This commit is contained in:
parent
28d8784ab9
commit
e5d6f28b4e
3 changed files with 54 additions and 25 deletions
|
@ -111,13 +111,17 @@ def write_buildinfo_file(prefix, workdir, rel=False):
|
||||||
dirs[:] = [d for d in dirs if d not in blacklist]
|
dirs[:] = [d for d in dirs if d not in blacklist]
|
||||||
for filename in files:
|
for filename in files:
|
||||||
path_name = os.path.join(root, filename)
|
path_name = os.path.join(root, filename)
|
||||||
filetype = relocate.get_filetype(path_name)
|
# Check if the file contains a string with the installroot.
|
||||||
if relocate.needs_binary_relocation(filetype, os_id):
|
# This cuts down on the number of files added to the list
|
||||||
rel_path_name = os.path.relpath(path_name, prefix)
|
# of files potentially needing relocation
|
||||||
binary_to_relocate.append(rel_path_name)
|
if relocate.strings_contains_installroot(path_name):
|
||||||
elif relocate.needs_text_relocation(filetype):
|
filetype = relocate.get_filetype(path_name)
|
||||||
rel_path_name = os.path.relpath(path_name, prefix)
|
if relocate.needs_binary_relocation(filetype, os_id):
|
||||||
text_to_relocate.append(rel_path_name)
|
rel_path_name = os.path.relpath(path_name, prefix)
|
||||||
|
binary_to_relocate.append(rel_path_name)
|
||||||
|
elif relocate.needs_text_relocation(filetype):
|
||||||
|
rel_path_name = os.path.relpath(path_name, prefix)
|
||||||
|
text_to_relocate.append(rel_path_name)
|
||||||
|
|
||||||
# Create buildinfo data and write it to disk
|
# Create buildinfo data and write it to disk
|
||||||
buildinfo = {}
|
buildinfo = {}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
import re
|
import re
|
||||||
import spack
|
import spack
|
||||||
import spack.cmd
|
import spack.cmd
|
||||||
from spack.util.executable import Executable
|
from spack.util.executable import Executable, ProcessError
|
||||||
from llnl.util.filesystem import filter_file
|
from llnl.util.filesystem import filter_file
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
|
@ -56,10 +56,15 @@ def get_existing_elf_rpaths(path_name):
|
||||||
as a list of strings.
|
as a list of strings.
|
||||||
"""
|
"""
|
||||||
if platform.system() == 'Linux':
|
if platform.system() == 'Linux':
|
||||||
command = Executable(get_patchelf())
|
patchelf = Executable(get_patchelf())
|
||||||
output = command('--print-rpath', '%s' %
|
try:
|
||||||
path_name, output=str, err=str)
|
output = patchelf('--print-rpath', '%s' %
|
||||||
return output.rstrip('\n').split(':')
|
path_name, output=str, error=str)
|
||||||
|
return output.rstrip('\n').split(':')
|
||||||
|
except ProcessError as e:
|
||||||
|
tty.debug('patchelf --print-rpath produced an error on %s' %
|
||||||
|
path_name, e)
|
||||||
|
return []
|
||||||
else:
|
else:
|
||||||
tty.die('relocation not supported for this platform')
|
tty.die('relocation not supported for this platform')
|
||||||
return
|
return
|
||||||
|
@ -193,19 +198,34 @@ def get_filetype(path_name):
|
||||||
file = Executable('file')
|
file = Executable('file')
|
||||||
file.add_default_env('LC_ALL', 'C')
|
file.add_default_env('LC_ALL', 'C')
|
||||||
output = file('-b', '-h', '%s' % path_name,
|
output = file('-b', '-h', '%s' % path_name,
|
||||||
output=str, err=str)
|
output=str, error=str)
|
||||||
return output.strip()
|
return output.strip()
|
||||||
|
|
||||||
|
|
||||||
def modify_elf_object(path_name, orig_rpath, new_rpath):
|
def strings_contains_installroot(path_name):
|
||||||
|
"""
|
||||||
|
Check if the file contain the install root string.
|
||||||
|
"""
|
||||||
|
strings = Executable('strings')
|
||||||
|
output = strings('%s' % path_name,
|
||||||
|
output=str, err=str)
|
||||||
|
return (spack.store.layout.root in output)
|
||||||
|
|
||||||
|
|
||||||
|
def modify_elf_object(path_name, new_rpaths):
|
||||||
"""
|
"""
|
||||||
Replace orig_rpath with new_rpath in RPATH of elf object path_name
|
Replace orig_rpath with new_rpath in RPATH of elf object path_name
|
||||||
"""
|
"""
|
||||||
if platform.system() == 'Linux':
|
if platform.system() == 'Linux':
|
||||||
new_joined = ':'.join(new_rpath)
|
new_joined = ':'.join(new_rpaths)
|
||||||
patchelf = Executable(get_patchelf())
|
patchelf = Executable(get_patchelf())
|
||||||
patchelf('--force-rpath', '--set-rpath', '%s' % new_joined,
|
try:
|
||||||
'%s' % path_name, output=str, cmd=str)
|
patchelf('--force-rpath', '--set-rpath', '%s' % new_joined,
|
||||||
|
'%s' % path_name, output=str, error=str)
|
||||||
|
except ProcessError as e:
|
||||||
|
tty.die('patchelf --set-rpath %s failed' %
|
||||||
|
path_name, e)
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
tty.die('relocation not supported for this platform')
|
tty.die('relocation not supported for this platform')
|
||||||
|
|
||||||
|
@ -255,8 +275,9 @@ def relocate_binary(path_names, old_dir, new_dir):
|
||||||
elif platform.system() == 'Linux':
|
elif platform.system() == 'Linux':
|
||||||
for path_name in path_names:
|
for path_name in path_names:
|
||||||
orig_rpaths = get_existing_elf_rpaths(path_name)
|
orig_rpaths = get_existing_elf_rpaths(path_name)
|
||||||
new_rpaths = substitute_rpath(orig_rpaths, old_dir, new_dir)
|
if orig_rpaths:
|
||||||
modify_elf_object(path_name, orig_rpaths, new_rpaths)
|
new_rpaths = substitute_rpath(orig_rpaths, old_dir, new_dir)
|
||||||
|
modify_elf_object(path_name, new_rpaths)
|
||||||
else:
|
else:
|
||||||
tty.die("Relocation not implemented for %s" % platform.system())
|
tty.die("Relocation not implemented for %s" % platform.system())
|
||||||
|
|
||||||
|
@ -278,9 +299,10 @@ def make_binary_relative(cur_path_names, orig_path_names, old_dir):
|
||||||
elif platform.system() == 'Linux':
|
elif platform.system() == 'Linux':
|
||||||
for cur_path, orig_path in zip(cur_path_names, orig_path_names):
|
for cur_path, orig_path in zip(cur_path_names, orig_path_names):
|
||||||
orig_rpaths = get_existing_elf_rpaths(cur_path)
|
orig_rpaths = get_existing_elf_rpaths(cur_path)
|
||||||
new_rpaths = get_relative_rpaths(orig_path, old_dir,
|
if orig_rpaths:
|
||||||
orig_rpaths)
|
new_rpaths = get_relative_rpaths(orig_path, old_dir,
|
||||||
modify_elf_object(cur_path, orig_rpaths, new_rpaths)
|
orig_rpaths)
|
||||||
|
modify_elf_object(cur_path, new_rpaths)
|
||||||
else:
|
else:
|
||||||
tty.die("Prelocation not implemented for %s" % platform.system())
|
tty.die("Prelocation not implemented for %s" % platform.system())
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
from spack.fetch_strategy import URLFetchStrategy, FetchStrategyComposite
|
from spack.fetch_strategy import URLFetchStrategy, FetchStrategyComposite
|
||||||
from spack.util.executable import ProcessError
|
from spack.util.executable import ProcessError
|
||||||
from spack.relocate import needs_binary_relocation, needs_text_relocation
|
from spack.relocate import needs_binary_relocation, needs_text_relocation
|
||||||
|
from spack.relocate import strings_contains_installroot
|
||||||
from spack.relocate import get_patchelf, relocate_text
|
from spack.relocate import get_patchelf, relocate_text
|
||||||
from spack.relocate import substitute_rpath, get_relative_rpaths
|
from spack.relocate import substitute_rpath, get_relative_rpaths
|
||||||
from spack.relocate import macho_replace_paths, macho_make_paths_relative
|
from spack.relocate import macho_replace_paths, macho_make_paths_relative
|
||||||
|
@ -217,10 +218,10 @@ def test_packaging(mock_archive, tmpdir):
|
||||||
stage.destroy()
|
stage.destroy()
|
||||||
|
|
||||||
|
|
||||||
def test_relocate_text():
|
def test_relocate_text(tmpdir):
|
||||||
# Validate the text path replacement
|
# Validate the text path replacement
|
||||||
old_dir = '/home/spack/opt/spack'
|
old_dir = '/home/spack/opt/spack'
|
||||||
filename = 'dummy.txt'
|
filename = str(tmpdir) + '/dummy.txt'
|
||||||
with open(filename, "w") as script:
|
with open(filename, "w") as script:
|
||||||
script.write(old_dir)
|
script.write(old_dir)
|
||||||
script.close()
|
script.close()
|
||||||
|
@ -229,7 +230,9 @@ def test_relocate_text():
|
||||||
new_dir = '/opt/rh/devtoolset/'
|
new_dir = '/opt/rh/devtoolset/'
|
||||||
relocate_text(filenames, old_dir, new_dir)
|
relocate_text(filenames, old_dir, new_dir)
|
||||||
|
|
||||||
with open(filename, "r")as script:
|
assert(strings_contains_installroot(filename) is False)
|
||||||
|
|
||||||
|
with open(filename, "r") as script:
|
||||||
for line in script:
|
for line in script:
|
||||||
assert(new_dir in line)
|
assert(new_dir in line)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue