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

x.py's naming of stages is confusing #59864

Open
nnethercote opened this issue Apr 11, 2019 · 28 comments
Open

x.py's naming of stages is confusing #59864

nnethercote opened this issue Apr 11, 2019 · 28 comments
Labels
A-contributor-roadblock Area: Makes things more difficult for new contributors to rust itself C-discussion Category: Discussion or questions that doesn't represent real issues. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap)

Comments

@nnethercote
Copy link
Contributor

nnethercote commented Apr 11, 2019

Rust has the standard multi-stage structure that all bootstrapping compilers have.

A newcomer who knows about compiler stages will be confident with this, until they run a command like ./x.py build --stage 1 and get output like this:

Building stage0 std artifacts 
    ...
Copying stage0 std from stage0
Building stage0 test artifacts 
    ...
Copying stage0 test from stage0
Building stage0 compiler artifacts 
    ...
Copying stage0 rustc from stage0
Building stage0 codegen artifacts 
    ...
Assembling stage1 compiler 
Building stage1 std artifacts 
    ...
Copying stage1 std from stage1
Building stage1 test artifacts 
    ...
Copying stage1 test from stage1
Building stage1 compiler artifacts 
    ...
Copying stage1 rustc from stage1
Building stage1 codegen artifacts 
    ...
Building rustdoc for stage1 
    ...

For a newcomer, this is completely bizarre.

  • Why is it building stage 0? Isn't stage 0 the compiler you download?
  • How does it assemble the stage 1 compiler before building the stage 1 artifacts?
  • Why is it building two stages? Shouldn't it only build one stage?

The key to understanding this is that x.py uses a surprising naming convention:

  • A "stage N artifact" is an artifact that is produced by the stage N compiler.
  • The "stage (N+1) compiler" is assembled from "stage N artifacts".
  • A --stage N flag means build with stage N.

Somebody had to explain this to me when I started working on Rust. I have since had to explain it to multiple newcomers. Even though I understand it now, I still find it very confusing, and I have to think carefully about it all.

Here's a naming convention that makes more sense to me:

  • A "stage N artifact" is an artifact that is produced by the stage (N-1) compiler.
  • The "stage N compiler" is assembled from "stage N artifacts".
  • A --stage N flag means build stage N, using stage (N-1).

That way, a command like ./x.py build --stage 1 would produce output like this:

Building stage1 std artifacts 
    ...
Copying stage1 std from stage1
Building stage1 test artifacts 
    ...
Copying stage1 test from stage1
Building stage1 compiler artifacts 
    ...
Copying stage1 rustc from stage1
Building stage1 codegen artifacts 
    ...
Assembling stage1 compiler 

Is there any appetite for this change? I realize it would be invasive and people would have to update their aliases, build scripts, etc. But it might be worthwhile to avoid the ongoing confusion to both newcomers and experienced contributors. Deprecating the word "stage" in favour of "phase" could help with the transition.

@jonas-schievink jonas-schievink added A-build T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) labels Apr 11, 2019
@steveklabnik
Copy link
Member

steveklabnik commented Apr 11, 2019 via email

@ehuss
Copy link
Contributor

ehuss commented Apr 11, 2019

I think this is essentially #57963. I agree it is confusing (I even drew a little picture to help me understand it).

@cuviper
Copy link
Member

cuviper commented Apr 11, 2019

@ehuss that diagram is excellent!

@cuviper
Copy link
Member

cuviper commented Apr 11, 2019

cc @Mark-Simulacrum @alexcrichton -- related to the discussion we had at all-hands.

@Mark-Simulacrum
Copy link
Member

My plan is to put in sometime this weekend to figure out and propose PRs for the changes discussed at the all hands (which should, to an extent, remove this issue by making dealing with --stage largely unnecessary). We may separately want to land a patch that changes stage "naming" though.

@Manishearth
Copy link
Member

I basically have to re-figure this out any time I'm doing anything complex with rustc, and yeah, we should change the naming here.

A key issue here is that the rust compiler is actually a thin wrapper around underlying libraries, which are shipped with rust like the stdlib is. So which stage is which differs based on whether you care about the stdlib or the compiler. Kind of. I've complained about this before and generally seen agreement that this needs fixing but not as many good solutions

@spastorino
Copy link
Member

@nnethercote I think your explanation and @ehuss diagram are perfect for rustc-guides 😄. I also would like to see this change happen, meanwhile can we document this on Rustc? are you comfortable if your explanation and diagrams are reused for rustc-guides?.
@igaray was interested in getting started with rustc-guides documentation maybe it's something he can use as a way to start.

@unbalancedparentheses
Copy link

Friday was the first time I compiled rust and it was pretty confusing for me too. I really like the diagram.

