summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth R. Johnson <johnsonsr@ornl.gov>2021-10-24 13:46:52 -0400
committerGitHub <noreply@github.com>2021-10-24 13:46:52 -0400
commitc255e91bbadb58381428c301eb85383b80fbeddf (patch)
tree3e3c5a2f19c7048aa70ef0bdf0881a242cf73754
parent5a3816567469f6c256173640ab278dbd7994cc33 (diff)
downloadspack-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.
-rw-r--r--var/spack/repos/builtin/packages/gcc/package.py65
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