Skip to content

Commit

Permalink
Auto merge of #39578 - canndrew:nixos-bootstrap-fix, r=alexcrichton
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Feb 17, 2017
2 parents dc0bb3f + 5e324bd commit 536a900
Showing 1 changed file with 56 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,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())

Expand All @@ -185,9 +187,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("/etc/NIXOS"):
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

Expand Down

0 comments on commit 536a900

Please sign in to comment.