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:
		 Patrick Gartung
					Patrick Gartung
				
			
				
					committed by
					
						 scheibelp
						scheibelp
					
				
			
			
				
	
			
			
			 scheibelp
						scheibelp
					
				
			
						parent
						
							28d8784ab9
						
					
				
				
					commit
					e5d6f28b4e
				
			| @@ -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) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user