Skip to content

Fix for bootstrapping on NixOS #39578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 17, 2017
Merged

Conversation

canndrew
Copy link
Contributor

@canndrew canndrew commented Feb 6, 2017

NixOS puts Linux's dynamic loader in wierd place. Detect when we're on NixOS and patch the downloaded bootstrap executables appropriately.

NixOS puts Linux's dynamic loader in wierd place. Detect when we're on NixOS
and patch the downloaded bootstrap executables appropriately.
@rust-highfive
Copy link
Contributor

r? @aturon

(rust_highfive has picked a reviewer for you, use r? to override)

Copy link
Contributor

@xen0n xen0n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM from a Python programmer's perspective, although I can't test this. Take care of the portability and this should be good to merge!


default_encoding = sys.getdefaultencoding()
try:
ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use platform.system() instead (with appropriate import added to the top). uname is not present on Windows and this gets executed before we know the OS type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was aware of platform.system() but I copied what was done here because I figured there must be a reason for it. This shouldn't break on windows because the fix_executable function just returns without doing anything if something goes wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, yeah. Didn't see that WindowsError right below. Although IMO the uname calls are only there for consistency with the configure logic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this deduplicate between here and the other location?

@@ -89,7 +89,6 @@ def verify(path, sha_path, verbose):
" expected: {}".format(found, expected))
return verified


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style cleanup is best done in a separate commit.

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW we're using all-lowercase messages in rustbuild, and this Info should be lower-cased too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(agreed)

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So should this Warning and some others below.

@aturon
Copy link
Member

aturon commented Feb 6, 2017

r? @brson

@rust-highfive rust-highfive assigned brson and unassigned aturon Feb 6, 2017
@alexcrichton
Copy link
Member

@canndrew could you describe why this is necessary, and why we should do it as part of the build system? This seems like a lot of brittle logic easily broken for something that I'd naively consider to be a local problem, but I'm sure I'm not aware of all the details!

@brson
Copy link
Contributor

brson commented Feb 6, 2017

I think this is a reasonable workaround, but it's a little weird - if you happen to be running on nix, it changes what it does to the outputs. In other words, one still can't build for NixOS generally, but if you happen to be building on Nix you get a Nix-compatible binary.

@canndrew
Copy link
Contributor Author

canndrew commented Feb 8, 2017

@alexcrichton
The stage0 linux rust binaries that the build system downloads are hard-coded to look for the dynamic loader at /lib/ld-linux-$arch.so.2. NixOS is different to other linuxes and keeps its dynamic loader(s) under /nix/store, but it comes with a tool called patchelf for patching precompiled binaries to use a different dynamic loader path. The brittle logic shouldn't be a problem because the fix_executable function will just return without doing anything if it fails.

@brson
Yeah, this isn't really the most correct way to do this on NixOS. Ideally you'd write a Nix derivation which takes the dynamic loader as an input so it can find the path to patch. Just using the dynamic loader for sh is very much a hack. However I want to just be able to cd into a rust directory and build it without screwing around with the nix tools. This will let me do that. And it shouldn't interfere with any derivations people have written if it patches the path immediately after downloading the binary - the derivation can always just patch it again with another path.

@alexcrichton
Copy link
Member

Thanks for the explanation @canndrew!

@canndrew
Copy link
Contributor Author

canndrew commented Feb 9, 2017

It might be a good idea to see what other NixOS users think of this. Maybe @Ericson2314 has an opinion? I'm not sure who else uses NixOS.

@Ericson2314
Copy link
Contributor

Granted, I'm a little out of date on this stuff as I mainly just patch the pre-compiled binaries, and then that stopped working great because the Cargo ones moved. But I thought at least the official nixpkgs rustc package downloads the bootstrap binaries on rustbuild's behalf?

In any event, I think this stuff can go away once the cargo integration with out build systems + distributed cache stuff is figured out, and stdlib-aware Cargo is implemented. Then we can build rustc like any other binary very nicely. So hopefully this would be a temporary thing for less than the year 🤞.

if ostype != "Linux":
return

if not os.path.exists("/nix/store"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any NixOS system has /etc/NIXOS (nixos-rebuild / the activation scripts check for its existence and refuse to run without it), so that's probably a better test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Thanks.

Copy link

@8573 8573 Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@edef1c's recommendation was for /etc/NIXOS, and I believe one could have a NixOS installation without /etc/nixos.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I was wondering why he wrote it in uppercase. I didn't realize that file existed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the record, s/he/they/

@nagisa
Copy link
Member

nagisa commented Feb 11, 2017

Instead of patching the rustc binary itself, change bootstrap logic to invoke rustc with ld.so bin/rustc. This can be done inside the rustc wrapper (at src/bootstrap/bin/rustc) for least churn (and similar wrapper could be made for cargo as well).

@xen0n
Copy link
Contributor

xen0n commented Feb 12, 2017

@nagisa If this is implemented we'd want to change rustup as well, as one can rustup toolchain link the stage0 for whatever reason and expect things to work. Personally I just feel it's adding inconsistency as the places that end up being touched for the ld.so invocations are more than if only the binaries are patched and everything goes as usual.

@canndrew
Copy link
Contributor Author

@nagisa What's the advantage of doing it like that? From my point of view, the precompiled rustc binaries are just broken for NixOS - they point to a file that doesn't exist. So why not just fix the problem directly?

@solson
Copy link
Member

solson commented Feb 16, 2017

This is also the standard way to fix binaries on NixOS.

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Collaborator

bors commented Feb 17, 2017

📌 Commit 5e324bd has been approved by alexcrichton

@bors
Copy link
Collaborator

bors commented Feb 17, 2017

⌛ Testing commit 5e324bd with merge 536a900...

bors added a commit that referenced this pull request Feb 17, 2017
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.
@bors
Copy link
Collaborator

bors commented Feb 17, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: alexcrichton
Pushing 536a900 to master...

@bors bors merged commit 5e324bd into rust-lang:master Feb 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.