This fixes a bug in creating rpaths relative to $ORIGIN on linux. (#5726)
* This fixes a bug in creating rpaths relative to on linux. * fix for macOS as well * found in testing * flake8 * fix testing on macOS * flake8
This commit is contained in:
		 Patrick Gartung
					Patrick Gartung
				
			
				
					committed by
					
						 Todd Gamblin
						Todd Gamblin
					
				
			
			
				
	
			
			
			 Todd Gamblin
						Todd Gamblin
					
				
			
						parent
						
							4d3424a5d4
						
					
				
				
					commit
					2e1aa0a5e9
				
			| @@ -240,24 +240,24 @@ def build_tarball(spec, outdir, force=False, rel=False, yes_to_all=False, | |||||||
|         else: |         else: | ||||||
|             raise NoOverwriteException(str(specfile_path)) |             raise NoOverwriteException(str(specfile_path)) | ||||||
|     # make a copy of the install directory to work with |     # make a copy of the install directory to work with | ||||||
|     prefix = join_path(outdir, os.path.basename(spec.prefix)) |     workdir = join_path(outdir, os.path.basename(spec.prefix)) | ||||||
|     if os.path.exists(prefix): |     if os.path.exists(workdir): | ||||||
|         shutil.rmtree(prefix) |         shutil.rmtree(workdir) | ||||||
|     install_tree(spec.prefix, prefix) |     install_tree(spec.prefix, workdir) | ||||||
|  |  | ||||||
|     # create info for later relocation and create tar |     # create info for later relocation and create tar | ||||||
|     write_buildinfo_file(prefix) |     write_buildinfo_file(workdir) | ||||||
|  |  | ||||||
|     # optinally make the paths in the binaries relative to each other |     # optinally make the paths in the binaries relative to each other | ||||||
|     # in the spack install tree before creating tarball |     # in the spack install tree before creating tarball | ||||||
|     if rel: |     if rel: | ||||||
|         make_package_relative(prefix) |         make_package_relative(workdir, spec.prefix) | ||||||
|     # create compressed tarball of the install prefix |     # create compressed tarball of the install prefix | ||||||
|     with closing(tarfile.open(tarfile_path, 'w:gz')) as tar: |     with closing(tarfile.open(tarfile_path, 'w:gz')) as tar: | ||||||
|         tar.add(name='%s' % prefix, |         tar.add(name='%s' % workdir, | ||||||
|                 arcname='%s' % os.path.basename(prefix)) |                 arcname='%s' % os.path.basename(workdir)) | ||||||
|     # remove copy of install directory |     # remove copy of install directory | ||||||
|     shutil.rmtree(prefix) |     shutil.rmtree(workdir) | ||||||
|  |  | ||||||
|     # get the sha256 checksum of the tarball |     # get the sha256 checksum of the tarball | ||||||
|     checksum = checksum_tarball(tarfile_path) |     checksum = checksum_tarball(tarfile_path) | ||||||
| @@ -327,15 +327,16 @@ def download_tarball(spec): | |||||||
|     return None |     return None | ||||||
|  |  | ||||||
|  |  | ||||||
| def make_package_relative(prefix): | def make_package_relative(workdir, prefix): | ||||||
|     """ |     """ | ||||||
|     Change paths in binaries to relative paths |     Change paths in binaries to relative paths | ||||||
|     """ |     """ | ||||||
|     buildinfo = read_buildinfo_file(prefix) |     buildinfo = read_buildinfo_file(workdir) | ||||||
|     old_path = buildinfo['buildpath'] |     old_path = buildinfo['buildpath'] | ||||||
|     for filename in buildinfo['relocate_binaries']: |     for filename in buildinfo['relocate_binaries']: | ||||||
|         path_name = os.path.join(prefix, filename) |         orig_path_name = os.path.join(prefix, filename) | ||||||
|         relocate.make_binary_relative(path_name, old_path) |         cur_path_name = os.path.join(workdir, filename) | ||||||
|  |         relocate.make_binary_relative(cur_path_name, orig_path_name, old_path) | ||||||
|  |  | ||||||
|  |  | ||||||
| def relocate_package(prefix): | def relocate_package(prefix): | ||||||
|   | |||||||
| @@ -158,7 +158,8 @@ def macho_replace_paths(old_dir, new_dir, rpaths, deps, idpath): | |||||||
|     return nrpaths, ndeps, id |     return nrpaths, ndeps, id | ||||||
|  |  | ||||||
|  |  | ||||||
| def modify_macho_object(path_name, old_dir, new_dir, relative): | def modify_macho_object(cur_path_name, orig_path_name, old_dir, new_dir, | ||||||
|  |                         relative): | ||||||
|     """ |     """ | ||||||
|     Modify MachO binary path_name by replacing old_dir with new_dir |     Modify MachO binary path_name by replacing old_dir with new_dir | ||||||
|     or the relative path to spack install root. |     or the relative path to spack install root. | ||||||
| @@ -170,14 +171,14 @@ def modify_macho_object(path_name, old_dir, new_dir, relative): | |||||||
|     install_name_tool  -rpath old new binary |     install_name_tool  -rpath old new binary | ||||||
|     """ |     """ | ||||||
|     # avoid error message for libgcc_s |     # avoid error message for libgcc_s | ||||||
|     if 'libgcc_' in path_name: |     if 'libgcc_' in cur_path_name: | ||||||
|         return |         return | ||||||
|     rpaths, deps, idpath = macho_get_paths(path_name) |     rpaths, deps, idpath = macho_get_paths(cur_path_name) | ||||||
|     id = None |     id = None | ||||||
|     nrpaths = [] |     nrpaths = [] | ||||||
|     ndeps = [] |     ndeps = [] | ||||||
|     if relative: |     if relative: | ||||||
|         nrpaths, ndeps, id = macho_make_paths_relative(path_name, |         nrpaths, ndeps, id = macho_make_paths_relative(orig_path_name, | ||||||
|                                                        old_dir, rpaths, |                                                        old_dir, rpaths, | ||||||
|                                                        deps, idpath) |                                                        deps, idpath) | ||||||
|     else: |     else: | ||||||
| @@ -185,13 +186,13 @@ def modify_macho_object(path_name, old_dir, new_dir, relative): | |||||||
|                                                  deps, idpath) |                                                  deps, idpath) | ||||||
|     install_name_tool = Executable('install_name_tool') |     install_name_tool = Executable('install_name_tool') | ||||||
|     if id: |     if id: | ||||||
|         install_name_tool('-id', id, path_name, output=str, err=str) |         install_name_tool('-id', id, cur_path_name, output=str, err=str) | ||||||
|  |  | ||||||
|     for orig, new in zip(deps, ndeps): |     for orig, new in zip(deps, ndeps): | ||||||
|         install_name_tool('-change', orig, new, path_name) |         install_name_tool('-change', orig, new, cur_path_name) | ||||||
|  |  | ||||||
|     for orig, new in zip(rpaths, nrpaths): |     for orig, new in zip(rpaths, nrpaths): | ||||||
|         install_name_tool('-rpath', orig, new, path_name) |         install_name_tool('-rpath', orig, new, cur_path_name) | ||||||
|     return |     return | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -256,17 +257,18 @@ def relocate_binary(path_name, old_dir, new_dir): | |||||||
|         tty.die("Relocation not implemented for %s" % platform.system()) |         tty.die("Relocation not implemented for %s" % platform.system()) | ||||||
|  |  | ||||||
|  |  | ||||||
| def make_binary_relative(path_name, old_dir): | def make_binary_relative(cur_path_name, orig_path_name, old_dir): | ||||||
|     """ |     """ | ||||||
|     Make RPATHs relative to old_dir in given elf or mach-o file path_name |     Make RPATHs relative to old_dir in given elf or mach-o file path_name | ||||||
|     """ |     """ | ||||||
|     if platform.system() == 'Darwin': |     if platform.system() == 'Darwin': | ||||||
|         new_dir = '' |         new_dir = '' | ||||||
|         modify_macho_object(path_name, old_dir, new_dir, relative=True) |         modify_macho_object(cur_path_name, orig_path_name, old_dir, new_dir, | ||||||
|  |                             relative=True) | ||||||
|     elif platform.system() == 'Linux': |     elif platform.system() == 'Linux': | ||||||
|         orig_rpaths = get_existing_elf_rpaths(path_name) |         orig_rpaths = get_existing_elf_rpaths(cur_path_name) | ||||||
|         new_rpaths = get_relative_rpaths(path_name, old_dir, orig_rpaths) |         new_rpaths = get_relative_rpaths(orig_path_name, old_dir, orig_rpaths) | ||||||
|         modify_elf_object(path_name, orig_rpaths, new_rpaths) |         modify_elf_object(cur_path_name, orig_rpaths, new_rpaths) | ||||||
|     else: |     else: | ||||||
|         tty.die("Prelocation not implemented for %s" % platform.system()) |         tty.die("Prelocation not implemented for %s" % platform.system()) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -291,11 +291,13 @@ def test_relocate_macho(): | |||||||
|     assert (needs_binary_relocation('Mach-O') is True) |     assert (needs_binary_relocation('Mach-O') is True) | ||||||
|     macho_get_paths('/bin/bash') |     macho_get_paths('/bin/bash') | ||||||
|     shutil.copyfile('/bin/bash', 'bash') |     shutil.copyfile('/bin/bash', 'bash') | ||||||
|     modify_macho_object('bash', '/usr', '/opt', False) |     modify_macho_object('bash', '/bin/bash', '/usr', '/opt', False) | ||||||
|     modify_macho_object('bash', '/usr', '/opt', True) |     modify_macho_object('bash', '/bin/bash', '/usr', '/opt', True) | ||||||
|     shutil.copyfile('/usr/lib/libncurses.5.4.dylib', 'libncurses.5.4.dylib') |     shutil.copyfile('/usr/lib/libncurses.5.4.dylib', 'libncurses.5.4.dylib') | ||||||
|     modify_macho_object('libncurses.5.4.dylib', '/usr', '/opt', False) |     modify_macho_object('libncurses.5.4.dylib', | ||||||
|     modify_macho_object('libncurses.5.4.dylib', '/usr', '/opt', True) |                         '/usr/lib/libncurses.5.4.dylib', '/usr', '/opt', False) | ||||||
|  |     modify_macho_object('libncurses.5.4.dylib', | ||||||
|  |                         '/usr/lib/libncurses.5.4.dylib', '/usr', '/opt', True) | ||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.mark.skipif(sys.platform != 'linux2', | @pytest.mark.skipif(sys.platform != 'linux2', | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user