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

Change build-std to use --sysroot #7421

Merged
merged 8 commits into from
Sep 25, 2019
Merged

Conversation

ehuss
Copy link
Contributor

@ehuss ehuss commented Sep 24, 2019

This transitions build-std to use --sysroot instead of --extern. This is necessary because existing crates have a certain expectation of how standard library crates are exposed. It was intended that explicit dependencies in Cargo.toml would solve this problem, but I didn't really consider this would be a backwards-incompatible change, so using --sysroot is probably the best way to go, even though it's not ideal.

Closes rust-lang/wg-cargo-std-aware#31
Closes rust-lang/wg-cargo-std-aware#40

ehuss and others added 3 commits September 23, 2019 18:53
* Minimize the sysroot crates in play
* Don't use build scripts to inject args
* Use `RUSTC_WRAPPER` to dynamically switch `--sysroot` depending on
  whether we're building sysroot crates or not.
* Minimize dependency graph in sysroot, only have each crate depend on a
  dummy crates.io crate for testing and otherwise don't depend on
  anything to load the desired sysroot crate directly.
@rust-highfive
Copy link

r? @alexcrichton

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 24, 2019
@ehuss
Copy link
Contributor Author

ehuss commented Sep 24, 2019

Thanks for working on the tests, Alex! That was the hardest part.

A few notes about this PR:

  • This line uses the wrong sysroot (it uses the one from rustc). Should I just skip that line if build-std is enabled? I don't 100% understand the purpose of it in the first place (is it only for building rustc?). target_dylib_path also doesn't handle .json targets correctly.
    • EDIT: The only test that relies on it is cross_test_dylib. Since build-std doesn't have dylibs, maybe it should be skipped?
  • Build-plan is not really supported properly. It doesn't include the steps for copying the artifacts to the sysroot. Maybe it should just include those paths in the links list? It's kinda hard to do since it isn't using the built-in artifact uplifting mechanism. I'm not really sure about the future of build-plan in general.
  • This uses link_or_copy, but I think there may be a race condition in the "copy" case. Copies are used on filesystems that don't support hardlinks (like some network filesystems). My concern is for rmeta/rlib pipelining. It will copy over the rmeta file, then pipelining will launch a new rustc. However, I'm concerned that the rlib file may be copied over while the new rustc is running. There is a tiny window where it may have an partially filled rlib, and I'm not sure how rustc will handle that.
  • This does not handle CRT files or bundled binaries like lld. I'd like to punt on that and figure out what to do later.

@alexcrichton
Copy link
Member

Since build-std doesn't have dylibs, maybe it should be skipped?

Agreed, should be fine to skip that line for -Zbuild-std

Build-plan is not really supported properly.

Good point! I think we should probably just give a first class error very early on saying that you can't combine -Zbuild-std and -Zbuild-plan

There is a tiny window where it may have an partially filled rlib, and I'm not sure how rustc will handle that.

This is already somewhat true for pipelining I think because although we pass --extern to specifically just the *.rmeta rustc still scans the directory for other rlibs and may read half-written rlibs. In general though rustc has had this problem quite a few times in the past, and at this point it's pretty resilient to errors which is to say it ignores all of them and only actually reports an error if it for sure can't make progress.

This does not handle CRT files or bundled binaries like lld.

Agreed. Let's open an issue in wg-std-aware-cargo after this lands?

// Compute the sysroot path for the build-std feature.
let build_std = ws.config().cli_unstable().build_std.as_ref();
let (sysroot, sysroot_libdir) = if let Some(tp) = build_std.and(triple_path) {
let sysroot = dest.join(".sysroot");
Copy link
Member

Choose a reason for hiding this comment

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

I'd have a mild preference for not hiding this directory by default, but I'm curious why you added the leading period?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue is that named profiles will be taking over this namespace (each named profile has a directory with its name). I'd like to avoid potential conflicts. An alternative would be to reserve "sysroot" and not allow it as a profile name (which won't be much of an option once named profiles stabilizes). Or we could come up with some other structure or naming convention. Any preferences?

