gcc: simplify specs file, make binutils locatable (#43861)
This commit is contained in:
parent
d946c37cbb
commit
2e8600bb71
1 changed files with 24 additions and 59 deletions
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
import spack.platforms
|
import spack.platforms
|
||||||
import spack.util.executable
|
import spack.util.executable
|
||||||
from spack.build_environment import dso_suffix
|
|
||||||
from spack.operating_systems.mac_os import macos_sdk_path, macos_version
|
from spack.operating_systems.mac_os import macos_sdk_path, macos_version
|
||||||
from spack.package import *
|
from spack.package import *
|
||||||
|
|
||||||
|
@ -957,76 +956,42 @@ def install_targets(self):
|
||||||
@property
|
@property
|
||||||
def spec_dir(self):
|
def spec_dir(self):
|
||||||
# e.g. lib/gcc/x86_64-unknown-linux-gnu/4.9.2
|
# e.g. lib/gcc/x86_64-unknown-linux-gnu/4.9.2
|
||||||
spec_dir = glob.glob("{0}/gcc/*/*".format(self.prefix.lib))
|
spec_dir = glob.glob(f"{self.prefix.lib}/gcc/*/*")
|
||||||
return spec_dir[0] if spec_dir else None
|
return spec_dir[0] if spec_dir else None
|
||||||
|
|
||||||
@run_after("install")
|
@run_after("install")
|
||||||
def write_rpath_specs(self):
|
def write_specs_file(self):
|
||||||
"""Generate a spec file so the linker adds a rpath to the libs
|
"""(1) inject an rpath to its runtime library dir, (2) add a default programs search path
|
||||||
the compiler used to build the executable.
|
to <binutils>/bin."""
|
||||||
|
|
||||||
.. 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:
|
if not self.spec_dir:
|
||||||
tty.warn(
|
tty.warn(f"Could not install specs for {self.spec.format('{name}{@version}')}.")
|
||||||
"Could not install specs for {0}.".format(self.spec.format("{name}{@version}"))
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
gcc = self.spec["gcc"].command
|
|
||||||
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
|
# Find which directories have shared libraries
|
||||||
rpath_libdirs = []
|
for dir in ["lib64", "lib"]:
|
||||||
for dir in ["lib", "lib64"]:
|
|
||||||
libdir = join_path(self.prefix, dir)
|
libdir = join_path(self.prefix, dir)
|
||||||
if glob.glob(join_path(libdir, "*." + dso_suffix)):
|
if glob.glob(join_path(libdir, "libgcc_s.*")):
|
||||||
rpath_libdirs.append(libdir)
|
rpath_dir = libdir
|
||||||
|
break
|
||||||
if not rpath_libdirs:
|
else:
|
||||||
# No shared libraries
|
|
||||||
tty.warn("No dynamic libraries found in lib/lib64")
|
tty.warn("No dynamic libraries found in lib/lib64")
|
||||||
return
|
rpath_dir = None
|
||||||
|
|
||||||
# Overwrite the specs file
|
specs_file = join_path(self.spec_dir, "specs")
|
||||||
with open(specs_file, "w") as out:
|
with open(specs_file, "w") as f:
|
||||||
for line in lines:
|
# rpath
|
||||||
out.write(line)
|
if rpath_dir:
|
||||||
if line.startswith("*link_libgcc:"):
|
print("*link_libgcc:", file=f)
|
||||||
# Insert at start of line following link_libgcc, which gets
|
print(f"+ -rpath={rpath_dir}", file=f)
|
||||||
# inserted into every call to the linker
|
print(file=f)
|
||||||
out.write("%(link_libgcc_rpath) ")
|
|
||||||
|
|
||||||
# Add easily-overridable rpath string at the end
|
# programs search path
|
||||||
out.write("*link_libgcc_rpath:\n")
|
if self.spec.satisfies("+binutils"):
|
||||||
out.write(" ".join("-rpath " + lib for lib in rpath_libdirs))
|
print("*self_spec:", file=f)
|
||||||
out.write("\n")
|
print(f"+ -B{self.spec['binutils'].prefix.bin}", file=f)
|
||||||
|
print(file=f)
|
||||||
set_install_permissions(specs_file)
|
set_install_permissions(specs_file)
|
||||||
tty.info("Wrote new spec file to {0}".format(specs_file))
|
tty.info(f"Wrote new spec file to {specs_file}")
|
||||||
|
|
||||||
def setup_run_environment(self, env):
|
def setup_run_environment(self, env):
|
||||||
# Search prefix directory for possibly modified compiler names
|
# Search prefix directory for possibly modified compiler names
|
||||||
|
|
Loading…
Reference in a new issue