From 64c1ac82dc7fb3661ba56ad6081102d597909c61 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Mon, 6 Feb 2017 16:30:01 +0800 Subject: [PATCH 1/4] Fix for bootstrapping on NixOS NixOS puts Linux's dynamic loader in wierd place. Detect when we're on NixOS and patch the downloaded bootstrap executables appropriately. --- src/bootstrap/bootstrap.py | 57 +++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 27255b6910093..c5e00a5818522 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -89,7 +89,6 @@ def verify(path, sha_path, verbose): " expected: {}".format(found, expected)) return verified - def unpack(tarball, dst, verbose=False, match=None): print("extracting " + tarball) fname = os.path.basename(tarball).replace(".tar.gz", "") @@ -173,6 +172,8 @@ def download_stage0(self): if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="rustc", verbose=self.verbose) + self.fix_executable(self.bin_root() + "/bin/rustc") + self.fix_executable(self.bin_root() + "/bin/rustdoc") with open(self.rustc_stamp(), 'w') as f: f.write(self.stage0_rustc_date()) @@ -185,9 +186,63 @@ def download_stage0(self): if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose) + self.fix_executable(self.bin_root() + "/bin/cargo") with open(self.cargo_stamp(), 'w') as f: f.write(self.stage0_cargo_rev()) + def fix_executable(self, fname): + # If we're on NixOS we need to change the path to the dynamic loader + + default_encoding = sys.getdefaultencoding() + try: + ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding) + except (subprocess.CalledProcessError, WindowsError): + return + + if ostype != "Linux": + return + + if not os.path.exists("/nix/store"): + return + if os.path.exists("/lib"): + return + + # At this point we're pretty sure the user is running NixOS + print("Info: you seem to be running NixOS. Attempting to patch " + fname) + + try: + interpreter = subprocess.check_output(["patchelf", "--print-interpreter", fname]) + interpreter = interpreter.strip().decode(default_encoding) + except subprocess.CalledProcessError as e: + print("Warning: failed to call patchelf: %s" % e) + 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 e: + print("Warning: unable to call ldd: %s" % e) + 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 + + try: + subprocess.check_output(["patchelf", "--set-interpreter", correct_interpreter, fname]) + except subprocess.CalledProcessError as e: + print("Warning: failed to call patchelf: %s" % e) + return + def stage0_cargo_rev(self): return self._cargo_rev From 6e2631a014f4dc4df3d863cc8ddf1efe64635068 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 11 Feb 2017 13:01:37 +0800 Subject: [PATCH 2/4] Change test for being on NixOS --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c5e00a5818522..0ac4de2b8bf3a 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -202,7 +202,7 @@ def fix_executable(self, fname): if ostype != "Linux": return - if not os.path.exists("/nix/store"): + if not os.path.exists("/etc/nixos"): return if os.path.exists("/lib"): return From e0a5b9d746cb7083a849773dc84f9e0a8e1e5621 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 11 Feb 2017 16:17:54 +0800 Subject: [PATCH 3/4] Change test for being on nixos again --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 0ac4de2b8bf3a..6ba3994c485e5 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -202,7 +202,7 @@ def fix_executable(self, fname): if ostype != "Linux": return - if not os.path.exists("/etc/nixos"): + if not os.path.exists("/etc/NIXOS"): return if os.path.exists("/lib"): return From 5e324bdc91415ae222becf362f68ffdebf3ec804 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Fri, 17 Feb 2017 14:00:58 +0800 Subject: [PATCH 4/4] Style fixups --- src/bootstrap/bootstrap.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 6ba3994c485e5..d21e5719ea2b1 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -89,6 +89,7 @@ def verify(path, sha_path, verbose): " expected: {}".format(found, expected)) return verified + def unpack(tarball, dst, verbose=False, match=None): print("extracting " + tarball) fname = os.path.basename(tarball).replace(".tar.gz", "") @@ -208,13 +209,13 @@ def fix_executable(self, fname): return # At this point we're pretty sure the user is running NixOS - print("Info: you seem to be running NixOS. Attempting to patch " + fname) + print("info: you seem to be running NixOS. Attempting to patch " + fname) try: interpreter = subprocess.check_output(["patchelf", "--print-interpreter", fname]) interpreter = interpreter.strip().decode(default_encoding) except subprocess.CalledProcessError as e: - print("Warning: failed to call patchelf: %s" % e) + print("warning: failed to call patchelf: %s" % e) return loader = interpreter.split("/")[-1] @@ -223,7 +224,7 @@ def fix_executable(self, fname): ldd_output = subprocess.check_output(['ldd', '/run/current-system/sw/bin/sh']) ldd_output = ldd_output.strip().decode(default_encoding) except subprocess.CalledProcessError as e: - print("Warning: unable to call ldd: %s" % e) + print("warning: unable to call ldd: %s" % e) return for line in ldd_output.splitlines(): @@ -232,7 +233,7 @@ def fix_executable(self, fname): loader_path = libname[:len(libname) - len(loader)] break else: - print("Warning: unable to find the path to the dynamic linker") + print("warning: unable to find the path to the dynamic linker") return correct_interpreter = loader_path + loader @@ -240,7 +241,7 @@ def fix_executable(self, fname): try: subprocess.check_output(["patchelf", "--set-interpreter", correct_interpreter, fname]) except subprocess.CalledProcessError as e: - print("Warning: failed to call patchelf: %s" % e) + print("warning: failed to call patchelf: %s" % e) return def stage0_cargo_rev(self):