Copy link
Member

Choose a reason for hiding this comment

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

Ah ok sounds good to me! Can you add that to a comment indicating why there's a leading dot?

if unit.is_std && unit.kind == super::Kind::Target && !cx.bcx.build_config.build_plan {
let rmeta = artifact == Artifact::Metadata;
standard_lib::add_sysroot_artifact(cx, unit, rmeta)?;
}
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 be possible to sink this work into the unit itself? Ideally we wouldn't be doing much extra stuff here in job_queue.rs and it keeps all the major work on each thread cargo spawns for work.

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'm not sure how that would work, particularly with pipelining. The rmeta json artifact notification goes through a generic route that most conveniently ends up here in JobQueue. I could disable pipelining and move it to the Work closure instead?

Copy link
Member

Choose a reason for hiding this comment

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

Ah I see what you mean. Thinking more on this though, I was actually assuming that we'd just change --out-dir for is_std crates. It looks like otherwise they're gonna show up both in the libdir as well as the main deps folder, right? If we switched --out-dir I think it'd solve this issue naturally?

Copy link
Member

Choose a reason for hiding this comment

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

Er wait no we already talked about it and ruled it out because we want to clean out the sysroot on each build.

In any case this poses an interesting scenario where the dependencies of std can be loaded from either the sysroot or -Ldependency=.../deps, they're actually all the same. I'm asking this from the point of view of concurrency which I think this issue is trying to solve (making sure we do this before the next compilation starts), but maybe that's not actually necessary?

Ok I want to try to work this through here in a coment...

  • So for std->std dependencies, as well as non-std->non-std dependencies, those all use --extern I believe. If that's the case then I think that nothing is necessary here in terms of sequencing things right because everything is loaded from deps
  • The only case I think this cares about is non-std -> std dependencies, since they're loaded through the sysroot. Specifically you're worried here that we will kick off compilations that depend on core, but nothing may actually be in the sysroot yet, so the compiler won't be able to find anything.

Does that sound right? If so...

So presumably this would otherwise go somewhere around here (transitively), and you're right that's a "pretty generic path" which isn't a great spot to put it.

Ok if you agree with what I've said above, let's leave this here, but add a comment perhaps saying that we may want to figure out how to offload it to worker threads eventually?

Copy link
Contributor Author

@ehuss ehuss Sep 24, 2019

Choose a reason for hiding this comment

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

That would be cleaner. For some reason I was thinking that was going to be harder (since the output directory is somewhat global), but it probably won't be too hard. I'll give it a shot.

EDIT: Oh, and I think I was also concerned about not atomically adding files while concurrent rustc's are running, but you mentioned that it shouldn't be too much of a problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we want to clean out the sysroot on each build

Oh, yea, that's the actual reason. Sorry, I'm mis-remembering things.

Ok if you agree with what I've said above, let's leave this here, but add a comment perhaps saying that we may want to figure out how to offload it to worker threads eventually?

That makes sense. I'll add a comment.

I was previously trying to think of a way that OutputFile::hard_link (or something like it) could be used, but it still runs into the problem with rmeta files needing to be available, and linking isn't done until after compilation finishes.

