From 8c281613739436582f979d228be4cc1d4f7afa3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 17 Jun 2025 16:09:30 +0200 Subject: [PATCH 1/3] Add `get_host_target` function --- src/bootstrap/src/core/config/config.rs | 4 ++-- src/bootstrap/src/utils/helpers.rs | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index ff0fda2d2e698..d3393afcae05a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -49,7 +49,7 @@ use crate::core::download::is_download_ci_available; use crate::utils::channel; use crate::utils::exec::command; use crate::utils::execution_context::ExecutionContext; -use crate::utils::helpers::exe; +use crate::utils::helpers::{exe, get_host_target}; use crate::{GitInfo, OnceLock, TargetSelection, check_ci_llvm, helpers, t}; /// Each path in this list is considered "allowed" in the `download-rustc="if-unchanged"` logic. @@ -349,7 +349,7 @@ impl Config { stderr_is_tty: std::io::stderr().is_terminal(), // set by build.rs - host_target: TargetSelection::from_user(env!("BUILD_TRIPLE")), + host_target: get_host_target(), src: { let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 2f18fb6031829..3c5f612daa7d4 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -178,6 +178,11 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result< } } +/// Return the host target on which we are currently running. +pub fn get_host_target() -> TargetSelection { + TargetSelection::from_user(env!("BUILD_TRIPLE")) +} + /// Rename a file if from and to are in the same filesystem or /// copy and remove the file otherwise pub fn move_file, Q: AsRef>(from: P, to: Q) -> io::Result<()> { From 21d21d5f81d6d0ac7e58275e40e982550951ec86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 17 Jun 2025 16:16:46 +0200 Subject: [PATCH 2/3] Normalize host target in snapshot tests --- src/bootstrap/src/core/builder/tests.rs | 48 ++++++++++++++++--------- src/bootstrap/src/utils/tests/mod.rs | 43 ++++++++++++++++++++++ 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 6268a2b59d6cc..f45afe0c789c2 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -9,6 +9,7 @@ use crate::Flags; use crate::core::build_steps::doc::DocumentationFormat; use crate::core::config::Config; use crate::utils::cache::ExecutedStep; +use crate::utils::helpers::get_host_target; use crate::utils::tests::git::{GitCtx, git_test}; static TEST_TRIPLE_1: &str = "i686-unknown-haiku"; @@ -1236,24 +1237,38 @@ fn any_debug() { /// The staging tests use insta for snapshot testing. /// See bootstrap's README on how to bless the snapshots. mod staging { + use crate::Build; + use crate::core::builder::Builder; use crate::core::builder::tests::{ TEST_TRIPLE_1, configure, configure_with_args, render_steps, run_build, }; + use crate::utils::tests::ConfigBuilder; #[test] fn build_compiler_stage_1() { - let mut cache = run_build( - &["compiler".into()], - configure_with_args(&["build", "--stage", "1"], &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]), - ); - let steps = cache.into_executed_steps(); - insta::assert_snapshot!(render_steps(&steps), @r" - [build] rustc 0 -> std 0 - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> rustc 1 + insta::assert_snapshot!( + ConfigBuilder::build() + .path("compiler") + .stage(1) + .get_steps(), @r" + [build] rustc 0 -> std 0 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> rustc 1 "); } + + impl ConfigBuilder { + fn get_steps(self) -> String { + let config = self.create_config(); + + let kind = config.cmd.kind(); + let build = Build::new(config); + let builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(kind), &builder.paths); + render_steps(&builder.cache.into_executed_steps()) + } + } } /// Renders the executed bootstrap steps for usage in snapshot tests with insta. @@ -1275,18 +1290,17 @@ fn render_steps(steps: &[ExecutedStep]) -> String { } let stage = if let Some(stage) = metadata.stage { format!("{stage} ") } else { "".to_string() }; - write!(record, "{} {stage}<{}>", metadata.name, metadata.target); + write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target)); Some(record) }) - .map(|line| { - line.replace(TEST_TRIPLE_1, "target1") - .replace(TEST_TRIPLE_2, "target2") - .replace(TEST_TRIPLE_3, "target3") - }) .collect::>() .join("\n") } +fn normalize_target(target: TargetSelection) -> String { + target.to_string().replace(&get_host_target().to_string(), "host") +} + fn render_compiler(compiler: Compiler) -> String { - format!("rustc {} <{}>", compiler.stage, compiler.host) + format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host)) } diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs index 73c500f6e3691..ec6293f3c2c19 100644 --- a/src/bootstrap/src/utils/tests/mod.rs +++ b/src/bootstrap/src/utils/tests/mod.rs @@ -1,3 +1,46 @@ //! This module contains shared utilities for bootstrap tests. +use crate::core::builder::Builder; +use crate::core::config::DryRun; +use crate::{Build, Config, Flags}; + pub mod git; + +/// Used to configure an invocation of bootstrap. +/// Currently runs in the rustc checkout, long-term it should be switched +/// to run in a (cache-primed) temporary directory instead. +pub struct ConfigBuilder { + args: Vec, +} + +impl ConfigBuilder { + pub fn from_args(args: &[&str]) -> Self { + Self::new(args) + } + + pub fn build() -> Self { + Self::new(&["build"]) + } + + pub fn path(mut self, path: &str) -> Self { + self.args.push(path.to_string()); + self + } + + pub fn stage(mut self, stage: u32) -> Self { + self.args.push("--stage".to_string()); + self.args.push(stage.to_string()); + self + } + + fn new(args: &[&str]) -> Self { + Self { args: args.iter().copied().map(String::from).collect() } + } + + pub fn create_config(mut self) -> Config { + let mut config = Config::parse(Flags::parse(&self.args)); + // Run in dry-check, otherwise the test would be too slow + config.set_dry_run(DryRun::SelfCheck); + config + } +} From 718e475cb12094cb182a8271b1855d8f1663dc3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 18 Jun 2025 13:14:16 +0200 Subject: [PATCH 3/3] Clarify arrow in snapshot tests --- src/bootstrap/src/core/builder/tests.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index f45afe0c789c2..1d1c315c1cfdb 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1274,6 +1274,10 @@ mod staging { /// Renders the executed bootstrap steps for usage in snapshot tests with insta. /// Only renders certain important steps. /// Each value in `steps` should be a tuple of (Step, step output). +/// +/// The arrow in the rendered output (`X -> Y`) means `X builds Y`. +/// This is similar to the output printed by bootstrap to stdout, but here it is +/// generated purely for the purpose of tests. fn render_steps(steps: &[ExecutedStep]) -> String { steps .iter()