@nikomatsakis
Copy link
Contributor

At minimum, we should move that content to the rustc-guide, yes. I am agnostic about the names. I'm wary that all names will be confusing unless there is a picture, and if there is a picture, any name may be fine.

@Mark-Simulacrum
Copy link
Member

The current plan (discussed and mentioned at all hands) is to work towards not needing to say "--stage" unless you're hacking on rustbuild itself or doing something odd; I'm not sure how quickly we can make that happen, but hopefully quite soon.

@scottmcm
Copy link
Member

@Mark-Simulacrum Does that apply to --keep-stage as well? That's the one I use most, since it's currently essentially if you're doing anything in core or std...

@Mark-Simulacrum
Copy link
Member

Yes, keep-stage as well -- you can see some notes here: https://paper.dropbox.com/doc/Rustbuild-All-Hands-2019--AbYzEwK9y9KN~OKiOg2bMnWrAQ-MLKsxxj1SXORp4Qg8aGbQ

@nnethercote
Copy link
Contributor Author

are you comfortable if your explanation and diagrams are reused for rustc-guides?.

Absolutely, please use the above words any way you like.

@jonas-schievink jonas-schievink added T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) and removed T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) A-build labels Apr 21, 2019
@RalfJung
Copy link
Member

RalfJung commented Apr 4, 2020

FWIW I suffered the exact same confusion until @eddyb explained the rustc stage naming to me.

@robinmoussu
Copy link

Same for me. Does this means that if I only need to build the sources, I only need to pass --stage 0 and not --stage 1? I am currently hacking on rustdoc.

@eddyb
Copy link
Member

eddyb commented Apr 5, 2020

@robinmoussu The best way to get the correct behavior is to run tests, IME.
./x.py test --stage 1 src/test/rustdoc{,-ui} will build the compiler and rustdoc exactly once and run its tests. If you want to hack on rustdoc without the compiler being built, but instead relying on the rustc-dev component from a nightly/master build, then you need @Mark-Simulacrum's plan which should allow that (last mentioned on this internals post).

@eddyb
Copy link
Member

eddyb commented Apr 5, 2020

I think overall the worst UX aspect is that ./x.py build --stage 1 doesn't do the same thing as ./x.py build --stage 1 src/libstd but rather it does almost everything that
./x.py build --stage 2 src/libstd does.

And in general ./x.py build --stage N, is useless, since it's missing host libraries (I'm not even sure you can use Xargo or Cargo's -Z build-std without them).

So making src/libstd the default and having to write ./x.py build --stage N src/rustc to get the (less useful) compiler binary with no libraries, seems adequate to me.

Oh and we need to get rid of fulldeps tests and similar things: ./x.py test --stage 1 should not build the compiler twice, but it does (for fulldeps tests and a few other things).
Or we could keep them and run them at stage 2 (ideally without building the compiler thrice).

Right now I'm forced to use this command:
./x.py test --no-fail-fast --stage 1 src/test/{rustdoc,rustdoc-ui,mir-opt,codegen,codegen-units,incremental,pretty,debuginfo,compile-fail,run-make,run-fail,ui}
in order to make sure I'm not missing out on any important tests, without doing unnecessary builds.

@robinmoussu
Copy link

Thanks.

And I agree this mess need to be clean-up. I hope someone will someday do the work.

@eddyb
Copy link
Member

eddyb commented Apr 5, 2020

Would it also help if the sysroot directories were named stage{1,2}-sysroot instead of just stage{1,2}? It would also match stage0-sysroot nicely.

Then some intuition there is that stage1-sysroot has executables (and their runtime dependencies) from stage0-rustc but libraries from stage1-std (built by stage1-sysroot/bin/rustc aka stage0-rustc).

@RalfJung
Copy link
Member

RalfJung commented May 3, 2020

A --stage N flag means build with stage N.

To make things even more confusing, this is not actually always true... ./x.py build src/tools/miri --stage 1 builds with the stage 1 compiler artifacts, i.e., it uses the stage 2 compiler. How that fits into the rest of the scheme is beyond me.

@RalfJung
Copy link
Member

RalfJung commented May 4, 2020

@oli-obk pointed out that stage 0 Miri is being built by the bootstrap compiler, but against the stage 0 compiler artifacts (i.e., it is linked with those). 🤯

@jyn514
Copy link
Member

jyn514 commented Sep 1, 2020

I have a proposal for explaining this better in rust-lang/rustc-dev-guide#843. Please let me know if that helps at all and if not, what I could do to make it better :)

@jyn514
Copy link
Member

jyn514 commented Jan 1, 2021

