about summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorJakub Beránek <berykubik@gmail.com>2025-08-12 12:29:14 +0200
committerJakub Beránek <berykubik@gmail.com>2025-08-23 11:00:30 +0200
commit502dc8df56e37477da5249245cb8074b40a4c2ce (patch)
treea2e80082765bf665676c36c6c3099bf147e6435b /src/bootstrap
parentf8b3c566cc9b27816efa17a21365d36dd55cd71f (diff)
downloadrust-502dc8df56e37477da5249245cb8074b40a4c2ce.tar.gz
rust-502dc8df56e37477da5249245cb8074b40a4c2ce.zip
Refactor `Std` dist step
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs41
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs46
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs2
-rw-r--r--src/bootstrap/src/utils/build_stamp.rs6
4 files changed, 62 insertions, 33 deletions
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 6ca32aca345..7b3e5db58f8 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -96,6 +96,30 @@ impl Std {
         }
         deps
     }
+
+    /// Returns true if the standard library will be uplifted from stage 1 for the given
+    /// `build_compiler` (which determines the stdlib stage) and `target`.
+    ///
+    /// Uplifting is enabled if we're building a stage2+ libstd, full bootstrap is
+    /// disabled and we have a stage1 libstd already compiled for the given target.
+    pub fn should_be_uplifted_from_stage_1(
+        builder: &Builder<'_>,
+        stage: u32,
+        target: TargetSelection,
+    ) -> bool {
+        stage > 1
+            && !builder.config.full_bootstrap
+            // This estimates if a stage1 libstd exists for the given target. If we're not
+            // cross-compiling, it should definitely exist by the time we're building a stage2
+            // libstd.
+            // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
+            // rustc needs to link to a cross-compiled libstd, so again we should have a stage1
+            // libstd for the given target prepared.
+            // Even if we guess wrong in the cross-compiled case, the worst that should happen is
+            // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
+            // don't pay the libstd build cost twice.
+            && (target == builder.host_target || builder.config.hosts.contains(&target))
+    }
 }
 
 impl Step for Std {
@@ -193,22 +217,7 @@ impl Step for Std {
         // Stage of the stdlib that we're building
         let stage = build_compiler.stage;
 
-        // If we're building a stage2+ libstd, full bootstrap is
-        // disabled and we have a stage1 libstd already compiled for the given target,
-        // then simply uplift a previously built stage1 library.
-        if build_compiler.stage > 1
-            && !builder.config.full_bootstrap
-            // This estimates if a stage1 libstd exists for the given target. If we're not
-            // cross-compiling, it should definitely exist by the time we're building a stage2
-            // libstd.
-            // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
-            // rustc needs to link to a cross-compiled libstd, so again we should have a stage1
-            // libstd for the given target prepared.
-            // Even if we guess wrong in the cross-compiled case, the worst that should happen is
-            // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
-            // don't pay the libstd build cost twice.
-            && (target == builder.host_target || builder.config.hosts.contains(&target))
-        {
+        if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage, target) {
             let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
             builder.std(build_compiler_for_std_to_uplift, target);
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 29e4a608c3a..5694688780b 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -747,9 +747,16 @@ fn copy_target_libs(
     }
 }
 
+/// Builds the standard library (`rust-std`) dist component for a given `target`.
+/// This includes the standard library dynamic library file (e.g. .so/.dll), along with stdlib
+/// .rlibs.
+///
+/// Note that due to uplifting, we actually ship the stage 1 library
+/// (built using the stage1 compiler) even with a stage 2 dist, unless `full-bootstrap` is enabled.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Std {
-    pub compiler: Compiler,
+    /// Compiler that will build the standard library.
+    pub build_compiler: Compiler,
     pub target: TargetSelection,
 }
 
@@ -762,31 +769,43 @@ impl Step for Std {
     }
 
     fn make_run(run: RunConfig<'_>) {
+        // This is a build time optimization for running just `x dist rust-std` (without
+        // `x dist rustc`).
+        // If we know that we will be uplifting a stage2+ library from stage 1 anyway,
+        // there is no point in building a stage2 rustc, which will then not do anything (because
+        // the stdlib will be uplifted).
+        let top_stage = run.builder.top_stage;
+        let stage = if top_stage > 1
+            && compile::Std::should_be_uplifted_from_stage_1(run.builder, top_stage, run.target)
+        {
+            run.builder.info(&format!(
+                "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)",
+                run.target
+            ));
+            1
+        } else {
+            top_stage
+        };
         run.builder.ensure(Std {
-            compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
+            build_compiler: run.builder.compiler(stage, run.builder.config.host_target),
             target: run.target,
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
+        let build_compiler = self.build_compiler;
         let target = self.target;
 
-        if skip_host_target_lib(builder, compiler) {
+        if skip_host_target_lib(builder, build_compiler) {
             return None;
         }
 
-        builder.std(compiler, target);
+        builder.std(build_compiler, target);
 
         let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
         tarball.include_target_in_component_name(true);
 
-        let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
-        let stamp = build_stamp::libstd_stamp(builder, compiler_to_use, target);
+        let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
         verify_uefi_rlib_format(builder, target, &stamp);
         copy_target_libs(builder, target, tarball.image_dir(), &stamp);
 
@@ -794,7 +813,7 @@ impl Step for Std {
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
-        Some(StepMetadata::dist("std", self.target).built_by(self.compiler))
+        Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
     }
 }
 
@@ -1630,7 +1649,8 @@ impl Step for Extended {
         // the std files during uninstall. To do this ensure that rustc comes
         // before rust-std in the list below.
         tarballs.push(builder.ensure(Rustc { target_compiler }));
-        tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
+        tarballs
+            .push(builder.ensure(Std { build_compiler: compiler, target }).expect("missing std"));
 
         if target.is_windows_gnu() {
             tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 92e5084d490..d1c93acd789 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -214,7 +214,7 @@ install!((self, builder, _config),
         // `expect` should be safe, only None when host != build, but this
         // only runs when host == build
         let tarball = builder.ensure(dist::Std {
-            compiler: self.compiler,
+            build_compiler: self.compiler,
             target: self.target
         }).expect("missing std");
         install_sh(builder, "std", self.compiler.stage, Some(self.target), &tarball);
diff --git a/src/bootstrap/src/utils/build_stamp.rs b/src/bootstrap/src/utils/build_stamp.rs
index 6c79385190e..4c35388a181 100644
--- a/src/bootstrap/src/utils/build_stamp.rs
+++ b/src/bootstrap/src/utils/build_stamp.rs
@@ -136,13 +136,13 @@ pub fn codegen_backend_stamp(
 }
 
 /// Cargo's output path for the standard library in a given stage, compiled
-/// by a particular compiler for the specified target.
+/// by a particular `build_compiler` for the specified `target`.
 pub fn libstd_stamp(
     builder: &Builder<'_>,
-    compiler: Compiler,
+    build_compiler: Compiler,
     target: TargetSelection,
 ) -> BuildStamp {
-    BuildStamp::new(&builder.cargo_out(compiler, Mode::Std, target)).with_prefix("libstd")
+    BuildStamp::new(&builder.cargo_out(build_compiler, Mode::Std, target)).with_prefix("libstd")
 }
 
 /// Cargo's output path for librustc in a given stage, compiled by a particular