let build_std = ws.config().cli_unstable().build_std.as_ref();
let (sysroot, sysroot_libdir) = if let Some(tp) = build_std.and(triple_path) {
let sysroot = dest.join(".sysroot");
let sysroot_libdir = sysroot.join("lib").join("rustlib").join(tp).join("lib");
Copy link
Member

Choose a reason for hiding this comment

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

So technically this isn't going to work on all compilers digging in a bit. The sysroot finding function in rustc takes into account CFG_LIBDIR_RELATIVE which is set by taking the difference between --libdir and --prefix when building rustc itself.

Now that's pretty esoteric though and only really relevant for Linux distributions, but it may be worth keeping in mind that this may run afoul of that at some point.

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'll try to investigate. There doesn't seem to be a way to discover the actual path.

let is_sysroot_crate = args.iter()
.any(|a| a.starts_with("rustc_std_workspace") || crates.iter().any(|b| a == b));

if is_sysroot_crate {
Copy link
Member

Choose a reason for hiding this comment

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

This can actually be simplified now I think to testing for RUSTC_BOOTSTRAP perhaps? (maybe with some extra checks for --target being passed as well)

@ehuss
Copy link
Contributor Author

ehuss commented Sep 24, 2019

I think we should probably just give a first class error very early on saying that you can't combine -Zbuild-std and -Zbuild-plan

I decided to just add a warning. I sometimes use it for testing, and I don't think anyone's going to use them together anytime soon.

Let's open an issue in wg-std-aware-cargo after this lands?

Yea, I'm planning to open a few issues after this is done.

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Sep 25, 2019

📌 Commit 9d86d86 has been approved by alexcrichton

@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 Sep 25, 2019
@bors
Copy link
Contributor

bors commented Sep 25, 2019

⌛ Testing commit 9d86d86 with merge c59e1f4...

bors added a commit that referenced this pull request Sep 25, 2019
Change build-std to use --sysroot

This transitions build-std to use `--sysroot` instead of `--extern`. This is necessary because existing crates have a certain expectation of how standard library crates are exposed. It was intended that explicit dependencies in `Cargo.toml` would solve this problem, but I didn't really consider this would be a backwards-incompatible change, so using `--sysroot` is probably the best way to go, even though it's not ideal.

Closes rust-lang/wg-cargo-std-aware#31
Closes rust-lang/wg-cargo-std-aware#40
@bors
Copy link
Contributor

bors commented Sep 25, 2019

☀️ Test successful - checks-azure
Approved by: alexcrichton
Pushing c59e1f4 to master...

@bors bors merged commit 9d86d86 into rust-lang:master Sep 25, 2019
alexcrichton added a commit to alexcrichton/rust that referenced this pull request Sep 25, 2019
4 commits in aa6b7e01abce30091cc594cb23a15c46cead6e24..ab6fa8908c9b6c8f7e2249231c395eebfbc49891
2019-09-24 17:19:12 +0000 to 2019-09-25 17:00:56 +0000
- Fix macOS collection of CPU data (rust-lang/cargo#7429)
- Don't ever capture CPU state if timings are disabled (rust-lang/cargo#7428)
- Change build-std to use --sysroot (rust-lang/cargo#7421)
- set -Zmtime_on_use from config or ENV (rust-lang/cargo#7411)
bors added a commit to rust-lang/rust that referenced this pull request Sep 25, 2019
Update cargo

4 commits in aa6b7e01abce30091cc594cb23a15c46cead6e24..ab6fa8908c9b6c8f7e2249231c395eebfbc49891
2019-09-24 17:19:12 +0000 to 2019-09-25 17:00:56 +0000
- Fix macOS collection of CPU data (rust-lang/cargo#7429)
- Don't ever capture CPU state if timings are disabled (rust-lang/cargo#7428)
- Change build-std to use --sysroot (rust-lang/cargo#7421)
- set -Zmtime_on_use from config or ENV (rust-lang/cargo#7411)
@Ericson2314
Copy link
Contributor

Ericson2314 commented Sep 26, 2019

Do we have a ticket tracking not doing this?

bors added a commit that referenced this pull request Dec 12, 2019
Switch build-std to use --extern

Switch `build-std` to use `--extern` flags instead of `--sysroot`.

This is mostly a revert of #7421. It uses the new extern flag options introduced in rust-lang/rust#67074. It avoids modifying the extern prelude which was the source of the problem of rust-lang/wg-cargo-std-aware#40.

Closes rust-lang/wg-cargo-std-aware#49
Reopens rust-lang/wg-cargo-std-aware#31
@ehuss ehuss added this to the 1.40.0 milestone Feb 6, 2022
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.

Possibly add a way to disable sysroot on rustc Using --extern is apparently not equivalent to --sysroot
5 participants