I have not gotten a lot of feedback about rust-lang/rustc-dev-guide#857 except from new contributors. Do you think it explains this well enough to close the issue, or are there still parts of bootstrapping that are confusing? I'm happy to add more documentation if you think it will help.

(You can see the rendered docs at https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html.)

@Manishearth
Copy link
Member

Manishearth commented Jan 1, 2021

@jyn514 I think what we really need is a set of scenarios like:

  • I want to modify and test the stdlib
  • I want to modify and test rustdoc
    • and test its impact on the stdlib
  • i want to modify and test the compiler
    • and test its impact on the stdlib

There's some of this in the first chapter, but there really should be more.

@Manishearth
Copy link
Member

But the docs about what the stages themselves mean are good! That and x.py saying "building" vs "copying" has been helpful.

@jyn514
Copy link
Member

jyn514 commented Feb 3, 2023

I have a proposal for making this simpler in https://jyn.dev/2023/01/12/Bootstrapping-Rust-in-2023.html.

@jyn514
Copy link
Member

jyn514 commented Jun 25, 2023

btw here is an updated progress message from x.py:

; x b --dry-run --stage 1
Building bootstrap
    Finished dev [unoptimized] target(s) in 0.01s
Building stage0 library artifacts (x86_64-unknown-linux-gnu)
Building compiler artifacts (stage0 -> stage1, x86_64-unknown-linux-gnu)
Creating a sysroot for stage1 compiler (use `rustup toolchain link 'name' build/host/stage1`)
Building stage1 library artifacts (x86_64-unknown-linux-gnu)
Building stage1 tool rust-analyzer-proc-macro-srv (x86_64-unknown-linux-gnu)
Building tool rustdoc (stage0 -> stage1, x86_64-unknown-linux-gnu)
Build completed successfully in 0:00:00

hopefully stage0 -> stage1 makes more sense than just stage0.

@Manishearth
Copy link
Member

Manishearth commented Jun 26, 2023

I wonder if this direction may help further?

; x b --dry-run --stage 1
Building bootstrap
    Finished dev [unoptimized] target(s) in 0.01s
Building stage0 library artifacts (stage0 compiler -> stage0 library, x86_64-unknown-linux-gnu)
Building compiler artifacts (stage0 compiler -> stage1 compiler, x86_64-unknown-linux-gnu)
Creating a sysroot for stage1 compiler (use `rustup toolchain link 'name' build/host/stage1`)
Building stage1 library artifacts (stage1 compiler -> stage1 library, x86_64-unknown-linux-gnu)
Building stage1 tool rust-analyzer-proc-macro-srv (stage1 compiler -> stage1 tool, x86_64-unknown-linux-gnu)
Building tool rustdoc (stage0 compiler -> stage1 tool, x86_64-unknown-linux-gnu)
Build completed successfully in 0:00:00

Interesting to me that rust-analyzer-proc-macro-srv is same-stage but most tools are cross-stage

@jieyouxu jieyouxu added A-contributor-roadblock Area: Makes things more difficult for new contributors to rust itself C-discussion Category: Discussion or questions that doesn't represent real issues. labels Aug 13, 2024
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 24, 2024
Fix cargo staging for run-make tests

Follow-up to rust-lang#130642 (comment) to make sure that when

```
$ COMPILETEST_FORCE_STAGE0=1 ./x test run-make --stage 0
```

is used, bootstrap cargo is used in order to avoid building stage 1 rustc. Note that run-make tests are usually not written with `--stage 0` in mind and some tests may rely on stage1 rustc (nightly) behavior, and it is expected that some tests will fail under this invocation.

This PR also fixes `tool::Cargo` staging in compiletest when preparing for `run-make` test mode, by chopping off a stage from the `compiler` passed to `tool::Cargo` such that when the user invokes with stage `N`

```
./x test run-make --stage N
```

the `run-make` test suite will be tested against the cargo built by stage `N` compiler. Let's take `N=1`, i.e. `--stage 1`, without chopping off a stage, previously `./x test run-make --stage 1` will cause stage 1 rustc + std to be built, then stage 2 rustc, and cargo will be produced by the stage 2 rustc, which is clearly not what we want. By chopping off a stage, it means that cargo will be produced by the stage 1 rustc.

cc rust-lang#119946, rust-lang#59864.
See discussions regarding the tool staging at https://rust-lang.zulipchat.com/#narrow/stream/326414-t-infra.2Fbootstrap/topic/.E2.9C.94.20stage1.20run-make.20tests.20now.20need.20stage2.20rustc.20built.20for.20c.2E.2E.2E.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-contributor-roadblock Area: Makes things more difficult for new contributors to rust itself C-discussion Category: Discussion or questions that doesn't represent real issues. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap)
Projects
None yet
Development

No branches or pull requests