Skip to content
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

bootstrap.py: patch RPATH on NixOS to handle the new zlib dependency. #74441

Merged
merged 2 commits into from
Jul 18, 2020

Conversation

eddyb
Copy link
Member

@eddyb eddyb commented Jul 17, 2020

This is a stop-gap until #74420 is resolved (assuming we'll patch beta to statically link zlib).

However, I've been meaning to rewrite the NixOS support we have in bootstrap.py for a while now, and had to in order to cleanly add zlib as a dependency (the second commit is a relatively small delta in functionality, compared to the first).

Previously, we would extract the ld-linux.so path from the output of ldd /run/current-system/sw/bin/sh, which assumes a lot. On top of that we didn't use any symlinks, which meant if the user ran GC (nix-collect-garbage), e.g. after updating their system, their stage0 binaries would suddenly be broken (i.e. referring to files that no longer exist).
We were also using patchelf directly, assuming it can be found in $PATH (which is not necessarily true).

My new approach relies on using nix-build to get the following "derivations" (packages, more or less):

This is closer to how software is built on Nix, but I've tried to keep it as simple as possible (and not add e.g. a stage0.nix file).
Symlinks to each of those dependencies are kept in stage0/.nix-deps, which prevents GC from invalidating stage0 binaries.

r? @nagisa cc @Mark-Simulacrum @oli-obk @davidtwco

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 17, 2020
try:
subprocess.check_output([
"nix-build", "<nixpkgs>",
"-A", dep,
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to try and build all of the deps with a single command?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure how to do that and keep the symlinks.

Copy link
Member

Choose a reason for hiding this comment

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

The symlinks won’t be named as well as they are right now, but:

$ nix-build '<nixpkgs>' -A zlib -A stdenv.cc.bintools -o foo/.nixdeps
$ ls -alh foo/
total 0
drwxr-xr-x  2 nagisa users  80 Jul 17 17:43 .
drwxrwxrwt 21 root   root  560 Jul 17 17:43 ..
lrwxrwxrwx  1 nagisa users  55 Jul 17 17:43 .nixdeps -> /nix/store/ml4ipdnvc7pr07dr6i35831f7ffxny0k-zlib-1.2.11
lrwxrwxrwx  1 nagisa users  67 Jul 17 17:43 .nixdeps-2 -> /nix/store/wy6v1s2y8rvxcy98l2yvxqj280cq9wgc-binutils-wrapper-2.31.1

if fname.endswith(".so"):
# Dynamic library, patch RPATH to point to system dependencies.
dylib_deps = ["zlib"]
rpath_entries = [
Copy link
Member

Choose a reason for hiding this comment

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

Hm… shouldn't we just append the rpath?

Copy link
Member Author

Choose a reason for hiding this comment

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

That would require a command to read it, which... I can do it if you want, it's just uglier (and I've gotten used to hardcoding the $ORIGIN/../lib part in my patchelf commands).

Copy link
Member

Choose a reason for hiding this comment

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

yeah, it is just not clear to me that $ORIGIN/../lib is sufficient and that there aren’t libraries/binaries that implicitly gain other rpath entries as part of their compilation process. I’m fine with it if it is, I guess.

Copy link
Member Author

Choose a reason for hiding this comment

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

For the record, NixOS rustup also hardcodes $ORIGIN/../lib:, so I think we're fine.

@nagisa
Copy link
Member

nagisa commented Jul 17, 2020

@bors r+ with or without comments addressed.

@bors
Copy link
Contributor

bors commented Jul 17, 2020

📌 Commit b5076fb has been approved by nagisa

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 17, 2020
Manishearth added a commit to Manishearth/rust that referenced this pull request Jul 18, 2020
bootstrap.py: patch RPATH on NixOS to handle the new zlib dependency.

This is a stop-gap until rust-lang#74420 is resolved (assuming we'll patch beta to statically link zlib).

However, I've been meaning to rewrite the NixOS support we have in `bootstrap.py` for a while now, and had to in order to cleanly add zlib as a dependency (the second commit is a relatively small delta in functionality, compared to the first).

Previously, we would extract the `ld-linux.so` path from the output of `ldd /run/current-system/sw/bin/sh`, which assumes a lot. On top of that we didn't use any symlinks, which meant if the user ran  GC (`nix-collect-garbage`), e.g. after updating their system, their `stage0` binaries would suddenly be broken (i.e. referring to files that no longer exist).
We were also using `patchelf` directly, assuming it can be found in `$PATH` (which is not necessarily true).

My new approach relies on using `nix-build` to get the following "derivations" (packages, more or less):
* `stdenv.cc.bintools`, which has a `nix-support/dynamic-linker` file containing the path to `ld-linux.so`
  * reading this file is [the canonical way to run `patchelf --set-interpreter`](https://github.com/NixOS/nixpkgs/search?l=Nix&q=%22--set-interpreter+%24%28cat+%24NIX_CC%2Fnix-support%2Fdynamic-linker%29%22)
* `patchelf` (so that the user doesn't need to have it installed)
* `zlib`, for the `libz.so` dependency of `libLLVM-*.so` (until rust-lang#74420 is resolved, presumably)

This is closer to how software is built on Nix, but I've tried to keep it as simple as possible (and not add e.g. a `stage0.nix` file).
Symlinks to each of those dependencies are kept in `stage0/.nix-deps`, which prevents GC from invalidating `stage0` binaries.

r? @nagisa cc @Mark-Simulacrum @oli-obk @davidtwco
Manishearth added a commit to Manishearth/rust that referenced this pull request Jul 18, 2020
bootstrap.py: patch RPATH on NixOS to handle the new zlib dependency.

This is a stop-gap until rust-lang#74420 is resolved (assuming we'll patch beta to statically link zlib).

However, I've been meaning to rewrite the NixOS support we have in `bootstrap.py` for a while now, and had to in order to cleanly add zlib as a dependency (the second commit is a relatively small delta in functionality, compared to the first).

Previously, we would extract the `ld-linux.so` path from the output of `ldd /run/current-system/sw/bin/sh`, which assumes a lot. On top of that we didn't use any symlinks, which meant if the user ran  GC (`nix-collect-garbage`), e.g. after updating their system, their `stage0` binaries would suddenly be broken (i.e. referring to files that no longer exist).
We were also using `patchelf` directly, assuming it can be found in `$PATH` (which is not necessarily true).

My new approach relies on using `nix-build` to get the following "derivations" (packages, more or less):
* `stdenv.cc.bintools`, which has a `nix-support/dynamic-linker` file containing the path to `ld-linux.so`
  * reading this file is [the canonical way to run `patchelf --set-interpreter`](https://github.com/NixOS/nixpkgs/search?l=Nix&q=%22--set-interpreter+%24%28cat+%24NIX_CC%2Fnix-support%2Fdynamic-linker%29%22)
* `patchelf` (so that the user doesn't need to have it installed)
* `zlib`, for the `libz.so` dependency of `libLLVM-*.so` (until rust-lang#74420 is resolved, presumably)

This is closer to how software is built on Nix, but I've tried to keep it as simple as possible (and not add e.g. a `stage0.nix` file).
Symlinks to each of those dependencies are kept in `stage0/.nix-deps`, which prevents GC from invalidating `stage0` binaries.

r? @nagisa cc @Mark-Simulacrum @oli-obk @davidtwco
bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 18, 2020
…arth

Rollup of 11 pull requests

Successful merges:

 - rust-lang#72414 ( Add lazy initialization primitives to std)
 - rust-lang#74069 (Compare tagged/niche-filling layout and pick the best one)
 - rust-lang#74418 (ci: Set `shell: bash` as a default, remove duplicates)
 - rust-lang#74441 (bootstrap.py: patch RPATH on NixOS to handle the new zlib dependency.)
 - rust-lang#74444 (Add regression test for rust-lang#69414)
 - rust-lang#74448 (improper_ctypes_definitions: allow `Box`)
 - rust-lang#74449 (Test codegen of compare_exchange operations)
 - rust-lang#74450 (Fix `Safety` docs for `from_raw_parts_mut`)
 - rust-lang#74453 (Use intra-doc links in `str` and `BTreeSet`)
 - rust-lang#74457 (rustbuild: drop tool::should_install)
 - rust-lang#74464 (Use pathdiff crate)

Failed merges:

r? @ghost
@bors bors merged commit 8d1bb0e into rust-lang:master Jul 18, 2020
@eddyb eddyb deleted the zlib-on-nixos branch July 18, 2020 16:09
@cuviper cuviper added this to the 1.47.0 milestone May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants