diff options
author | Seth R. Johnson <johnsonsr@ornl.gov> | 2021-10-24 13:46:52 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-24 13:46:52 -0400 |
commit | c255e91bbadb58381428c301eb85383b80fbeddf (patch) | |
tree | 3e3c5a2f19c7048aa70ef0bdf0881a242cf73754 /var | |
parent | 5a3816567469f6c256173640ab278dbd7994cc33 (diff) | |
download | spack-c255e91bbadb58381428c301eb85383b80fbeddf.tar.gz spack-c255e91bbadb58381428c301eb85383b80fbeddf.tar.bz2 spack-c255e91bbadb58381428c301eb85383b80fbeddf.tar.xz spack-c255e91bbadb58381428c301eb85383b80fbeddf.zip |
gcc: support alternate mechanism for providing GCC rpaths (#26590)
* gcc: support runtime ability to not install spack rpaths
Fixes #26582 .
* gcc: Fix malformed specs file and add docs
The updated docs point out that the spack-modified GCC does *not*
follow the usual behavior of LD_RUN_PATH!
* gcc: fix bad rpath on macOS
This bug has been around since the beginning of the GCC package file:
the rpath command it generates for macOS writes a single (invalid)
rpath entry.
* gcc: only write rpaths for directories with shared libraries
The original lib64+lib was just a hack for "in case either has one" but
it's easy to tell whether either has libraries that can be directly
referenced.
Diffstat (limited to 'var')
-rw-r--r-- | var/spack/repos/builtin/packages/gcc/package.py | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/var/spack/repos/builtin/packages/gcc/package.py b/var/spack/repos/builtin/packages/gcc/package.py index 83836cbf79..5520fb0f71 100644 --- a/var/spack/repos/builtin/packages/gcc/package.py +++ b/var/spack/repos/builtin/packages/gcc/package.py @@ -12,6 +12,7 @@ import llnl.util.tty as tty import spack.platforms import spack.util.executable +from spack.build_environment import dso_suffix from spack.operating_systems.mac_os import macos_sdk_path, macos_version @@ -647,22 +648,74 @@ class Gcc(AutotoolsPackage, GNUMirrorPackage): @run_after('install') def write_rpath_specs(self): """Generate a spec file so the linker adds a rpath to the libs - the compiler used to build the executable.""" + the compiler used to build the executable. + + .. caution:: + + The custom spec file by default with *always* pass ``-Wl,-rpath + ...`` to the linker, which will cause the linker to *ignore* the + value of ``LD_RUN_PATH``, which otherwise would be saved to the + binary as the default rpath. See the mitigation below for how to + temporarily disable this behavior. + + Structure the specs file so that users can define a custom spec file + to suppress the spack-linked rpaths to facilitate rpath adjustment + for relocatable binaries. The custom spec file + :file:`{norpath}.spec` will have a single + line followed by two blanks lines:: + + *link_libgcc_rpath: + + + + It can be passed to the GCC linker using the argument + ``--specs=norpath.spec`` to disable the automatic rpath and restore + the behavior of ``LD_RUN_PATH``.""" if not self.spec_dir: tty.warn('Could not install specs for {0}.'.format( self.spec.format('{name}{@version}'))) return gcc = self.spec['gcc'].command - lines = gcc('-dumpspecs', output=str).strip().split('\n') + lines = gcc('-dumpspecs', output=str).splitlines(True) specs_file = join_path(self.spec_dir, 'specs') + + # Save a backup + with open(specs_file + '.orig', 'w') as out: + out.writelines(lines) + + # Find which directories have shared libraries + rpath_libdirs = [] + for dir in ['lib', 'lib64']: + libdir = join_path(self.prefix, dir) + if glob.glob(join_path(libdir, "*." + dso_suffix)): + rpath_libdirs.append(libdir) + + if not rpath_libdirs: + # No shared libraries + tty.warn('No dynamic libraries found in lib/lib64') + return + + # Overwrite the specs file with open(specs_file, 'w') as out: for line in lines: - out.write(line + '\n') - if line.startswith('*link:'): - out.write('-rpath {0}:{1} '.format( - self.prefix.lib, self.prefix.lib64)) + out.write(line) + if line.startswith('*link_libgcc:'): + # Insert at start of line following link_libgcc, which gets + # inserted into every call to the linker + out.write('%(link_libgcc_rpath) ') + + # Add easily-overridable rpath string at the end + out.write('*link_libgcc_rpath:\n') + if 'platform=darwin' in self.spec: + # macOS linker requires separate rpath commands + out.write(' '.join('-rpath ' + lib for lib in rpath_libdirs)) + else: + # linux linker uses colon-separated rpath + out.write('-rpath ' + ':'.join(rpath_libdirs)) + out.write('\n') set_install_permissions(specs_file) + tty.info('Wrote new spec file to {0}'.format(specs_file)) def setup_run_environment(self, env): # Search prefix directory for possibly modified compiler names |