diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-07-17 15:35:14 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-07-17 15:35:49 +0300 |
| commit | d866160b85107551c339c35995db4b35c0364264 (patch) | |
| tree | 6711a3a2045fd213f1e230f048d68c75f4eee256 | |
| parent | c2dbebd3d4ad21e80ef4e7535dd1e868aaad7e50 (diff) | |
| download | rust-d866160b85107551c339c35995db4b35c0364264.tar.gz rust-d866160b85107551c339c35995db4b35c0364264.zip | |
bootstrap.py: guard against GC in NixOS patching support.
| -rw-r--r-- | src/bootstrap/bootstrap.py | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 1dfa635c694..bdf3bdf80b6 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -349,6 +349,7 @@ class RustBuild(object): self.use_vendored_sources = '' self.verbose = False self.git_version = None + self.nix_deps_dir = None def download_stage0(self): """Fetch the build system for Rust, written in Rust @@ -440,8 +441,7 @@ class RustBuild(object): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose) - @staticmethod - def fix_executable(fname): + def fix_executable(self, fname): """Modifies the interpreter section of 'fname' to fix the dynamic linker This method is only required on NixOS and uses the PatchELF utility to @@ -472,38 +472,49 @@ class RustBuild(object): nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" print(nix_os_msg, fname) - try: - interpreter = subprocess.check_output( - ["patchelf", "--print-interpreter", fname]) - interpreter = interpreter.strip().decode(default_encoding) - except subprocess.CalledProcessError as reason: - print("warning: failed to call patchelf:", reason) - return - - loader = interpreter.split("/")[-1] - - try: - ldd_output = subprocess.check_output( - ['ldd', '/run/current-system/sw/bin/sh']) - ldd_output = ldd_output.strip().decode(default_encoding) - except subprocess.CalledProcessError as reason: - print("warning: unable to call ldd:", reason) - return - - for line in ldd_output.splitlines(): - libname = line.split()[0] - if libname.endswith(loader): - loader_path = libname[:len(libname) - len(loader)] - break - else: - print("warning: unable to find the path to the dynamic linker") - return - - correct_interpreter = loader_path + loader + # Only build `stage0/.nix-deps` once. + nix_deps_dir = self.nix_deps_dir + if not nix_deps_dir: + nix_deps_dir = "{}/.nix-deps".format(self.bin_root()) + if not os.path.exists(nix_deps_dir): + os.makedirs(nix_deps_dir) + + nix_deps = [ + # Needed for the path of `ld-linux.so` (via `nix-support/dynamic-linker`). + "stdenv.cc.bintools", + + # Needed for patching ELF binaries (see doc comment above). + "patchelf", + ] + + # Run `nix-build` to "build" each dependency (which will likely reuse + # the existing `/nix/store` copy, or at most download a pre-built copy). + # Importantly, we don't rely on `nix-build` printing the `/nix/store` + # path on stdout, but use `-o` to symlink it into `stage0/.nix-deps/$dep`, + # ensuring garbage collection will never remove the `/nix/store` path + # (which would break our patched binaries that hardcode those paths). + for dep in nix_deps: + try: + subprocess.check_output([ + "nix-build", "<nixpkgs>", + "-A", dep, + "-o", "{}/{}".format(nix_deps_dir, dep), + ]) + except subprocess.CalledProcessError as reason: + print("warning: failed to call nix-build:", reason) + return + + 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() try: subprocess.check_output( - ["patchelf", "--set-interpreter", correct_interpreter, fname]) + [patchelf, "--set-interpreter", interpreter, fname]) except subprocess.CalledProcessError as reason: print("warning: failed to call patchelf:", reason) return |
