Skip to content

Commit

Permalink
bootstrap.py: patch RPATH on NixOS to handle the new zlib dependency.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jul 17, 2020
1 parent d866160 commit b5076fb
Showing 1 changed file with 30 additions and 13 deletions.
43 changes: 30 additions & 13 deletions src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,12 @@ def support_xz():
filename = "rustc-{}-{}{}".format(rustc_channel, self.build,
tarball_suffix)
self._download_stage0_helper(filename, "rustc", tarball_suffix)
self.fix_executable("{}/bin/rustc".format(self.bin_root()))
self.fix_executable("{}/bin/rustdoc".format(self.bin_root()))
self.fix_bin_or_dylib("{}/bin/rustc".format(self.bin_root()))
self.fix_bin_or_dylib("{}/bin/rustdoc".format(self.bin_root()))
lib_dir = "{}/lib".format(self.bin_root())
for lib in os.listdir(lib_dir):
if lib.endswith(".so"):
self.fix_bin_or_dylib("{}/{}".format(lib_dir, lib))
with output(self.rustc_stamp()) as rust_stamp:
rust_stamp.write(self.date)

Expand All @@ -409,7 +413,7 @@ def support_xz():
filename = "cargo-{}-{}{}".format(cargo_channel, self.build,
tarball_suffix)
self._download_stage0_helper(filename, "cargo", tarball_suffix)
self.fix_executable("{}/bin/cargo".format(self.bin_root()))
self.fix_bin_or_dylib("{}/bin/cargo".format(self.bin_root()))
with output(self.cargo_stamp()) as cargo_stamp:
cargo_stamp.write(self.date)

Expand All @@ -422,8 +426,8 @@ def support_xz():
[channel, date] = rustfmt_channel.split('-', 1)
filename = "rustfmt-{}-{}{}".format(channel, self.build, tarball_suffix)
self._download_stage0_helper(filename, "rustfmt-preview", tarball_suffix, date)
self.fix_executable("{}/bin/rustfmt".format(self.bin_root()))
self.fix_executable("{}/bin/cargo-fmt".format(self.bin_root()))
self.fix_bin_or_dylib("{}/bin/rustfmt".format(self.bin_root()))
self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(self.bin_root()))
with output(self.rustfmt_stamp()) as rustfmt_stamp:
rustfmt_stamp.write(self.date + self.rustfmt_channel)

Expand All @@ -441,11 +445,12 @@ def _download_stage0_helper(self, filename, pattern, tarball_suffix, date=None):
get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose)

def fix_executable(self, fname):
"""Modifies the interpreter section of 'fname' to fix the dynamic linker
def fix_bin_or_dylib(self, fname):
"""Modifies the interpreter section of 'fname' to fix the dynamic linker,
or the RPATH section, to fix the dynamic library search path
This method is only required on NixOS and uses the PatchELF utility to
change the dynamic linker of ELF executables.
change the interpreter/RPATH of ELF executables.
Please see https://nixos.org/patchelf.html for more information
"""
Expand Down Expand Up @@ -483,6 +488,9 @@ def fix_executable(self, fname):
# Needed for the path of `ld-linux.so` (via `nix-support/dynamic-linker`).
"stdenv.cc.bintools",

# Needed as a system dependency of `libLLVM-*.so`.
"zlib",

# Needed for patching ELF binaries (see doc comment above).
"patchelf",
]
Expand All @@ -507,14 +515,23 @@ def fix_executable(self, fname):
self.nix_deps_dir = nix_deps_dir

patchelf = "{}/patchelf/bin/patchelf".format(nix_deps_dir)
bintools_dir = "{}/stdenv.cc.bintools".format(nix_deps_dir)

with open("{}/nix-support/dynamic-linker".format(bintools_dir)) as dynamic_linker:
interpreter = dynamic_linker.read().rstrip()
if fname.endswith(".so"):
# Dynamic library, patch RPATH to point to system dependencies.
dylib_deps = ["zlib"]
rpath_entries = [
# Relative default, all binary and dynamic libraries we ship
# appear to have this (even when `../lib` is redundant).
"$ORIGIN/../lib",
] + ["{}/{}/lib".format(nix_deps_dir, dep) for dep in dylib_deps]
patchelf_args = ["--set-rpath", ":".join(rpath_entries)]
else:
bintools_dir = "{}/stdenv.cc.bintools".format(nix_deps_dir)
with open("{}/nix-support/dynamic-linker".format(bintools_dir)) as dynamic_linker:
patchelf_args = ["--set-interpreter", dynamic_linker.read().rstrip()]

try:
subprocess.check_output(
[patchelf, "--set-interpreter", interpreter, fname])
subprocess.check_output([patchelf] + patchelf_args + [fname])
except subprocess.CalledProcessError as reason:
print("warning: failed to call patchelf:", reason)
return
Expand Down

0 comments on commit b5076fb

Please sign in to comment.