Skip to content

Commit 92d076c

Browse files
committed
Refactor Std dist step
1 parent 5ccafaa commit 92d076c

File tree

4 files changed

+62
-33
lines changed

4 files changed

+62
-33
lines changed

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,30 @@ impl Std {
9696
}
9797
deps
9898
}
99+
100+
/// Returns true if the standard library will be uplifted from stage 1 for the given
101+
/// `build_compiler` (which determines the stdlib stage) and `target`.
102+
///
103+
/// Uplifting is enabled if we're building a stage2+ libstd, full bootstrap is
104+
/// disabled and we have a stage1 libstd already compiled for the given target.
105+
pub fn should_be_uplifted_from_stage_1(
106+
builder: &Builder<'_>,
107+
stage: u32,
108+
target: TargetSelection,
109+
) -> bool {
110+
stage > 1
111+
&& !builder.config.full_bootstrap
112+
// This estimates if a stage1 libstd exists for the given target. If we're not
113+
// cross-compiling, it should definitely exist by the time we're building a stage2
114+
// libstd.
115+
// Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
116+
// rustc needs to link to a cross-compiled libstd, so again we should have a stage1
117+
// libstd for the given target prepared.
118+
// Even if we guess wrong in the cross-compiled case, the worst that should happen is
119+
// that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
120+
// don't pay the libstd build cost twice.
121+
&& (target == builder.host_target || builder.config.hosts.contains(&target))
122+
}
99123
}
100124

101125
impl Step for Std {
@@ -193,22 +217,7 @@ impl Step for Std {
193217
// Stage of the stdlib that we're building
194218
let stage = build_compiler.stage;
195219

196-
// If we're building a stage2+ libstd, full bootstrap is
197-
// disabled and we have a stage1 libstd already compiled for the given target,
198-
// then simply uplift a previously built stage1 library.
199-
if build_compiler.stage > 1
200-
&& !builder.config.full_bootstrap
201-
// This estimates if a stage1 libstd exists for the given target. If we're not
202-
// cross-compiling, it should definitely exist by the time we're building a stage2
203-
// libstd.
204-
// Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
205-
// rustc needs to link to a cross-compiled libstd, so again we should have a stage1
206-
// libstd for the given target prepared.
207-
// Even if we guess wrong in the cross-compiled case, the worst that should happen is
208-
// that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
209-
// don't pay the libstd build cost twice.
210-
&& (target == builder.host_target || builder.config.hosts.contains(&target))
211-
{
220+
if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage, target) {
212221
let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
213222
builder.std(build_compiler_for_std_to_uplift, target);
214223

src/bootstrap/src/core/build_steps/dist.rs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -747,9 +747,16 @@ fn copy_target_libs(
747747
}
748748
}
749749

750+
/// Builds the standard library (`rust-std`) dist component for a given `target`.
751+
/// This includes the standard library dynamic library file (e.g. .so/.dll), along with stdlib
752+
/// .rlibs.
753+
///
754+
/// Note that due to uplifting, we actually ship the stage 1 library
755+
/// (built using the stage1 compiler) even with a stage 2 dist, unless `full-bootstrap` is enabled.
750756
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
751757
pub struct Std {
752-
pub compiler: Compiler,
758+
/// Compiler that will build the standard library.
759+
pub build_compiler: Compiler,
753760
pub target: TargetSelection,
754761
}
755762

@@ -762,39 +769,51 @@ impl Step for Std {
762769
}
763770

764771
fn make_run(run: RunConfig<'_>) {
772+
// This is a build time optimization for running just `x dist rust-std` (without
773+
// `x dist rustc`).
774+
// If we know that we will be uplifting a stage2+ library from stage 1 anyway,
775+
// there is no point in building a stage2 rustc, which will then not do anything (because
776+
// the stdlib will be uplifted).
777+
let top_stage = run.builder.top_stage;
778+
let stage = if top_stage > 1
779+
&& compile::Std::should_be_uplifted_from_stage_1(run.builder, top_stage, run.target)
780+
{
781+
run.builder.info(&format!(
782+
"Note: stage {top_stage} library for `{}` would be uplifted from stage 1, so stage was downgraded from {top_stage} to 1 to avoid needless compiler build(s)",
783+
run.target
784+
));
785+
1
786+
} else {
787+
top_stage
788+
};
765789
run.builder.ensure(Std {
766-
compiler: run.builder.compiler_for(
767-
run.builder.top_stage,
768-
run.builder.config.host_target,
769-
run.target,
770-
),
790+
build_compiler: run.builder.compiler(stage, run.builder.config.host_target),
771791
target: run.target,
772792
});
773793
}
774794

775795
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
776-
let compiler = self.compiler;
796+
let build_compiler = self.build_compiler;
777797
let target = self.target;
778798

779-
if skip_host_target_lib(builder, compiler) {
799+
if skip_host_target_lib(builder, build_compiler) {
780800
return None;
781801
}
782802

783-
builder.std(compiler, target);
803+
builder.std(build_compiler, target);
784804

785805
let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
786806
tarball.include_target_in_component_name(true);
787807

788-
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
789-
let stamp = build_stamp::libstd_stamp(builder, compiler_to_use, target);
808+
let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
790809
verify_uefi_rlib_format(builder, target, &stamp);
791810
copy_target_libs(builder, target, tarball.image_dir(), &stamp);
792811

793812
Some(tarball.generate())
794813
}
795814

796815
fn metadata(&self) -> Option<StepMetadata> {
797-
Some(StepMetadata::dist("std", self.target).built_by(self.compiler))
816+
Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
798817
}
799818
}
800819

@@ -1630,7 +1649,8 @@ impl Step for Extended {
16301649
// the std files during uninstall. To do this ensure that rustc comes
16311650
// before rust-std in the list below.
16321651
tarballs.push(builder.ensure(Rustc { target_compiler }));
1633-
tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
1652+
tarballs
1653+
.push(builder.ensure(Std { build_compiler: compiler, target }).expect("missing std"));
16341654

16351655
if target.is_windows_gnu() {
16361656
tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));

src/bootstrap/src/core/build_steps/install.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ install!((self, builder, _config),
214214
// `expect` should be safe, only None when host != build, but this
215215
// only runs when host == build
216216
let tarball = builder.ensure(dist::Std {
217-
compiler: self.compiler,
217+
build_compiler: self.compiler,
218218
target: self.target
219219
}).expect("missing std");
220220
install_sh(builder, "std", self.compiler.stage, Some(self.target), &tarball);

src/bootstrap/src/utils/build_stamp.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ pub fn codegen_backend_stamp(
136136
}
137137

138138
/// Cargo's output path for the standard library in a given stage, compiled
139-
/// by a particular compiler for the specified target.
139+
/// by a particular `build_compiler` for the specified `target`.
140140
pub fn libstd_stamp(
141141
builder: &Builder<'_>,
142-
compiler: Compiler,
142+
build_compiler: Compiler,
143143
target: TargetSelection,
144144
) -> BuildStamp {
145-
BuildStamp::new(&builder.cargo_out(compiler, Mode::Std, target)).with_prefix("libstd")
145+
BuildStamp::new(&builder.cargo_out(build_compiler, Mode::Std, target)).with_prefix("libstd")
146146
}
147147

148148
/// Cargo's output path for librustc in a given stage, compiled by a particular

0 commit comments

Comments
 (0)