about summary refs log tree commit diff
diff options
context:
space:
mode:
authorStuart Cook <Zalathar@users.noreply.github.com>2025-08-19 14:18:26 +1000
committerGitHub <noreply@github.com>2025-08-19 14:18:26 +1000
commitcf2f50e332fc57ada7c667080df3df414ef6bd5f (patch)
tree35c47cddab1d43bc8282c4250bd86288dad15652
parent8748d8e7d5b63932e3062361f736ff436c86be1f (diff)
parent4c212513cf084ad2923cbf86b38c30d4a11fb48d (diff)
downloadrust-cf2f50e332fc57ada7c667080df3df414ef6bd5f.tar.gz
rust-cf2f50e332fc57ada7c667080df3df414ef6bd5f.zip
Rollup merge of #145557 - Kobzol:rustc-link-fix, r=jieyouxu
Fix uplifting in `Assemble` step

In https://github.com/rust-lang/rust/pull/145310, I removed [this line](https://github.com/rust-lang/rust/pull/145310/files#diff-5a1e05f2688d271039171a547d407d0c8a96715ee64d35562fc76b4c9a874303L2109), which adjusted the stage of the build compiler if an uplift has happened. This broke stage3+ uplifted rustc builds (https://github.com/rust-lang/rust/issues/145534). I could swear I tested this in the PR, but somehow I missed it.

Instead of keeping the original returned stage, I made it more explicit by returning the actually used `build_compiler` from the `Rustc` step, and then use that in the `Assemble` step.

The changes to `RustcLink` were needed to fix `ui-fulldeps`, which apparently build a stage3 rustc, because I haven't fixed the test steps yet :sweat_smile:

Hopefully we might be able to remove `RustcLink` if the approach from https://github.com/rust-lang/rust/pull/144252 will work.

Should fix https://github.com/rust-lang/rust/issues/145534.

r? ``@jieyouxu``
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs112
1 files changed, 78 insertions, 34 deletions
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 997a152a31f..74a8cea1ebe 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -933,6 +933,15 @@ fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, conte
     }
 }
 
+/// Represents information about a built rustc.
+#[derive(Clone, Debug)]
+pub struct BuiltRustc {
+    /// The compiler that actually built this *rustc*.
+    /// This can be different from the *build_compiler* passed to the `Rustc` step because of
+    /// uplifting.
+    pub build_compiler: Compiler,
+}
+
 /// Build rustc using the passed `build_compiler`.
 ///
 /// - Makes sure that `build_compiler` has a standard library prepared for its host target,
