From efaf154882e69ad736958b1e902038a121be9ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Aug 2026 08:31:52 +0200 Subject: [PATCH 1/4] Pass Cargo's kind, instead of builder kind, when deciding on rustc features --- src/bootstrap/src/core/build_steps/compile.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index a1fdffc35f226..4422a361ba86d 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1221,9 +1221,10 @@ pub fn rustc_cargo( build_compiler: &Compiler, crates: &[String], ) { + let kind = cargo.kind(); cargo .arg("--features") - .arg(builder.rustc_features(builder.kind, target, crates)) + .arg(builder.rustc_features(kind, target, crates)) .arg("--manifest-path") .arg(builder.src.join("compiler/rustc/Cargo.toml")); From b30618f487bcf29cc46338de375303e6a8b31dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Aug 2026 08:55:24 +0200 Subject: [PATCH 2/4] Centralize handling of `rustc_llvm` check skip --- src/bootstrap/src/core/build_steps/compile.rs | 27 +++++++++++++------ src/bootstrap/src/core/builder/cargo.rs | 15 ----------- src/bootstrap/src/core/builder/mod.rs | 22 +++++++++++++++ src/bootstrap/src/core/session.rs | 4 +-- 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 4422a361ba86d..c12257e9ba2bf 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1387,18 +1387,29 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS // variables, requiring LLVM to have been built. // - For check builds, we want to avoid building LLVM if possible. // - Check builds and non-check builds should have the same environment if - // possible, to avoid unnecessary rebuilds due to cache-busting. + // possible, to avoid unnecessary rebuilds due to cache-busting (in the same stage). // - // Therefore we try to avoid building LLVM for check builds, but only if - // building LLVM would be expensive. If "building" LLVM is cheap - // (i.e. it's already built or is downloadable), we prefer to maintain a - // consistent environment between check and non-check builds. + // If we have either: + // - LLVM already locally built + // - download-ci-llvm enabled + // - LLVM provided externally through a llvm-config + // + // and we do a check-like build, we run rustc_llvm as normally, to maintain a + // consistent environment between check and non-check builds + // + // However, if neither from the above three bullet points is true, and we do a check-like build, + // we skip running rustc_llvm by setting the RUST_CHECK environment variable. + // + // Note that if download-ci-llvm is enabled, `prebuilt_llvm_output` will *eagerly* download + // LLVM from CI, thus making it locally available. if builder.config.llvm_enabled(target) { let building_llvm_is_expensive = prebuilt_llvm_output(builder, target).is_none(); - let skip_llvm = (cargo.kind() == Kind::Check) && building_llvm_is_expensive; - if !skip_llvm { - rustc_llvm_env(builder, cargo, target) + let skip_llvm = cargo.kind().is_check_like() && building_llvm_is_expensive; + if skip_llvm { + cargo.env("RUST_CHECK", "1"); + } else { + rustc_llvm_env(builder, cargo, target); } } diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 121f3c0a81850..9eff50772a8f2 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -5,7 +5,6 @@ use std::{env, fs}; use super::{Builder, Kind}; use crate::core::build_steps::compile::is_lto_stage; -use crate::core::build_steps::llvm::prebuilt_llvm_output; use crate::core::build_steps::test; use crate::core::build_steps::tool::SourceType; use crate::core::compiler::Compiler; @@ -752,20 +751,6 @@ impl Builder<'_> { cargo.env("REAL_LIBRARY_PATH", e); } - // Set a flag for `check`/`clippy`/`fix`, so that certain build - // scripts can do less work (i.e. not building/requiring LLVM). - if matches!(cmd_kind, Kind::Check | Kind::Clippy | Kind::Fix) { - // If we've not yet built LLVM, or it's stale, then bust - // the rustc_llvm cache. That will always work, even though it - // may mean that on the next non-check build we'll need to rebuild - // rustc_llvm. But if LLVM is stale, that'll be a tiny amount - // of work comparatively, and we'd likely need to rebuild it anyway, - // so that's okay. - if prebuilt_llvm_output(self, target).is_none() { - cargo.env("RUST_CHECK", "1"); - } - } - // Forward `./x fix --allow-dirty` from bootstrap to cargo. if matches!(cmd_kind, Kind::Fix) && let Subcommand::Fix { allow_dirty } = self.config.cmd diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 0d7f4613723dc..441431d2fc8a6 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -688,6 +688,28 @@ impl Kind { } .to_owned() } + + /// Is this a command similar to check, which only runs the compiler frontend and doesn't + /// build code for the target? (it can still build code for the host, i.e. proc macros). + pub fn is_check_like(&self) -> bool { + match self { + Kind::Check | Kind::Clippy | Kind::Fix | Kind::Doc => true, + Kind::Build + | Kind::Format + | Kind::Test + | Kind::Miri + | Kind::MiriSetup + | Kind::MiriTest + | Kind::Bench + | Kind::Clean + | Kind::Dist + | Kind::Install + | Kind::Run + | Kind::Setup + | Kind::Vendor + | Kind::Perf => false, + } + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] diff --git a/src/bootstrap/src/core/session.rs b/src/bootstrap/src/core/session.rs index d830fa2086386..a80df35b0d3c3 100644 --- a/src/bootstrap/src/core/session.rs +++ b/src/bootstrap/src/core/session.rs @@ -698,7 +698,7 @@ impl Session { { features.push(allocator_feature_name); } - if (self.config.llvm_enabled(target) || kind == Kind::Check) && check("llvm") { + if self.config.llvm_enabled(target) && check("llvm") { features.push("llvm"); } if self.config.llvm_offload { @@ -708,7 +708,7 @@ impl Session { if self.config.rust_randomize_layout && check("rustc_randomized_layouts") { features.push("rustc_randomized_layouts"); } - if self.config.compile_time_deps && kind == Kind::Check { + if self.config.compile_time_deps && kind.is_check_like() { features.push("check_only"); } From 9bff2d7f24b6678adb94fac0731551e04452fbe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Aug 2026 08:59:29 +0200 Subject: [PATCH 3/4] Stop using `rustc_cargo_env` for codegen backends Its environment variables don't seem to be used for the codegen backends. --- src/bootstrap/src/core/build_steps/check.rs | 5 +---- src/bootstrap/src/core/build_steps/compile.rs | 6 ++---- src/bootstrap/src/core/build_steps/test.rs | 2 -- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 45d84d533fe14..f4b0a718af7df 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -5,8 +5,7 @@ use std::path::{Path, PathBuf}; use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::compile::{ - ArtifactKeepMode, add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, - std_crates_for_make_run, + ArtifactKeepMode, add_to_sysroot, run_cargo, rustc_cargo, std_cargo, std_crates_for_make_run, }; use crate::core::build_steps::tool; use crate::core::build_steps::tool::{ @@ -582,7 +581,6 @@ impl CommandLineStep for CraneliftCodegenBackend { cargo .arg("--manifest-path") .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo, target); self.build_compiler.configure_cargo(&mut cargo); let _guard = builder.msg( @@ -665,7 +663,6 @@ impl CommandLineStep for GccCodegenBackend { ); cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo, target); self.build_compiler.configure_cargo(&mut cargo); let _guard = diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index c12257e9ba2bf..d1747e64ab781 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1318,7 +1318,7 @@ pub fn rustc_cargo( rustc_cargo_env(builder, cargo, target); } -pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) { +fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) { // Set some configuration variables picked up by build scripts and // the compiler alike cargo @@ -1432,7 +1432,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS /// Pass down configuration from the LLVM build into the build of /// rustc_llvm and rustc_codegen_llvm. /// -/// Note that this has the side-effect of _building LLVM_, which is sometimes +/// Note that calling this function has the side-effect of _building LLVM_, which is sometimes /// unwanted (e.g. for check builds). fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) { let llvm_output = builder.ensure(llvm::Llvm { target }); @@ -1730,7 +1730,6 @@ impl CommandLineStep for GccCodegenBackend { Kind::Build, ); cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo, host); let _guard = builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host); @@ -1801,7 +1800,6 @@ impl CommandLineStep for CraneliftCodegenBackend { cargo .arg("--manifest-path") .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo, target); let _guard = builder.msg( Kind::Build, diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 713d9a6426fc7..425f91a787f31 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -4418,7 +4418,6 @@ impl CommandLineStep for CodegenCranelift { cargo .arg("--manifest-path") .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml")); - compile::rustc_cargo_env(builder, &mut cargo, target); // Avoid incremental cache issues when changing rustc cargo.env("CARGO_BUILD_INCREMENTAL", "false"); @@ -4544,7 +4543,6 @@ impl CommandLineStep for CodegenGCC { cargo .arg("--manifest-path") .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml")); - compile::rustc_cargo_env(builder, &mut cargo, target); add_cg_gcc_cargo_flags(&mut cargo, &gcc); // Avoid incremental cache issues when changing rustc From 45f342d8ba8a85a6c2524ae8254dadbbed43ad93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Aug 2026 09:13:17 +0200 Subject: [PATCH 4/4] Bless bootstrap tests --- src/bootstrap/src/core/builder/tests.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 9d0a7aa466c9e..1f08ee9c11864 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -2541,9 +2541,8 @@ mod snapshot { ctx.config("doc") .path("compiler") .stage(1) - .render_steps(), @r" + .render_steps(), @" [build] rustdoc 0 - [build] llvm [doc] rustc 0 -> rustc 1 "); } @@ -2643,10 +2642,7 @@ mod snapshot { insta::assert_snapshot!( ctx.config("clippy") .path("compiler") - .render_steps(), @r" - [build] llvm - [clippy] rustc 0 -> rustc 1 - "); + .render_steps(), @"[clippy] rustc 0 -> rustc 1 "); } #[test] @@ -3024,10 +3020,7 @@ mod snapshot { #[test] fn fix_compiler() { let ctx = TestCtx::new(); - insta::assert_snapshot!(ctx.config("fix").path("compiler").render_steps(), @r" - [build] llvm - [fix] rustc 0 -> rustc 1 (77 crates) - "); + insta::assert_snapshot!(ctx.config("fix").path("compiler").render_steps(), @"[fix] rustc 0 -> rustc 1 (77 crates)"); } }