-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Enforce in bootstrap that build must have stage at least 1 #142581
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
Conversation
|
This actually interacts with cross-compilation, as I mentioned here:
You need to pass |
This comment has been minimized.
This comment has been minimized.
This PR modifies If appropriate, please update This PR modifies If appropriate, please update |
49ed3f9
to
6bf0ab7
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
// Now check that the selected stage makes sense, and if not, print a warning and end | ||
match (config.stage, &config.cmd) { | ||
(0, Subcommand::Build) => { | ||
eprintln!("WARNING: cannot build anything on stage 0. Use at least stage 1."); | ||
exit!(1) | ||
} | ||
_ => {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: if we warn on the no-op that is ./x build --stage=0
, what about ./x check --stage=0
? I guess for the check case, we can't do that yet without untying bootstrap tool checking from staging?
Also, does this reject e.g. ./x build src/tools/opt-dist --stage=0
?
EDIT: indeed,
#[test]
#[should_panic]
fn build_bootstrap_tool_stage_0() {
insta::assert_snapshot!(get_steps("opt-dist", "build", Some(0)), @"");
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check is a whole another beast, I'm working on a PR for it, but the individual bootstrap kinds (build/check/etc.) are mostly separate in the stage handling, so I will do it piece by piece.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, I'm planning for check --stage 0
to also be an error.
// If only `compiler` was passed, do not run this step. | ||
// Instead the `Assemble` step will take care of compiling Rustc. | ||
if run.builder.paths == vec![PathBuf::from("compiler")] { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remark: this kinda feels iffy, in that I feel like the path filtering/handling logic that lead to
Rustc
step was invoked twice, once with all crates and once with no crates (even though both of these mean the same thing).
makes this kinda weird.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would love Rustc
and Assemble
to be just one step (to avoid things like this), but I guess that it's sort of an optimizatoin, Rustc
allows building only selected crates, and doesn't involve building a ton of other things that you might not want for a quick build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that does make sense.
I'm generally in favor of imposing more discipline (or more order, for that matter) on build staging as is done in this PR. Not super sure about rejecting Maybe r? @Mark-Simulacrum |
That depends on how we decide #t-infra/bootstrap > Proposal to cleanup stages and steps after the redesign. The bootstrap tools don't really participate in staging (unless you're cross-compiling, but we don't even support cross-compiling these tools, as they are host tools, essentially). So in theory we could allow them to be built with whatever |
☔ The latest upstream changes (presumably #142685) made this pull request unmergeable. Please resolve the merge conflicts. |
…ompiler` path It was confusing that the `Rustc` step was invoked twice, once with all crates and once with no crates (even though both of these mean the same thing).
f8a105c
to
809f750
Compare
The pre-requisite PRs have finally landed, so I ported this PR on top of the new config test builder and step metadata. Now it should be hopefully quite clear which (important) steps are being executed when we do @jieyouxu Could you please take another looks? Thanks! |
I had to port a bunch of tests to the new snapshot test suite. Some of them were duplicated or seemed quite dubious, so I removed a few of them. I expect that several step traces are not ideal here (in particular around cross-compilation), and we might want to re-evaluate them. But I would only do it after we finish the renumbering for check/clippy/test kinds and also for tools, which are all kinds of special. To avoid any intermediate hacks before we see how the staging traces work after everything has been ported. |
I think this goes back to what Ralf described as the "staging boundary" right? As in, where do you do a stage cut-off.
Sounds a bit weird to me at first, because the stage 1 library is built with the stage 1 compiler, but now bootstrap tools (stage 1 too in this PR) are built with the stage 0 compiler. Previously, they were stuffed to stage 0, because the reasoning is moreso that "it's built by the stage 0 compiler". After reading https://hackmd.io/QXj6LqntQTKPgm3uBuE-aA, I think I can see that with
In the sense that bootstrap tools were built from in-tree sources. I still feel a bit... confused, mentally, by this model. I think I can understand "well, you have to pick a mental model", and I can appreciate that trying to fit various kinds of "tools" into this mental model and making this coherent/self-consistent and easy to comprehend is not exactly trivial. @rust-lang/bootstrap thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The overall implementation looks good. Just a few nits/questions, and also see previously the discussion re. mental model.
StepMetadata::build("rustdoc", self.compiler.host) | ||
// rustdoc is ToolRustc, so stage N rustdoc is built by stage N-1 rustc | ||
// FIXME: make this stage deduction automatic somehow | ||
// FIXME: log the compiler that actually built ToolRustc steps | ||
.stage(self.compiler.stage.saturating_sub(1)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussion [MENTAL-MODEL 1/N]: for example, like trying to fit rustc-tools into a self-consistent/coherent mental model
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I already have a follow-up branch prepared that works on tools. They are so painful.. and also duplicated across check/build. I still have to untangle this mess, and move some tools to different modes.
// Cross-compilation fails on stage 1, as we don't have a stage0 std available | ||
// for non-host targets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussion [MENTAL-MODEL]: I think this makes sense, and I would agree that we should strive for correctness -- for example, don't try to do magic stage promotions/adjustments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'd rather just disable cross-compilation at stage 1 than do the magical step promotion. I was in the opposite opinion camp just a few weeks ago, but after investigating bootstrap in detail, I have switched opinions =D
#[test] | ||
fn build_bootstrap_tool_stage_2() { | ||
let ctx = TestCtx::new(); | ||
insta::assert_snapshot!( | ||
ctx.config("build") | ||
.path("opt-dist") | ||
.stage(2) | ||
.render_steps(), @"[build] rustc 0 <host> -> OptimizedDist <host>"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussion: I almost wonder if we should issue a warning for the case where you try to ./x build <bootstrap-tool> --stage=2
, but since bootstrap tools are stage-agnostic, so to speak, this mental model is still coherent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it could be a warning. I'd leave that for a different PR though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
So far (unless we find yet another exception), the "new" mental model is:
I think that's simple enough. |
Okay, that does seem reasonable to me. |
To me, the current set of changes looks more consistent. I'd like to have a second pair of eyes on this though, so. |
Actually @Kobzol could you add
In the rustc-dev-guide bootstrap chapter somewhere, to establish what contributors should interpret the stage meaning as? |
Otherwise, I think we should merge this, there are some hard self-consistency fixes that need this invariant and test coverage (e.g. to work towards fixing #142505 properly). |
Happy to document this, but I'm not sure if it isn't premature? In the sense that check/clippy/test and possibly other stuff doesn't fully uphold this mental model yet. |
Right. |
Okay, I looked at this again, it does seem more self-consistent to me. I'm going to give this some |
☀️ Test successful - checks-actions |
What is this?This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.Comparing 1e83852 (parent) -> 8f21a5c (this PR) Test differencesShow 51 test diffsStage 0
Job group index Test dashboardRun cargo run --manifest-path src/ci/citool/Cargo.toml -- \
test-dashboard 8f21a5c92ea55c348c275a1bc4fedbdf181e0d64 --output-dir test-dashboard And then open Job duration changes
How to interpret the job duration changes?Job durations can vary a lot, based on the actual runner instance |
Finished benchmarking commit (8f21a5c): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)Results (primary 5.9%, secondary -2.8%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (secondary 10.3%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 691.88s -> 691.142s (-0.11%) |
This PR is a step towards https://rust-lang.zulipchat.com/#narrow/channel/326414-t-infra.2Fbootstrap/topic/Proposal.20to.20cleanup.20stages.20and.20steps.20after.20the.20redesign/with/523586917. It's very hard or me to make self-contained changes to bootstrap at this moment, so this PR kind of does several things:
Std::new
in bootstrap, and replace it with aBuilder::std
method (similar toBuilder::compiler
). This is mostly to remove executions of theStd
step for stage 0, which doesn't make a lot of sense; I'd like to ideally have the invariant that when a step is invoked, it actually builds or does something. Eventually, I'd like for everything to go throughBuilder::std
. (Note: I'm not totally married to this idea, if you don't like it, we can remove it from this PR. I mostly did it right now to remove stage 0 std steps from snapshot tests, which shouldn't be there, but we can also filter them out in a different way)x build compiler
, only theAssemble
root level step will be invoked, and not theRustc
step. Before, both were invoked, which actually ranRustc
twice, once with allcrates
filled, and once with no crates (but both actually represent the same situation). Since theRustc::make_run
step actually requests a compile that is one stage below it, this actually madebuild compiler --stage 0
work, which we don't want to have anymore.build
commands are always on stage>=1
. If you try tobuild
anything on stage 0, it will print a warning and exit bootstrap. This follows the intuition from the new staging rules after the stage redesign; artifacts that are "stage 0" come outside of bootstrap, and we can't really build something for which we don't have source (although we can still test it, but that's for another PR).Now the logic for build should be quite simple. For pretty much everything except for
Std
, you first use the stage0 compiler to build stage 1. Then you can build a stage 2 using the previously built stage 1 (and then you can continue to stage 3 etc.). And that's it. The default build stage for everything is 1 (modulo download-ci-rustc, but that's a separate can of worms).The snapshot test infra isn't super nice at the moment, as one of next steps I want to create some simple Builder pattern that will allow us to configure the bootstrap invocations in a more "forward-compatible" way (e.g. now it's not possible to modify the config passed to
configure_with_args
).There are some things not yet fully resolved for build stage 0:
ModeRustc
tool, even though it doesn't really have to be, it is buildable with the stage0 compileropt-dist
,build-manifest
etc.) are still called stage0 tools, and in the bootstrap output it says something like "stage 0 rustc builds stage 0 opt-dist". Which is a bit weird, but functionally there's no difference, it's just a slightly inconsistent output. We still haven't decided if we should make these tools ignore staging altogether (which is IMO the right choice) or if we want to allow building stage 1/2/3/... bootstrap tools.r? @jieyouxu
try-job: x86_64-rust-for-linux