@@ -960,7 +969,7 @@ impl Rustc {
 }
 
 impl Step for Rustc {
-    type Output = ();
+    type Output = BuiltRustc;
 
     const IS_HOST: bool = true;
     const DEFAULT: bool = false;
@@ -1000,7 +1009,7 @@ impl Step for Rustc {
     /// This will build the compiler for a particular stage of the build using
     /// the `build_compiler` targeting the `target` architecture. The artifacts
     /// created will also be linked into the sysroot directory.
-    fn run(self, builder: &Builder<'_>) {
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
         let build_compiler = self.build_compiler;
         let target = self.target;
 
@@ -1016,7 +1025,7 @@ impl Step for Rustc {
                 &sysroot,
                 builder.config.ci_rustc_dev_contents(),
             );
-            return;
+            return BuiltRustc { build_compiler };
         }
 
         // Build a standard library for `target` using the `build_compiler`.
@@ -1028,9 +1037,9 @@ impl Step for Rustc {
 
             builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
             builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
-            builder.ensure(RustcLink::from_rustc(self, build_compiler));
+            builder.ensure(RustcLink::from_rustc(self));
 
-            return;
+            return BuiltRustc { build_compiler };
         }
 
         // The stage of the compiler that we're building
@@ -1042,21 +1051,35 @@ impl Step for Rustc {
             && !builder.config.full_bootstrap
             && (target == builder.host_target || builder.hosts.contains(&target))
         {
-            // If we're cross-compiling, the earliest rustc that we could have is stage 2.
-            // If we're not cross-compiling, then we should have rustc stage 1.
-            let stage_to_uplift = if target == builder.host_target { 1 } else { 2 };
-            let rustc_to_uplift = builder.compiler(stage_to_uplift, target);
-            let msg = if rustc_to_uplift.host == target {
-                format!("Uplifting rustc (stage{} -> stage{stage})", rustc_to_uplift.stage,)
+            // Here we need to determine the **build compiler** that built the stage that we will
+            // be uplifting. We cannot uplift stage 1, as it has a different ABI than stage 2+,
+            // so we always uplift the stage2 compiler (compiled with stage 1).
+            let uplift_build_compiler = builder.compiler(1, build_compiler.host);
+            let msg = if uplift_build_compiler.host == target {
+                format!("Uplifting rustc (stage2 -> stage{stage})")
             } else {
                 format!(
-                    "Uplifting rustc (stage{}:{} -> stage{stage}:{target})",
-                    rustc_to_uplift.stage, rustc_to_uplift.host,
+                    "Uplifting rustc (stage2:{} -> stage{stage}:{target})",
+                    uplift_build_compiler.host
                 )
             };
             builder.info(&msg);
-            builder.ensure(RustcLink::from_rustc(self, rustc_to_uplift));
-            return;
+
+            // Here the compiler that built the rlibs (`uplift_build_compiler`) can be different
+            // from the compiler whose sysroot should be modified in this step. So we need to copy
+            // the (previously built) rlibs into the correct sysroot.
+            builder.ensure(RustcLink::from_build_compiler_and_sysroot(
+                // This is the compiler that actually built the rustc rlibs
+                uplift_build_compiler,
+                // We copy the rlibs into the sysroot of `build_compiler`
+                build_compiler,
+                target,
+                self.crates,
+            ));
+
+            // Here we have performed an uplift, so we return the actual build compiler that "built"
+            // this rustc.
+            return BuiltRustc { build_compiler: uplift_build_compiler };
         }
 
         // Build a standard library for the current host target using the `build_compiler`.
@@ -1129,10 +1152,8 @@ impl Step for Rustc {
             strip_debug(builder, target, &target_root_dir.join("rustc-main"));
         }
 
-        builder.ensure(RustcLink::from_rustc(
-            self,
-            builder.compiler(build_compiler.stage, builder.config.host_target),
-        ));
+        builder.ensure(RustcLink::from_rustc(self));
+        BuiltRustc { build_compiler }
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
@@ -1441,31 +1462,51 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
     }
 }
 
-/// `RustcLink` copies all of the rlibs from the rustc build into the previous stage's sysroot.
+/// `RustcLink` copies compiler rlibs from a rustc build into a compiler sysroot.
+/// It works with (potentially up to) three compilers:
+/// - `build_compiler` is a compiler that built rustc rlibs
+/// - `sysroot_compiler` is a compiler into whose sysroot we will copy the rlibs
+///   - In most situations, `build_compiler` == `sysroot_compiler`
+/// - `target_compiler` is the compiler whose rlibs were built. It is not represented explicitly
+///   in this step, rather we just read the rlibs from a rustc build stamp of `build_compiler`.
+///
 /// This is necessary for tools using `rustc_private`, where the previous compiler will build
 /// a tool against the next compiler.
 /// To build a tool against a compiler, the rlibs of that compiler that it links against
 /// must be in the sysroot of the compiler that's doing the compiling.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 struct RustcLink {
-    /// The compiler whose rlibs we are copying around.
-    pub compiler: Compiler,
-    /// This is the compiler into whose sysroot we want to copy the rlibs into.
-    pub previous_stage_compiler: Compiler,
-    pub target: TargetSelection,
+    /// This compiler **built** some rustc, whose rlibs we will copy into a sysroot.
+    build_compiler: Compiler,
+    /// This is the compiler into whose sysroot we want to copy the built rlibs.
+    /// In most cases, it will correspond to `build_compiler`.
+    sysroot_compiler: Compiler,
+    target: TargetSelection,
     /// Not actually used; only present to make sure the cache invalidation is correct.
     crates: Vec<String>,
 }
 
 impl RustcLink {
-    fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
+    /// Copy rlibs from the build compiler that build this `rustc` into the sysroot of that
+    /// build compiler.
+    fn from_rustc(rustc: Rustc) -> Self {
         Self {
-            compiler: host_compiler,
-            previous_stage_compiler: rustc.build_compiler,
+            build_compiler: rustc.build_compiler,
+            sysroot_compiler: rustc.build_compiler,
             target: rustc.target,
             crates: rustc.crates,
         }
     }
+
+    /// Copy rlibs **built** by `build_compiler` into the sysroot of `sysroot_compiler`.
+    fn from_build_compiler_and_sysroot(
+        build_compiler: Compiler,
+        sysroot_compiler: Compiler,
+        target: TargetSelection,
+        crates: Vec<String>,
+    ) -> Self {
+        Self { build_compiler, sysroot_compiler, target, crates }
+    }
 }
 
 impl Step for RustcLink {
@@ -1477,14 +1518,14 @@ impl Step for RustcLink {
 
     /// Same as `std_link`, only for librustc
     fn run(self, builder: &Builder<'_>) {
-        let compiler = self.compiler;
-        let previous_stage_compiler = self.previous_stage_compiler;
+        let build_compiler = self.build_compiler;
+        let sysroot_compiler = self.sysroot_compiler;
         let target = self.target;
         add_to_sysroot(
             builder,
-            &builder.sysroot_target_libdir(previous_stage_compiler, target),
-            &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
-            &build_stamp::librustc_stamp(builder, compiler, target),
+            &builder.sysroot_target_libdir(sysroot_compiler, target),
+            &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
+            &build_stamp::librustc_stamp(builder, build_compiler, target),
         );
     }
 }
@@ -2099,7 +2140,10 @@ impl Step for Assemble {
             "target_compiler.host" = ?target_compiler.host,
             "building compiler libraries to link to"
         );
-        builder.ensure(Rustc::new(build_compiler, target_compiler.host));
+
+        // It is possible that an uplift has happened, so we override build_compiler here.
+        let BuiltRustc { build_compiler } =
+            builder.ensure(Rustc::new(build_compiler, target_compiler.host));
 
         let stage = target_compiler.stage;
         let host = target_compiler.host;