-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Fix off-by-one-error in stage numbering between rustc-guide and rustbuild #57963
Comments
(I think this misunderstanding has been at the root of all my rustc feedback loop problems, so I'd be happy to resolve it or attempt to.) |
FWIW, the stages printed in rustc output aren't wrong -- the Specifically, "Stage 0: the stage0 compiler is usually the current beta compiler" is true, but that's (mostly, modulo build scripts in stage0 std compilation) only true for the I'm not sure if any of that made sense -- I myself still struggle with this pretty much every time I confront any sort of staging issue or work with rustbuild. If you have suggestions, I'd love to hear them; I think the problem is that there are two concepts at play here: a compiler (with its set of dependencies) and it's "target" libraries (std, test, and rustc-ish). Both are staged, but in sort of a staggered manner. That makes talking about any of this quite hard. |
I also found the situation quite confusing. @Mark-Simulacrum Perhaps it would be easier to understand and give words to things if we had a sort of sequence/activity diagram or flowchart for stages and dependencies that exist. A picture says... |
I have found it to be confusing, too. I had some notes lying around about how it works. Perhaps one way to think of it is:
That's a bit convoluted. I would expect it to be more along the lines of "stage 0 builds stage 1", but alas it is not. It's also confusing because building HOST std and TARGET std are different based on the stage (notice below how stage2 only builds non-host std targets — I don't know why). And
--stage=0 stops here
--stage=1 stops here
--stage=2 stops here Notes:
Maybe adding a little extra detail to rustc-guide would help? Does any of that help, or is it more confusing now? |
Thank you all for your comments. I understand now that stage0 is a full-fledged stage and no one feels like that's wrong, which is a good thing because it means we just need to fix the guide not change the semantics of rustc guide. I think there are several misleading things in that section of the rustc guide:
I'll come back to this use your info and insights to propose some changes to the rustc-guide repo. |
Here's another part that has me doubting everything I think I know about how rustc is built, the guide says:
and in a few more places it makes reference to |
Also, in https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html#workflow about the commend
Which "old standard library" does it mean there, stage 0 or stage 1? Also, it's confusing to target stage 1 and keep stage 1. Assuming it's not equivalent to |
@dwijnand the first bit is just a bit confusingly worded. rustc is the compiler and libstd is the standard library (which includes libcore, liballoc, etc.). It just means "rustc, and libstd, and other tooling may use unstable features internally". |
@jonas-schievink I'm not sure. You're right, that could be the interpretation, but in https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html#build-flags it says from running
And again in https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html#workflow:
|
Yes, you need both the Rust compiler rustc and a libstd compatible with that compiler in order to build Rust programs (unless you use ...this really is hairy |
A PR to the rustc guide would be much appreciated. A better naming scheme in the build system would be helpful too: if it is built with stage N, it should be called stage N+1, even if that stage contains only a libstd or only a compiler... |
@jonas-schievink I'm concerned that it's instructing to compile stage 1 libstd just so it does the two steps before: copy rustc and sysroot into
Yeah, perhaps that can be achieved without any or too much disruption. I'll try and send a PR soon fixing some of the explanation and probably including Eric's breakdown. |
Actually... @jonas-schievink
At stage 0 beta rust compiles first libstd then rustc. Are those two artefacts compatible with one another? |
(take everything I say with a grain of salt, I'm not really sure how the entire bootstrap process works)
I think this step is needed to ensure the compiler is always built against its own libstd, not the libstd shipped with beta (downloaded as stage0). This is where the The compiler is then built and links against this libstd we just built. Now we want to build libstd again, using that compiler, which now has all features that libstd might want, so we can turn off (I'm not sure how the process around proc macros or compiler plugins works, I think those have a few more caveats) |
Thanks, @jonas-schievink, your explanation is looking more and more likely. The question I have about that being how it works is: if a proper, usable distribution requires a fresh compiler and a fresh library built with that compiler, why is stage0 first libstd and then rustc? It's like staging is delimited by compiler builds which is only half of a distribution build. Why not use beta rustc + beta std to build the first iteration of the distribution? In a proper release of Rust, what's at the tail of the build? Is there a final-final-final compiler that build libstd and together they ship? |
I believe the compiler and libs that ends up in the "stage2" directory is what is typically distributed. I made a simplified diagram of what I wrote above: https://gist.github.com/ehuss/e40c18e1678fec0aa5861fd0d1653a87 |
I'm not entirely sure, but I think this is because it's convenient if we only have to make rustc build against the libstd inside the same repository instead of having to make it compatible with the downloaded beta libstd. The libstd in this repo often has quite a few Or I'm completely wrong, we do sometimes need |
I'm just going to leave a semi-quick comment here (well, it turned out longer than expected) -- I want to more fully flesh out this documentation, unfortunately I just don't have the time right now; probably after the all hands I will have the time to respond more thoroughly. I'm hopeful that we can get some good documentation/understanding here for all parties though! I've excerpted a few bits from above with some answers, hopefully this at least helps for now:
This is because during stage 2, the host std is uplifted from the "stage 1" std -- specifically, when you see "Building stage 1 artifacts" that's later copied into stage 2 as well (both the compiler's libdir and the sysroot).
This is not wasteful -- that std is pretty much necessary for any useful work with the compiler. Specifically, it's used as the std for programs compiled by that compiler (so when you compile
I've considered doing this in the past but it's actually somewhat misleading. Every time we compile any of the main artifacts ("std", "test", "rustc") we're actually performing two steps. I'll call the compiler which compiles these libraries
The rustc that's built is linked to the freshly-built libstd. So not only are they compatible, that's the only way rustc is guaranteed to build. As @jonas-schievink discusses in #57963 (comment), "the compiler is always built against its own libstd" is the correct reason for this. That means that for the most part only std needs to be cfg-gated. This means that rustc can use features added to std immediately after their addition, there's no need to wait until they get into beta. However, in "The libstd created by that is up-to-date and compatible with the built compiler (as in, you can use the resulting rustc+libstd pair to build any Rust program using the latest Rust features)." (#57963 (comment)), that's perhaps a bit misleading. The libstd built by the stage1/bin/rustc compiler, also known as stage 1 std artifacts, is not necessarily ABI-compatible with that compiler. That is, the Perhaps worth noting -- when I say "ABI" I most likely mean more than that. I've not received any concrete answers from rustc devs as to what actually needs to stay the same -- but loosely I believe this is broadly metadata encoding and the ABI itself. This is also where
The reason we first build std, then test, then rustc, is largely just because we want to minimize The reason we need to build twice is because of ABI compatibility. The beta compiler has it's own ABI, then the stage1/bin/rustc compiler will produce programs/libraries with the new ABI. We actually used to build three times, but because we assume that the ABI is constant within a codebase, we presume that the libraries produced by the "stage2" compiler (produced by the stage1/bin/rustc compiler) is ABI-compatible with the stage1/bin/rustc compiler's produced libraries. What this means is that we can skip that final compilation -- and simply use the same libraries as the stage2/bin/rustc compiler uses itself for programs it links against. This stage2/bin/rustc compiler is shipped to end-users, along with the "stage 1 {std,test,rustc}" artifacts. I hope this was helpful -- I'll try to make some time to leave another response tomorrow, maybe even put together that graphic @Centril suggested, but not sure if that'll happen yet. |
Thank you, @Mark-Simulacrum, for that. I must confess that while I did understand parts of it, large parts flew over my head. 😕 However...
I'll hold off on making any changes myself, then. If you send changes to the rustc-guide I could help review them and perhaps add some of my own. |
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 :) |
I don't think the model of bootstrapping is going to change - I tried that in rust-lang/rustc-dev-guide#843 and there was a lot of resistance to having to change mental models or the arguments to pass to x.py. So I think that means this is a duplicate of #59864 and it doesn't make sense to track this in both places. Feel free to re-open if you disagree :) |
The rustc guide states that:
However a run of rustbuild like so
./x.py build --stage 0
outputs:Personally I think the guide makes more sense. However fixing rustbuild would mean that
--stage 1
would become--stage 2
(and so forth).The text was updated successfully, but these errors were encountered: