diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 59541bf12def0..95707e37018e9 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -19,7 +19,7 @@ use serde_derive::Deserialize; use tracing::{instrument, span}; use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; -use crate::core::build_steps::tool::{SourceType, copy_lld_artifacts}; +use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts}; use crate::core::build_steps::{dist, llvm}; use crate::core::builder; use crate::core::builder::{ @@ -1131,7 +1131,7 @@ impl Step for Rustc { cargo.env("RUSTC_BOLT_LINK_FLAGS", "1"); } - let _guard = builder.msg_sysroot_tool( + let _guard = builder.msg_rustc_tool( Kind::Build, build_compiler.stage, format_args!("compiler artifacts{}", crate_description(&self.crates)), @@ -1544,9 +1544,8 @@ impl Step for RustcLink { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CodegenBackend { - pub target: TargetSelection, - pub compiler: Compiler, - pub backend: CodegenBackendKind, + compilers: RustcPrivateCompilers, + backend: CodegenBackendKind, } fn needs_codegen_config(run: &RunConfig<'_>) -> bool { @@ -1610,8 +1609,11 @@ impl Step for CodegenBackend { } run.builder.ensure(CodegenBackend { - target: run.target, - compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), + compilers: RustcPrivateCompilers::new( + run.builder, + run.builder.top_stage, + run.target, + ), backend: backend.clone(), }); } @@ -1624,20 +1626,17 @@ impl Step for CodegenBackend { name = "CodegenBackend::run", skip_all, fields( - compiler = ?self.compiler, - target = ?self.target, - backend = ?self.target, + compilers = ?self.compilers, + backend = ?self.backend, ), ), )] fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; - let target = self.target; let backend = self.backend; + let target = self.compilers.target(); + let build_compiler = self.compilers.build_compiler(); - builder.ensure(Rustc::new(compiler, target)); - - if builder.config.keep_stage.contains(&compiler.stage) { + if builder.config.keep_stage.contains(&build_compiler.stage) { trace!("`keep-stage` requested"); builder.info( "WARNING: Using a potentially old codegen backend. \ @@ -1648,17 +1647,11 @@ impl Step for CodegenBackend { return; } - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - if compiler_to_use != compiler { - builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend }); - return; - } - - let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); + let out_dir = builder.cargo_out(build_compiler, Mode::Codegen, target); let mut cargo = builder::Cargo::new( builder, - compiler, + build_compiler, Mode::Codegen, SourceType::InTree, target, @@ -1679,8 +1672,13 @@ impl Step for CodegenBackend { let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp"); - let _guard = - builder.msg_build(compiler, format_args!("codegen backend {}", backend.name()), target); + let _guard = builder.msg_rustc_tool( + Kind::Build, + build_compiler.stage, + format_args!("codegen backend {}", backend.name()), + build_compiler.host, + target, + ); let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false); if builder.config.dry_run() { return; @@ -1700,10 +1698,17 @@ impl Step for CodegenBackend { f.display() ); } - let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend); + let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, &backend); let codegen_backend = codegen_backend.to_str().unwrap(); t!(stamp.add_stamp(codegen_backend).write()); } + + fn metadata(&self) -> Option { + Some( + StepMetadata::build(&self.backend.crate_name(), self.compilers.target()) + .built_by(self.compilers.build_compiler()), + ) + } } /// Creates the `codegen-backends` folder for a compiler that's about to be @@ -2190,8 +2195,10 @@ impl Step for Assemble { continue; } builder.ensure(CodegenBackend { - compiler: build_compiler, - target: target_compiler.host, + compilers: RustcPrivateCompilers::from_build_and_target_compiler( + build_compiler, + target_compiler, + ), backend: backend.clone(), }); } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 4699813abf42a..0465a071159ba 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -20,7 +20,7 @@ use object::read::archive::ArchiveFile; use tracing::instrument; use crate::core::build_steps::doc::DocumentationFormat; -use crate::core::build_steps::tool::{self, Tool}; +use crate::core::build_steps::tool::{self, RustcPrivateCompilers, Tool}; use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor}; use crate::core::build_steps::{compile, llvm}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata}; @@ -425,19 +425,20 @@ impl Step for Rustc { .as_ref() .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc")) { - let rustdoc = builder.rustdoc(compiler); + let rustdoc = builder.rustdoc_for_compiler(compiler); builder.install(&rustdoc, &image.join("bin"), FileType::Executable); } let ra_proc_macro_srv_compiler = builder.compiler_for(compiler.stage, builder.config.host_target, compiler.host); - builder.ensure(compile::Rustc::new(ra_proc_macro_srv_compiler, compiler.host)); + let compilers = RustcPrivateCompilers::from_build_compiler( + builder, + ra_proc_macro_srv_compiler, + compiler.host, + ); if let Some(ra_proc_macro_srv) = builder.ensure_if_default( - tool::RustAnalyzerProcMacroSrv { - compiler: ra_proc_macro_srv_compiler, - target: compiler.host, - }, + tool::RustAnalyzerProcMacroSrv::from_compilers(compilers), builder.kind, ) { let dst = image.join("libexec"); @@ -1172,7 +1173,7 @@ impl Step for PlainSourceTarball { #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] pub struct Cargo { - pub compiler: Compiler, + pub build_compiler: Compiler, pub target: TargetSelection, } @@ -1188,7 +1189,7 @@ impl Step for Cargo { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Cargo { - compiler: run.builder.compiler_for( + build_compiler: run.builder.compiler_for( run.builder.top_stage, run.builder.config.host_target, run.target, @@ -1198,12 +1199,10 @@ impl Step for Cargo { } fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; + let build_compiler = self.build_compiler; let target = self.target; - builder.ensure(compile::Rustc::new(compiler, target)); - - let cargo = builder.ensure(tool::Cargo { compiler, target }); + let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target)); let src = builder.src.join("src/tools/cargo"); let etc = src.join("src/etc"); @@ -1228,7 +1227,7 @@ impl Step for Cargo { #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] pub struct RustAnalyzer { - pub compiler: Compiler, + pub build_compiler: Compiler, pub target: TargetSelection, } @@ -1244,7 +1243,7 @@ impl Step for RustAnalyzer { fn make_run(run: RunConfig<'_>) { run.builder.ensure(RustAnalyzer { - compiler: run.builder.compiler_for( + build_compiler: run.builder.compiler_for( run.builder.top_stage, run.builder.config.host_target, run.target, @@ -1254,12 +1253,11 @@ impl Step for RustAnalyzer { } fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; let target = self.target; + let compilers = + RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target); - builder.ensure(compile::Rustc::new(compiler, target)); - - let rust_analyzer = builder.ensure(tool::RustAnalyzer { compiler, target }); + let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(compilers)); let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple); tarball.set_overlay(OverlayKind::RustAnalyzer); @@ -1270,9 +1268,9 @@ impl Step for RustAnalyzer { } } -#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Clippy { - pub compiler: Compiler, + pub build_compiler: Compiler, pub target: TargetSelection, } @@ -1288,7 +1286,7 @@ impl Step for Clippy { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Clippy { - compiler: run.builder.compiler_for( + build_compiler: run.builder.compiler_for( run.builder.top_stage, run.builder.config.host_target, run.target, @@ -1298,16 +1296,15 @@ impl Step for Clippy { } fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; let target = self.target; - - builder.ensure(compile::Rustc::new(compiler, target)); + let compilers = + RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target); // Prepare the image directory // We expect clippy to build, because we've exited this step above if tool // state for clippy isn't testing. - let clippy = builder.ensure(tool::Clippy { compiler, target }); - let cargoclippy = builder.ensure(tool::CargoClippy { compiler, target }); + let clippy = builder.ensure(tool::Clippy::from_compilers(compilers)); + let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(compilers)); let mut tarball = Tarball::new(builder, "clippy", &target.triple); tarball.set_overlay(OverlayKind::Clippy); @@ -1319,9 +1316,9 @@ impl Step for Clippy { } } -#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Miri { - pub compiler: Compiler, + pub build_compiler: Compiler, pub target: TargetSelection, } @@ -1337,7 +1334,7 @@ impl Step for Miri { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Miri { - compiler: run.builder.compiler_for( + build_compiler: run.builder.compiler_for( run.builder.top_stage, run.builder.config.host_target, run.target, @@ -1354,15 +1351,12 @@ impl Step for Miri { return None; } - let compiler = self.compiler; - let target = self.target; - - builder.ensure(compile::Rustc::new(compiler, target)); + let compilers = + RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target); + let miri = builder.ensure(tool::Miri::from_compilers(compilers)); + let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(compilers)); - let miri = builder.ensure(tool::Miri { compiler, target }); - let cargomiri = builder.ensure(tool::CargoMiri { compiler, target }); - - let mut tarball = Tarball::new(builder, "miri", &target.triple); + let mut tarball = Tarball::new(builder, "miri", &self.target.triple); tarball.set_overlay(OverlayKind::Miri); tarball.is_preview(true); tarball.add_file(&miri.tool_path, "bin", FileType::Executable); @@ -1466,9 +1460,9 @@ impl Step for CodegenBackend { } } -#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Rustfmt { - pub compiler: Compiler, + pub build_compiler: Compiler, pub target: TargetSelection, } @@ -1484,7 +1478,7 @@ impl Step for Rustfmt { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Rustfmt { - compiler: run.builder.compiler_for( + build_compiler: run.builder.compiler_for( run.builder.top_stage, run.builder.config.host_target, run.target, @@ -1494,14 +1488,13 @@ impl Step for Rustfmt { } fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; - let target = self.target; + let compilers = + RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target); - builder.ensure(compile::Rustc::new(compiler, target)); + let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(compilers)); + let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(compilers)); - let rustfmt = builder.ensure(tool::Rustfmt { compiler, target }); - let cargofmt = builder.ensure(tool::Cargofmt { compiler, target }); - let mut tarball = Tarball::new(builder, "rustfmt", &target.triple); + let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple); tarball.set_overlay(OverlayKind::Rustfmt); tarball.is_preview(true); tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable); @@ -1548,7 +1541,7 @@ impl Step for Extended { let mut built_tools = HashSet::new(); macro_rules! add_component { ($name:expr => $step:expr) => { - if let Some(tarball) = builder.ensure_if_default($step, Kind::Dist) { + if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) { tarballs.push(tarball); built_tools.insert($name); } @@ -1568,12 +1561,12 @@ impl Step for Extended { add_component!("rust-docs" => Docs { host: target }); add_component!("rust-json-docs" => JsonDocs { host: target }); - add_component!("cargo" => Cargo { compiler, target }); - add_component!("rustfmt" => Rustfmt { compiler, target }); - add_component!("rust-analyzer" => RustAnalyzer { compiler, target }); + add_component!("cargo" => Cargo { build_compiler: compiler, target }); + add_component!("rustfmt" => Rustfmt { build_compiler: compiler, target }); + add_component!("rust-analyzer" => RustAnalyzer { build_compiler: compiler, target }); add_component!("llvm-components" => LlvmTools { target }); - add_component!("clippy" => Clippy { compiler, target }); - add_component!("miri" => Miri { compiler, target }); + add_component!("clippy" => Clippy { build_compiler: compiler, target }); + add_component!("miri" => Miri { build_compiler: compiler, target }); add_component!("analysis" => Analysis { compiler, target }); add_component!("rustc-codegen-cranelift" => CodegenBackend { compiler: builder.compiler(stage, target), diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 37418f640aca6..d4539a0eb34d1 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -149,7 +149,7 @@ impl Step for RustbookSrc

{ let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); if let Some(compiler) = self.rustdoc_compiler { - let mut rustdoc = builder.rustdoc(compiler); + let mut rustdoc = builder.rustdoc_for_compiler(compiler); rustdoc.pop(); let old_path = env::var_os("PATH").unwrap_or_default(); let new_path = @@ -365,7 +365,7 @@ impl Step for Standalone { } let html = out.join(filename).with_extension("html"); - let rustdoc = builder.rustdoc(compiler); + let rustdoc = builder.rustdoc_for_compiler(compiler); if up_to_date(&path, &html) && up_to_date(&footer, &html) && up_to_date(&favicon, &html) @@ -463,7 +463,7 @@ impl Step for Releases { let html = out.join("releases.html"); let tmppath = out.join("releases.md"); let inpath = builder.src.join("RELEASES.md"); - let rustdoc = builder.rustdoc(compiler); + let rustdoc = builder.rustdoc_for_compiler(compiler); if !up_to_date(&inpath, &html) || !up_to_date(&footer, &html) || !up_to_date(&favicon, &html) @@ -811,7 +811,7 @@ impl Step for Rustc { let compiler = builder.compiler(stage, builder.config.host_target); builder.std(compiler, builder.config.host_target); - let _guard = builder.msg_sysroot_tool( + let _guard = builder.msg_rustc_tool( Kind::Doc, stage, format!("compiler{}", crate_description(&self.crates)), @@ -901,6 +901,10 @@ impl Step for Rustc { builder.open_in_browser(index); } } + + fn metadata(&self) -> Option { + Some(StepMetadata::doc("rustc", self.target).stage(self.stage)) + } } macro_rules! tool_doc { @@ -1018,6 +1022,10 @@ macro_rules! tool_doc { })? } } + + fn metadata(&self) -> Option { + Some(StepMetadata::doc(stringify!($tool), self.target)) + } } } } diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 4513a138e192a..f628330e9ed4d 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -215,13 +215,13 @@ install!((self, builder, _config), }; Cargo, alias = "cargo", Self::should_build(_config), only_hosts: true, { let tarball = builder - .ensure(dist::Cargo { compiler: self.compiler, target: self.target }) + .ensure(dist::Cargo { build_compiler: self.compiler, target: self.target }) .expect("missing cargo"); install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball); }; RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), only_hosts: true, { if let Some(tarball) = - builder.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target }) + builder.ensure(dist::RustAnalyzer { build_compiler: self.compiler, target: self.target }) { install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball); } else { @@ -232,12 +232,12 @@ install!((self, builder, _config), }; Clippy, alias = "clippy", Self::should_build(_config), only_hosts: true, { let tarball = builder - .ensure(dist::Clippy { compiler: self.compiler, target: self.target }) + .ensure(dist::Clippy { build_compiler: self.compiler, target: self.target }) .expect("missing clippy"); install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball); }; Miri, alias = "miri", Self::should_build(_config), only_hosts: true, { - if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) { + if let Some(tarball) = builder.ensure(dist::Miri { build_compiler: self.compiler, target: self.target }) { install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball); } else { // Miri is only available on nightly @@ -257,7 +257,7 @@ install!((self, builder, _config), }; Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, { if let Some(tarball) = builder.ensure(dist::Rustfmt { - compiler: self.compiler, + build_compiler: self.compiler, target: self.target }) { install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball); diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs index 4d61b38c876d0..108b7f90c149e 100644 --- a/src/bootstrap/src/core/build_steps/perf.rs +++ b/src/bootstrap/src/core/build_steps/perf.rs @@ -157,7 +157,7 @@ Consider setting `rust.debuginfo-level = 1` in `bootstrap.toml`."#); if let Some(opts) = args.cmd.shared_opts() && opts.profiles.contains(&Profile::Doc) { - builder.ensure(Rustdoc { compiler }); + builder.ensure(Rustdoc { target_compiler: compiler }); } let sysroot = builder.ensure(Sysroot::new(compiler)); diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index b2293fdd9b523..962dd372849d2 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -9,7 +9,7 @@ use clap_complete::{Generator, shells}; use crate::core::build_steps::dist::distdir; use crate::core::build_steps::test; -use crate::core::build_steps::tool::{self, SourceType, Tool}; +use crate::core::build_steps::tool::{self, RustcPrivateCompilers, SourceType, Tool}; use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; @@ -135,13 +135,13 @@ impl Step for Miri { } // This compiler runs on the host, we'll just use it for the target. - let target_compiler = builder.compiler(stage, target); - let miri_build = builder.ensure(tool::Miri { compiler: target_compiler, target }); - // Rustc tools are off by one stage, so use the build compiler to run miri. + let compilers = RustcPrivateCompilers::new(builder, stage, target); + let miri_build = builder.ensure(tool::Miri::from_compilers(compilers)); let host_compiler = miri_build.build_compiler; // Get a target sysroot for Miri. - let miri_sysroot = test::Miri::build_miri_sysroot(builder, target_compiler, target); + let miri_sysroot = + test::Miri::build_miri_sysroot(builder, compilers.target_compiler(), target); // # Run miri. // Running it via `cargo run` as that figures out the right dylib path. @@ -465,8 +465,8 @@ impl Step for Rustfmt { std::process::exit(1); } - let compiler = builder.compiler(stage, host); - let rustfmt_build = builder.ensure(tool::Rustfmt { compiler, target: host }); + let compilers = RustcPrivateCompilers::new(builder, stage, host); + let rustfmt_build = builder.ensure(tool::Rustfmt::from_compilers(compilers)); let mut rustfmt = tool::prepare_tool_cargo( builder, diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 119fa4237bcfe..1d5b1cea604e4 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -4,10 +4,12 @@ //! However, this contains ~all test parts we expect people to be able to build and run locally. use std::collections::HashSet; +use std::env::split_paths; use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; use std::{env, fs, iter}; +use build_helper::exit; #[cfg(feature = "tracing")] use tracing::instrument; @@ -17,7 +19,10 @@ use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; use crate::core::build_steps::llvm::get_llvm_version; use crate::core::build_steps::run::get_completion_paths; use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; -use crate::core::build_steps::tool::{self, COMPILETEST_ALLOW_FEATURES, SourceType, Tool}; +use crate::core::build_steps::tool::{ + self, COMPILETEST_ALLOW_FEATURES, RustcPrivateCompilers, SourceType, Tool, ToolTargetBuildMode, + get_tool_target_compiler, +}; use crate::core::build_steps::toolstate::ToolState; use crate::core::build_steps::{compile, dist, llvm}; use crate::core::builder::{ @@ -29,8 +34,8 @@ use crate::core::config::flags::{Subcommand, get_completion}; use crate::utils::build_stamp::{self, BuildStamp}; use crate::utils::exec::{BootstrapCommand, command}; use crate::utils::helpers::{ - self, LldThreads, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var, linker_args, - linker_flags, t, target_supports_cranelift_backend, up_to_date, + self, LldThreads, add_dylib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var, + linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date, }; use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests}; use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, debug, envify}; @@ -226,7 +231,7 @@ impl Step for HtmlCheck { /// order to test cargo. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Cargotest { - stage: u32, + build_compiler: Compiler, host: TargetSelection, } @@ -239,7 +244,19 @@ impl Step for Cargotest { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Cargotest { stage: run.builder.top_stage, host: run.target }); + if run.builder.top_stage == 0 { + eprintln!( + "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1." + ); + exit!(1); + } + // We want to build cargo stage N (where N == top_stage), and rustc stage N, + // and test both of these together. + // So we need to get a build compiler stage N-1 to build the stage N components. + run.builder.ensure(Cargotest { + build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target), + host: run.target, + }); } /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler. @@ -247,9 +264,19 @@ impl Step for Cargotest { /// This tool in `src/tools` will check out a few Rust projects and run `cargo /// test` to ensure that we don't regress the test suites there. fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(self.stage, self.host); - builder.ensure(compile::Rustc::new(compiler, compiler.host)); - let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host }); + // cargotest's staging has several pieces: + // consider ./x test cargotest --stage=2. + // + // The test goal is to exercise a (stage 2 cargo, stage 2 rustc) pair through a stage 2 + // cargotest tool. + // To produce the stage 2 cargo and cargotest, we need to do so with the stage 1 rustc and std. + // Importantly, the stage 2 rustc being tested (`tested_compiler`) via stage 2 cargotest is + // the rustc built by an earlier stage 1 rustc (the build_compiler). These are two different + // compilers! + let cargo = + builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host)); + let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host); + builder.std(tested_compiler, self.host); // Note that this is a short, cryptic, and not scoped directory name. This // is currently to minimize the length of path on Windows where we otherwise @@ -262,23 +289,28 @@ impl Step for Cargotest { cmd.arg(&cargo.tool_path) .arg(&out_dir) .args(builder.config.test_args()) - .env("RUSTC", builder.rustc(compiler)) - .env("RUSTDOC", builder.rustdoc(compiler)); + .env("RUSTC", builder.rustc(tested_compiler)) + .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler)); add_rustdoc_cargo_linker_args( &mut cmd, builder, - compiler.host, + tested_compiler.host, LldThreads::No, - compiler.stage, + tested_compiler.stage, ); cmd.delay_failure().run(builder); } + + fn metadata(&self) -> Option { + Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1)) + } } /// Runs `cargo test` for cargo itself. +/// We label these tests as "cargo self-tests". #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Cargo { - stage: u32, + build_compiler: Compiler, host: TargetSelection, } @@ -295,35 +327,33 @@ impl Step for Cargo { } fn make_run(run: RunConfig<'_>) { - // If stage is explicitly set or not lower than 2, keep it. Otherwise, make sure it's at least 2 - // as tests for this step don't work with a lower stage. - let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 { - run.builder.top_stage - } else { - 2 - }; - - run.builder.ensure(Cargo { stage, host: run.target }); + run.builder.ensure(Cargo { + build_compiler: get_tool_target_compiler( + run.builder, + ToolTargetBuildMode::Build(run.target), + ), + host: run.target, + }); } /// Runs `cargo test` for `cargo` packaged with Rust. fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - - if stage < 2 { - eprintln!("WARNING: cargo tests on stage {stage} may not behave well."); - eprintln!("HELP: consider using stage 2"); - } - - let compiler = builder.compiler(stage, self.host); - - let cargo = builder.ensure(tool::Cargo { compiler, target: self.host }); - let compiler = cargo.build_compiler; + // When we do a "stage 1 cargo self-test", it means that we test the stage 1 rustc + // using stage 1 cargo. So we actually build cargo using the stage 0 compiler, and then + // run its tests against the stage 1 compiler (called `tested_compiler` below). + builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host)); + + let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host); + builder.std(tested_compiler, self.host); + // We also need to build rustdoc for cargo tests + // It will be located in the bindir of `tested_compiler`, so we don't need to explicitly + // pass its path to Cargo. + builder.rustdoc_for_compiler(tested_compiler); let cargo = tool::prepare_tool_cargo( builder, - compiler, - Mode::ToolRustc, + self.build_compiler, + Mode::ToolTarget, self.host, Kind::Test, Self::CRATE_PATH, @@ -340,7 +370,25 @@ impl Step for Cargo { // Forcibly disable tests using nightly features since any changes to // those features won't be able to land. cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1"); - cargo.env("PATH", path_for_cargo(builder, compiler)); + + // Configure PATH to find the right rustc. NB. we have to use PATH + // and not RUSTC because the Cargo test suite has tests that will + // fail if rustc is not spelled `rustc`. + cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler)); + + // The `cargo` command configured above has dylib dir path set to the `build_compiler`'s + // libdir. That causes issues in cargo test, because the programs that cargo compiles are + // incorrectly picking that libdir, even though they should be picking the + // `tested_compiler`'s libdir. We thus have to override the precedence here. + let mut existing_dylib_paths = cargo + .get_envs() + .find(|(k, _)| *k == OsStr::new(dylib_path_var())) + .and_then(|(_, v)| v) + .map(|value| split_paths(value).collect::>()) + .unwrap_or_default(); + existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler)); + add_dylib_path(existing_dylib_paths, &mut cargo); + // Cargo's test suite uses `CARGO_RUSTC_CURRENT_DIR` to determine the path that `file!` is // relative to. Cargo no longer sets this env var, so we have to do that. This has to be the // same value as `-Zroot-dir`. @@ -352,7 +400,7 @@ impl Step for Cargo { crates: vec!["cargo".into()], target: self.host.triple.to_string(), host: self.host.triple.to_string(), - stage, + stage: self.build_compiler.stage + 1, }, builder, ); @@ -364,8 +412,7 @@ impl Step for Cargo { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RustAnalyzer { - stage: u32, - host: TargetSelection, + compilers: RustcPrivateCompilers, } impl Step for RustAnalyzer { @@ -378,19 +425,18 @@ impl Step for RustAnalyzer { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Self { stage: run.builder.top_stage, host: run.target }); + run.builder.ensure(Self { + compilers: RustcPrivateCompilers::new( + run.builder, + run.builder.top_stage, + run.builder.host_target, + ), + }); } /// Runs `cargo test` for rust-analyzer fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let host = self.host; - let compiler = builder.compiler(stage, host); - let compiler = tool::get_tool_rustc_compiler(builder, compiler); - - // We don't need to build the whole Rust Analyzer for the proc-macro-srv test suite, - // but we do need the standard library to be present. - builder.ensure(compile::Rustc::new(compiler, host)); + let host = self.compilers.target(); let workspace_path = "src/tools/rust-analyzer"; // until the whole RA test suite runs on `i686`, we only run @@ -398,7 +444,7 @@ impl Step for RustAnalyzer { let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv"; let mut cargo = tool::prepare_tool_cargo( builder, - compiler, + self.compilers.build_compiler(), Mode::ToolRustc, host, Kind::Test, @@ -425,8 +471,7 @@ impl Step for RustAnalyzer { /// Runs `cargo test` for rustfmt. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Rustfmt { - stage: u32, - host: TargetSelection, + compilers: RustcPrivateCompilers, } impl Step for Rustfmt { @@ -438,36 +483,39 @@ impl Step for Rustfmt { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Rustfmt { stage: run.builder.top_stage, host: run.target }); + run.builder.ensure(Rustfmt { + compilers: RustcPrivateCompilers::new( + run.builder, + run.builder.top_stage, + run.builder.host_target, + ), + }); } /// Runs `cargo test` for rustfmt. fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let host = self.host; - let compiler = builder.compiler(stage, host); - - let tool_result = builder.ensure(tool::Rustfmt { compiler, target: self.host }); - let compiler = tool_result.build_compiler; + let tool_result = builder.ensure(tool::Rustfmt::from_compilers(self.compilers)); + let build_compiler = tool_result.build_compiler; + let target = self.compilers.target(); let mut cargo = tool::prepare_tool_cargo( builder, - compiler, + build_compiler, Mode::ToolRustc, - host, + target, Kind::Test, "src/tools/rustfmt", SourceType::InTree, &[], ); - let dir = testdir(builder, compiler.host); + let dir = testdir(builder, target); t!(fs::create_dir_all(&dir)); cargo.env("RUSTFMT_TEST_DIR", dir); cargo.add_rustc_lib_path(builder); - run_cargo_test(cargo, &[], &[], "rustfmt", host, builder); + run_cargo_test(cargo, &[], &[], "rustfmt", target, builder); } } @@ -542,12 +590,14 @@ impl Step for Miri { } // This compiler runs on the host, we'll just use it for the target. - let target_compiler = builder.compiler(stage, host); + let compilers = RustcPrivateCompilers::new(builder, stage, host); // Build our tools. - let miri = builder.ensure(tool::Miri { compiler: target_compiler, target: host }); + let miri = builder.ensure(tool::Miri::from_compilers(compilers)); // the ui tests also assume cargo-miri has been built - builder.ensure(tool::CargoMiri { compiler: target_compiler, target: host }); + builder.ensure(tool::CargoMiri::from_compilers(compilers)); + + let target_compiler = compilers.target_compiler(); // We also need sysroots, for Miri and for the host (the latter for build scripts). // This is for the tests so everything is done with the target compiler. @@ -599,7 +649,7 @@ impl Step for Miri { cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg()); { - let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "miri", host, target); + let _guard = builder.msg_rustc_tool(Kind::Test, stage, "miri", host, target); let _time = helpers::timeit(builder); cargo.run(builder); } @@ -615,7 +665,7 @@ impl Step for Miri { cargo.args(["tests/pass", "tests/panic"]); { - let _guard = builder.msg_sysroot_tool( + let _guard = builder.msg_rustc_tool( Kind::Test, stage, "miri (mir-opt-level 4)", @@ -692,7 +742,7 @@ impl Step for CargoMiri { // Finally, run everything. let mut cargo = BootstrapCommand::from(cargo); { - let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "cargo-miri", host, target); + let _guard = builder.msg_rustc_tool(Kind::Test, stage, "cargo-miri", host, target); let _time = helpers::timeit(builder); cargo.run(builder); } @@ -756,7 +806,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Clippy { - host: TargetSelection, + compilers: RustcPrivateCompilers, } impl Step for Clippy { @@ -769,23 +819,30 @@ impl Step for Clippy { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Clippy { host: run.target }); + run.builder.ensure(Clippy { + compilers: RustcPrivateCompilers::new( + run.builder, + run.builder.top_stage, + run.builder.host_target, + ), + }); } /// Runs `cargo test` for clippy. fn run(self, builder: &Builder<'_>) { - let stage = builder.top_stage; - let host = self.host; + let host = self.compilers.target(); + // We need to carefully distinguish the compiler that builds clippy, and the compiler // that is linked into the clippy being tested. `target_compiler` is the latter, // and it must also be used by clippy's test runner to build tests and their dependencies. - let target_compiler = builder.compiler(stage, host); + let compilers = self.compilers; + let target_compiler = compilers.target_compiler(); - let tool_result = builder.ensure(tool::Clippy { compiler: target_compiler, target: host }); - let tool_compiler = tool_result.build_compiler; + let tool_result = builder.ensure(tool::Clippy::from_compilers(compilers)); + let build_compiler = tool_result.build_compiler; let mut cargo = tool::prepare_tool_cargo( builder, - tool_compiler, + build_compiler, Mode::ToolRustc, host, Kind::Test, @@ -794,9 +851,10 @@ impl Step for Clippy { &[], ); - cargo.env("RUSTC_TEST_SUITE", builder.rustc(tool_compiler)); - cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(tool_compiler)); - let host_libs = builder.stage_out(tool_compiler, Mode::ToolRustc).join(builder.cargo_dir()); + cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler)); + cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler)); + let host_libs = + builder.stage_out(build_compiler, Mode::ToolRustc).join(builder.cargo_dir()); cargo.env("HOST_LIBS", host_libs); // Build the standard library that the tests can use. @@ -825,8 +883,7 @@ impl Step for Clippy { cargo.add_rustc_lib_path(builder); let cargo = prepare_cargo_test(cargo, &[], &[], host, builder); - let _guard = - builder.msg_sysroot_tool(Kind::Test, tool_compiler.stage, "clippy", host, host); + let _guard = builder.msg_rustc_tool(Kind::Test, build_compiler.stage, "clippy", host, host); // Clippy reports errors if it blessed the outputs if cargo.allow_failure().run(builder) { @@ -840,10 +897,7 @@ impl Step for Clippy { } } -fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString { - // Configure PATH to find the right rustc. NB. we have to use PATH - // and not RUSTC because the Cargo test suite has tests that will - // fail if rustc is not spelled `rustc`. +fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString { let path = builder.sysroot(compiler).join("bin"); let old_path = env::var_os("PATH").unwrap_or_default(); env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") @@ -878,7 +932,7 @@ impl Step for RustdocTheme { .env("RUSTC_SYSROOT", builder.sysroot(self.compiler)) .env("RUSTDOC_LIBDIR", builder.sysroot_target_libdir(self.compiler, self.compiler.host)) .env("CFG_RELEASE_CHANNEL", &builder.config.channel) - .env("RUSTDOC_REAL", builder.rustdoc(self.compiler)) + .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.compiler)) .env("RUSTC_BOOTSTRAP", "1"); cmd.args(linker_args(builder, self.compiler.host, LldThreads::No, self.compiler.stage)); @@ -1037,7 +1091,11 @@ impl Step for RustdocGUI { let mut cmd = builder.tool_cmd(Tool::RustdocGUITest); let out_dir = builder.test_out(self.target).join("rustdoc-gui"); - build_stamp::clear_if_dirty(builder, &out_dir, &builder.rustdoc(self.compiler)); + build_stamp::clear_if_dirty( + builder, + &out_dir, + &builder.rustdoc_for_compiler(self.compiler), + ); if let Some(src) = builder.config.src.to_str() { cmd.arg("--rust-src").arg(src); @@ -1053,7 +1111,7 @@ impl Step for RustdocGUI { cmd.arg("--jobs").arg(builder.jobs().to_string()); - cmd.env("RUSTDOC", builder.rustdoc(self.compiler)) + cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.compiler)) .env("RUSTC", builder.rustc(self.compiler)); add_rustdoc_cargo_linker_args( @@ -1089,7 +1147,7 @@ impl Step for RustdocGUI { } let _time = helpers::timeit(builder); - let _guard = builder.msg_sysroot_tool( + let _guard = builder.msg_rustc_tool( Kind::Test, self.compiler.stage, "rustdoc-gui", @@ -1723,7 +1781,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // If we're using `--stage 0`, we should provide the bootstrap cargo. builder.initial_cargo.clone() } else { - builder.ensure(tool::Cargo { compiler, target: compiler.host }).tool_path + builder.ensure(tool::Cargo::from_build_compiler(compiler, compiler.host)).tool_path }; cmd.arg("--cargo-path").arg(cargo_path); @@ -1742,7 +1800,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the || mode == "rustdoc-json" || suite == "coverage-run-rustdoc" { - cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler)); + cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(compiler)); } if mode == "rustdoc-json" { @@ -2258,7 +2316,7 @@ impl BookTest { // mdbook just executes a binary named "rustdoc", so we need to update // PATH so that it points to our rustdoc. - let mut rustdoc_path = builder.rustdoc(compiler); + let mut rustdoc_path = builder.rustdoc_for_compiler(compiler); rustdoc_path.pop(); let old_path = env::var_os("PATH").unwrap_or_default(); let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path))) @@ -2581,7 +2639,7 @@ fn run_cargo_test<'a>( let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder); let _time = helpers::timeit(builder); let _group = description.into().and_then(|what| { - builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target) + builder.msg_rustc_tool(Kind::Test, compiler.stage, what, compiler.host, target) }); #[cfg(feature = "build-metrics")] diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index f5fa33b98f3bf..e3f49fa126ed8 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -71,13 +71,9 @@ impl Builder<'_> { ) -> Option { match mode { // depends on compiler stage, different to host compiler - Mode::ToolRustc => self.msg_sysroot_tool( - kind, - build_stage, - format_args!("tool {tool}"), - *host, - *target, - ), + Mode::ToolRustc => { + self.msg_rustc_tool(kind, build_stage, format_args!("tool {tool}"), *host, *target) + } // doesn't depend on compiler, same as host compiler _ => self.msg(kind, build_stage, format_args!("tool {tool}"), *host, *target), } @@ -90,11 +86,8 @@ impl Builder<'_> { pub struct ToolBuildResult { /// Artifact path of the corresponding tool that was built. pub tool_path: PathBuf, - /// Compiler used to build the tool. For non-`ToolRustc` tools this is equal to `target_compiler`. - /// For `ToolRustc` this is one stage before of the `target_compiler`. + /// Compiler used to build the tool. pub build_compiler: Compiler, - /// Target compiler passed to `Step`. - pub target_compiler: Compiler, } impl Step for ToolBuild { @@ -108,22 +101,15 @@ impl Step for ToolBuild { /// /// This will build the specified tool with the specified `host` compiler in /// `stage` into the normal cargo output directory. - fn run(mut self, builder: &Builder<'_>) -> ToolBuildResult { + fn run(self, builder: &Builder<'_>) -> ToolBuildResult { let target = self.target; let mut tool = self.tool; let path = self.path; - let target_compiler = self.build_compiler; - self.build_compiler = if self.mode == Mode::ToolRustc { - get_tool_rustc_compiler(builder, self.build_compiler) - } else { - self.build_compiler - }; - match self.mode { Mode::ToolRustc => { - // If compiler was forced, its artifacts should have been prepared earlier. - if !self.build_compiler.is_forced_compiler() { + // FIXME: remove this, it's only needed for download-rustc... + if !self.build_compiler.is_forced_compiler() && builder.download_rustc() { builder.std(self.build_compiler, self.build_compiler.host); builder.ensure(compile::Rustc::new(self.build_compiler, target)); } @@ -184,8 +170,7 @@ impl Step for ToolBuild { Kind::Build, self.mode, self.tool, - // A stage N tool is built with the stage N-1 compiler. - self.build_compiler.stage + 1, + self.build_compiler.stage, &self.build_compiler.host, &self.target, ); @@ -216,7 +201,7 @@ impl Step for ToolBuild { .join(format!("lib{tool}.rlib")), }; - ToolBuildResult { tool_path, build_compiler: self.build_compiler, target_compiler } + ToolBuildResult { tool_path, build_compiler: self.build_compiler } } } } @@ -346,27 +331,6 @@ pub fn prepare_tool_cargo( cargo } -/// Handle stage-off logic for `ToolRustc` tools when necessary. -pub(crate) fn get_tool_rustc_compiler( - builder: &Builder<'_>, - target_compiler: Compiler, -) -> Compiler { - if target_compiler.is_forced_compiler() { - return target_compiler; - } - - if builder.download_rustc() && target_compiler.stage == 1 { - // We shouldn't drop to stage0 compiler when using CI rustc. - return builder.compiler(1, builder.config.host_target); - } - - // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise - // we'd have stageN/bin/rustc and stageN/bin/$rustc_tool be effectively different stage - // compilers, which isn't what we want. Rustc tools should be linked in the same way as the - // compiler it's paired with, so it must be built with the previous stage compiler. - builder.compiler(target_compiler.stage.saturating_sub(1), builder.config.host_target) -} - /// Determines how to build a `ToolTarget`, i.e. which compiler should be used to compile it. /// The compiler stage is automatically bumped if we need to cross-compile a stage 1 tool. pub enum ToolTargetBuildMode { @@ -719,15 +683,21 @@ impl Step for RemoteTestServer { } } -#[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] +/// Represents `Rustdoc` that either comes from the external stage0 sysroot or that is built +/// locally. +/// Rustdoc is special, because it both essentially corresponds to a `Compiler` (that can be +/// externally provided), but also to a `ToolRustc` tool. +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Rustdoc { - /// This should only ever be 0 or 2. - /// We sometimes want to reference the "bootstrap" rustdoc, which is why this option is here. - pub compiler: Compiler, + /// If the stage of `target_compiler` is `0`, then rustdoc is externally provided. + /// Otherwise it is built locally. + pub target_compiler: Compiler, } impl Step for Rustdoc { - type Output = ToolBuildResult; + /// Path to the built rustdoc binary. + type Output = PathBuf; + const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -736,26 +706,25 @@ impl Step for Rustdoc { } fn make_run(run: RunConfig<'_>) { - run.builder - .ensure(Rustdoc { compiler: run.builder.compiler(run.builder.top_stage, run.target) }); + run.builder.ensure(Rustdoc { + target_compiler: run.builder.compiler(run.builder.top_stage, run.target), + }); } - fn run(self, builder: &Builder<'_>) -> ToolBuildResult { - let target_compiler = self.compiler; + fn run(self, builder: &Builder<'_>) -> Self::Output { + let target_compiler = self.target_compiler; let target = target_compiler.host; + // If stage is 0, we use a prebuilt rustdoc from stage0 if target_compiler.stage == 0 { if !target_compiler.is_snapshot(builder) { panic!("rustdoc in stage 0 must be snapshot rustdoc"); } - return ToolBuildResult { - tool_path: builder.initial_rustdoc.clone(), - build_compiler: target_compiler, - target_compiler, - }; + return builder.initial_rustdoc.clone(); } + // If stage is higher, we build rustdoc instead let bin_rustdoc = || { let sysroot = builder.sysroot(target_compiler); let bindir = sysroot.join("bin"); @@ -767,10 +736,7 @@ impl Step for Rustdoc { // If CI rustc is enabled and we haven't modified the rustdoc sources, // use the precompiled rustdoc from CI rustc's sysroot to speed up bootstrapping. - if builder.download_rustc() - && target_compiler.stage > 0 - && builder.rust_info().is_managed_git_subrepository() - { + if builder.download_rustc() && builder.rust_info().is_managed_git_subrepository() { let files_to_track = &["src/librustdoc", "src/tools/rustdoc", "src/rustdoc-json-types"]; // Check if unchanged @@ -783,12 +749,7 @@ impl Step for Rustdoc { let bin_rustdoc = bin_rustdoc(); builder.copy_link(&precompiled_rustdoc, &bin_rustdoc, FileType::Executable); - - return ToolBuildResult { - tool_path: bin_rustdoc, - build_compiler: target_compiler, - target_compiler, - }; + return bin_rustdoc; } } @@ -804,9 +765,10 @@ impl Step for Rustdoc { extra_features.push("jemalloc".to_string()); } - let ToolBuildResult { tool_path, build_compiler, target_compiler } = - builder.ensure(ToolBuild { - build_compiler: target_compiler, + let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler); + let tool_path = builder + .ensure(ToolBuild { + build_compiler: compilers.build_compiler, target, // Cargo adds a number of paths to the dylib search path on windows, which results in // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool" @@ -819,38 +781,41 @@ impl Step for Rustdoc { allow_features: "", cargo_args: Vec::new(), artifact_kind: ToolArtifactKind::Binary, - }); - - // don't create a stage0-sysroot/bin directory. - if target_compiler.stage > 0 { - if builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None { - // Due to LTO a lot of debug info from C++ dependencies such as jemalloc can make it into - // our final binaries - compile::strip_debug(builder, target, &tool_path); - } - let bin_rustdoc = bin_rustdoc(); - builder.copy_link(&tool_path, &bin_rustdoc, FileType::Executable); - ToolBuildResult { tool_path: bin_rustdoc, build_compiler, target_compiler } - } else { - ToolBuildResult { tool_path, build_compiler, target_compiler } + }) + .tool_path; + + if builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None { + // Due to LTO a lot of debug info from C++ dependencies such as jemalloc can make it into + // our final binaries + compile::strip_debug(builder, target, &tool_path); } + let bin_rustdoc = bin_rustdoc(); + builder.copy_link(&tool_path, &bin_rustdoc, FileType::Executable); + bin_rustdoc } fn metadata(&self) -> Option { Some( - StepMetadata::build("rustdoc", self.compiler.host) - // rustdoc is ToolRustc, so stage N rustdoc is built by stage N-1 rustc - // FIXME: make this stage deduction automatic somehow - // FIXME: log the compiler that actually built ToolRustc steps - .stage(self.compiler.stage.saturating_sub(1)), + StepMetadata::build("rustdoc", self.target_compiler.host) + .stage(self.target_compiler.stage), ) } } +/// Builds the cargo tool. +/// Note that it can be built using a stable compiler. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Cargo { - pub compiler: Compiler, - pub target: TargetSelection, + build_compiler: Compiler, + target: TargetSelection, +} + +impl Cargo { + /// Returns `Cargo` that will be **compiled** by the passed compiler, for the given + /// `target`. + pub fn from_build_compiler(build_compiler: Compiler, target: TargetSelection) -> Self { + Self { build_compiler, target } + } } impl Step for Cargo { @@ -865,7 +830,10 @@ impl Step for Cargo { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Cargo { - compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target), + build_compiler: get_tool_target_compiler( + run.builder, + ToolTargetBuildMode::Build(run.target), + ), target: run.target, }); } @@ -873,19 +841,28 @@ impl Step for Cargo { fn run(self, builder: &Builder<'_>) -> ToolBuildResult { builder.build.require_submodule("src/tools/cargo", None); + builder.std(self.build_compiler, self.target); builder.ensure(ToolBuild { - build_compiler: self.compiler, + build_compiler: self.build_compiler, target: self.target, tool: "cargo", - mode: Mode::ToolRustc, + mode: Mode::ToolTarget, path: "src/tools/cargo", source_type: SourceType::Submodule, extra_features: Vec::new(), - allow_features: "", + // Cargo is compilable with a stable compiler, but since we run in bootstrap, + // with RUSTC_BOOTSTRAP being set, some "clever" build scripts enable specialization + // based on this, which breaks stuff. We thus have to explicitly allow these features + // here. + allow_features: "min_specialization,specialization", cargo_args: Vec::new(), artifact_kind: ToolArtifactKind::Binary, }) } + + fn metadata(&self) -> Option { + Some(StepMetadata::build("cargo", self.target).built_by(self.build_compiler)) + } } /// Represents a built LldWrapper, the `lld-wrapper` tool itself, and a directory @@ -1066,8 +1043,13 @@ impl Step for WasmComponentLd { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustAnalyzer { - pub compiler: Compiler, - pub target: TargetSelection, + compilers: RustcPrivateCompilers, +} + +impl RustAnalyzer { + pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self { + Self { compilers } + } } impl RustAnalyzer { @@ -1086,15 +1068,16 @@ impl Step for RustAnalyzer { fn make_run(run: RunConfig<'_>) { run.builder.ensure(RustAnalyzer { - compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target), - target: run.target, + compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), }); } fn run(self, builder: &Builder<'_>) -> ToolBuildResult { + let build_compiler = self.compilers.build_compiler; + let target = self.compilers.target(); builder.ensure(ToolBuild { - build_compiler: self.compiler, - target: self.target, + build_compiler, + target, tool: "rust-analyzer", mode: Mode::ToolRustc, path: "src/tools/rust-analyzer", @@ -1105,16 +1088,29 @@ impl Step for RustAnalyzer { artifact_kind: ToolArtifactKind::Binary, }) } + + fn metadata(&self) -> Option { + Some( + StepMetadata::build("rust-analyzer", self.compilers.target()) + .built_by(self.compilers.build_compiler), + ) + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustAnalyzerProcMacroSrv { - pub compiler: Compiler, - pub target: TargetSelection, + compilers: RustcPrivateCompilers, +} + +impl RustAnalyzerProcMacroSrv { + pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self { + Self { compilers } + } } impl Step for RustAnalyzerProcMacroSrv { - type Output = Option; + type Output = ToolBuildResult; + const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -1131,15 +1127,14 @@ impl Step for RustAnalyzerProcMacroSrv { fn make_run(run: RunConfig<'_>) { run.builder.ensure(RustAnalyzerProcMacroSrv { - compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target), - target: run.target, + compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), }); } - fn run(self, builder: &Builder<'_>) -> Option { + fn run(self, builder: &Builder<'_>) -> Self::Output { let tool_result = builder.ensure(ToolBuild { - build_compiler: self.compiler, - target: self.target, + build_compiler: self.compilers.build_compiler, + target: self.compilers.target(), tool: "rust-analyzer-proc-macro-srv", mode: Mode::ToolRustc, path: "src/tools/rust-analyzer/crates/proc-macro-srv-cli", @@ -1152,7 +1147,7 @@ impl Step for RustAnalyzerProcMacroSrv { // Copy `rust-analyzer-proc-macro-srv` to `/libexec/` // so that r-a can use it. - let libexec_path = builder.sysroot(self.compiler).join("libexec"); + let libexec_path = builder.sysroot(self.compilers.target_compiler).join("libexec"); t!(fs::create_dir_all(&libexec_path)); builder.copy_link( &tool_result.tool_path, @@ -1160,7 +1155,14 @@ impl Step for RustAnalyzerProcMacroSrv { FileType::Executable, ); - Some(tool_result) + tool_result + } + + fn metadata(&self) -> Option { + Some( + StepMetadata::build("rust-analyzer-proc-macro-srv", self.compilers.target()) + .built_by(self.compilers.build_compiler), + ) } } @@ -1302,7 +1304,92 @@ impl Step for LibcxxVersionTool { } } -macro_rules! tool_extended { +/// Represents which compilers are involved in the compilation of a tool +/// that depends on compiler internals (`rustc_private`). +/// Their compilation looks like this: +/// +/// - `build_compiler` (stage N-1) builds `target_compiler` (stage N) to produce .rlibs +/// - These .rlibs are copied into the sysroot of `build_compiler` +/// - `build_compiler` (stage N-1) builds `` (stage N) +/// - `` links to .rlibs from `target_compiler` +/// +/// Eventually, this could also be used for .rmetas and check builds, but so far we only deal with +/// normal builds here. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct RustcPrivateCompilers { + /// Compiler that builds the tool and that builds `target_compiler`. + build_compiler: Compiler, + /// Compiler to which .rlib artifacts the tool links to. + /// The host target of this compiler corresponds to the target of the tool. + target_compiler: Compiler, +} + +impl RustcPrivateCompilers { + /// Create compilers for a `rustc_private` tool with the given `stage` and for the given + /// `target`. + pub fn new(builder: &Builder<'_>, stage: u32, target: TargetSelection) -> Self { + let build_compiler = Self::build_compiler_from_stage(builder, stage); + + // This is the compiler we'll link to + // FIXME: make 100% sure that `target_compiler` was indeed built with `build_compiler`... + let target_compiler = builder.compiler(build_compiler.stage + 1, target); + + Self { build_compiler, target_compiler } + } + + pub fn from_build_and_target_compiler( + build_compiler: Compiler, + target_compiler: Compiler, + ) -> Self { + Self { build_compiler, target_compiler } + } + + /// Create rustc tool compilers from the build compiler. + pub fn from_build_compiler( + builder: &Builder<'_>, + build_compiler: Compiler, + target: TargetSelection, + ) -> Self { + let target_compiler = builder.compiler(build_compiler.stage + 1, target); + Self { build_compiler, target_compiler } + } + + /// Create rustc tool compilers from the target compiler. + pub fn from_target_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self { + Self { + build_compiler: Self::build_compiler_from_stage(builder, target_compiler.stage), + target_compiler, + } + } + + fn build_compiler_from_stage(builder: &Builder<'_>, stage: u32) -> Compiler { + assert!(stage > 0); + + if builder.download_rustc() && stage == 1 { + // We shouldn't drop to stage0 compiler when using CI rustc. + builder.compiler(1, builder.config.host_target) + } else { + builder.compiler(stage - 1, builder.config.host_target) + } + } + + pub fn build_compiler(&self) -> Compiler { + self.build_compiler + } + + pub fn target_compiler(&self) -> Compiler { + self.target_compiler + } + + /// Target of the tool being compiled + pub fn target(&self) -> TargetSelection { + self.target_compiler.host + } +} + +/// Creates a step that builds an extended `Mode::ToolRustc` tool +/// and installs it into the sysroot of a corresponding compiler. +macro_rules! tool_rustc_extended { ( $name:ident { path: $path:expr, @@ -1316,8 +1403,15 @@ macro_rules! tool_extended { ) => { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct $name { - pub compiler: Compiler, - pub target: TargetSelection, + compilers: RustcPrivateCompilers, + } + + impl $name { + pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self { + Self { + compilers, + } + } } impl Step for $name { @@ -1326,7 +1420,7 @@ macro_rules! tool_extended { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - should_run_tool_build_step( + should_run_extended_rustc_tool( run, $tool_name, $path, @@ -1336,17 +1430,15 @@ macro_rules! tool_extended { fn make_run(run: RunConfig<'_>) { run.builder.ensure($name { - compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target), - target: run.target, + compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), }); } fn run(self, builder: &Builder<'_>) -> ToolBuildResult { - let Self { compiler, target } = self; - run_tool_build_step( + let Self { compilers } = self; + build_extended_rustc_tool( builder, - compiler, - target, + compilers, $tool_name, $path, None $( .or(Some(&$add_bins_to_sysroot)) )?, @@ -1356,18 +1448,16 @@ macro_rules! tool_extended { } fn metadata(&self) -> Option { - // FIXME: refactor extended tool steps to make the build_compiler explicit, - // it is offset by one now for rustc tools Some( - StepMetadata::build($tool_name, self.target) - .built_by(self.compiler.with_stage(self.compiler.stage.saturating_sub(1))) + StepMetadata::build($tool_name, self.compilers.target()) + .built_by(self.compilers.build_compiler) ) } } } } -fn should_run_tool_build_step<'a>( +fn should_run_extended_rustc_tool<'a>( run: ShouldRun<'a>, tool_name: &'static str, path: &'static str, @@ -1391,39 +1481,38 @@ fn should_run_tool_build_step<'a>( ) } -#[expect(clippy::too_many_arguments)] // silence overeager clippy lint -fn run_tool_build_step( +fn build_extended_rustc_tool( builder: &Builder<'_>, - compiler: Compiler, - target: TargetSelection, + compilers: RustcPrivateCompilers, tool_name: &'static str, path: &'static str, add_bins_to_sysroot: Option<&[&str]>, add_features: Option, TargetSelection, &mut Vec)>, cargo_args: Option<&[&'static str]>, ) -> ToolBuildResult { + let target = compilers.target(); let mut extra_features = Vec::new(); if let Some(func) = add_features { func(builder, target, &mut extra_features); } - let ToolBuildResult { tool_path, build_compiler, target_compiler } = - builder.ensure(ToolBuild { - build_compiler: compiler, - target, - tool: tool_name, - mode: Mode::ToolRustc, - path, - extra_features, - source_type: SourceType::InTree, - allow_features: "", - cargo_args: cargo_args.unwrap_or_default().iter().map(|s| String::from(*s)).collect(), - artifact_kind: ToolArtifactKind::Binary, - }); - + let build_compiler = compilers.build_compiler; + let ToolBuildResult { tool_path, .. } = builder.ensure(ToolBuild { + build_compiler, + target, + tool: tool_name, + mode: Mode::ToolRustc, + path, + extra_features, + source_type: SourceType::InTree, + allow_features: "", + cargo_args: cargo_args.unwrap_or_default().iter().map(|s| String::from(*s)).collect(), + artifact_kind: ToolArtifactKind::Binary, + }); + + let target_compiler = compilers.target_compiler; if let Some(add_bins_to_sysroot) = add_bins_to_sysroot && !add_bins_to_sysroot.is_empty() - && target_compiler.stage > 0 { let bindir = builder.sysroot(target_compiler).join("bin"); t!(fs::create_dir_all(&bindir)); @@ -1435,25 +1524,25 @@ fn run_tool_build_step( // Return a path into the bin dir. let path = bindir.join(exe(tool_name, target_compiler.host)); - ToolBuildResult { tool_path: path, build_compiler, target_compiler } + ToolBuildResult { tool_path: path, build_compiler } } else { - ToolBuildResult { tool_path, build_compiler, target_compiler } + ToolBuildResult { tool_path, build_compiler } } } -tool_extended!(Cargofmt { +tool_rustc_extended!(Cargofmt { path: "src/tools/rustfmt", tool_name: "cargo-fmt", stable: true, add_bins_to_sysroot: ["cargo-fmt"] }); -tool_extended!(CargoClippy { +tool_rustc_extended!(CargoClippy { path: "src/tools/clippy", tool_name: "cargo-clippy", stable: true, add_bins_to_sysroot: ["cargo-clippy"] }); -tool_extended!(Clippy { +tool_rustc_extended!(Clippy { path: "src/tools/clippy", tool_name: "clippy-driver", stable: true, @@ -1464,7 +1553,7 @@ tool_extended!(Clippy { } } }); -tool_extended!(Miri { +tool_rustc_extended!(Miri { path: "src/tools/miri", tool_name: "miri", stable: false, @@ -1472,13 +1561,13 @@ tool_extended!(Miri { // Always compile also tests when building miri. Otherwise feature unification can cause rebuilds between building and testing miri. cargo_args: &["--all-targets"], }); -tool_extended!(CargoMiri { +tool_rustc_extended!(CargoMiri { path: "src/tools/miri/cargo-miri", tool_name: "cargo-miri", stable: false, add_bins_to_sysroot: ["cargo-miri"] }); -tool_extended!(Rustfmt { +tool_rustc_extended!(Rustfmt { path: "src/tools/rustfmt", tool_name: "rustfmt", stable: true, diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 6b3236ef47ef6..1d0c9da694f01 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -508,7 +508,7 @@ impl Builder<'_> { } _ => panic!("doc mode {mode:?} not expected"), }; - let rustdoc = self.rustdoc(compiler); + let rustdoc = self.rustdoc_for_compiler(compiler); build_stamp::clear_if_dirty(self, &my_out, &rustdoc); } @@ -822,7 +822,7 @@ impl Builder<'_> { } let rustdoc_path = match cmd_kind { - Kind::Doc | Kind::Test | Kind::MiriTest => self.rustdoc(compiler), + Kind::Doc | Kind::Test | Kind::MiriTest => self.rustdoc_for_compiler(compiler), _ => PathBuf::from("/path/to/nowhere/rustdoc/not/required"), }; diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 96289a63785e2..98deb66030267 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -16,6 +16,7 @@ use tracing::instrument; pub use self::cargo::{Cargo, cargo_profile_var}; pub use crate::Compiler; use crate::core::build_steps::compile::{Std, StdLink}; +use crate::core::build_steps::tool::RustcPrivateCompilers; use crate::core::build_steps::{ check, clean, clippy, compile, dist, doc, gcc, install, llvm, run, setup, test, tool, vendor, }; @@ -1535,8 +1536,11 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s .map(|entry| entry.path()) } - pub fn rustdoc(&self, compiler: Compiler) -> PathBuf { - self.ensure(tool::Rustdoc { compiler }).tool_path + /// Returns a path to `Rustdoc` that "belongs" to the `target_compiler`. + /// It can be either a stage0 rustdoc or a locally built rustdoc that *links* to + /// `target_compiler`. + pub fn rustdoc_for_compiler(&self, target_compiler: Compiler) -> PathBuf { + self.ensure(tool::Rustdoc { target_compiler }) } pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { @@ -1552,10 +1556,13 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s return cmd; } - let _ = - self.ensure(tool::Clippy { compiler: run_compiler, target: self.build.host_target }); - let cargo_clippy = self - .ensure(tool::CargoClippy { compiler: run_compiler, target: self.build.host_target }); + // FIXME: double check that `run_compiler`'s stage is what we want to use + let compilers = + RustcPrivateCompilers::new(self, run_compiler.stage, self.build.host_target); + assert_eq!(run_compiler, compilers.target_compiler()); + + let _ = self.ensure(tool::Clippy::from_compilers(compilers)); + let cargo_clippy = self.ensure(tool::CargoClippy::from_compilers(compilers)); let mut dylib_path = helpers::dylib_path(); dylib_path.insert(0, self.sysroot(run_compiler).join("lib")); @@ -1567,11 +1574,14 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { assert!(run_compiler.stage > 0, "miri can not be invoked at stage 0"); + + let compilers = + RustcPrivateCompilers::new(self, run_compiler.stage, self.build.host_target); + assert_eq!(run_compiler, compilers.target_compiler()); + // Prepare the tools - let miri = - self.ensure(tool::Miri { compiler: run_compiler, target: self.build.host_target }); - let cargo_miri = - self.ensure(tool::CargoMiri { compiler: run_compiler, target: self.build.host_target }); + let miri = self.ensure(tool::Miri::from_compilers(compilers)); + let cargo_miri = self.ensure(tool::CargoMiri::from_compilers(compilers)); // Invoke cargo-miri, make sure it can find miri and cargo. let mut cmd = command(cargo_miri.tool_path); cmd.env("MIRI", &miri.tool_path); @@ -1596,7 +1606,7 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s // equivalently to rustc. .env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)) .env("CFG_RELEASE_CHANNEL", &self.config.channel) - .env("RUSTDOC_REAL", self.rustdoc(compiler)) + .env("RUSTDOC_REAL", self.rustdoc_for_compiler(compiler)) .env("RUSTC_BOOTSTRAP", "1"); cmd.arg("-Wrustdoc::invalid_codeblock_attributes"); @@ -1705,11 +1715,11 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s /// Ensure that a given step is built *only if it's supposed to be built by default*, returning /// its output. This will cache the step, so it's safe (and good!) to call this as often as /// needed to ensure that all dependencies are build. - pub(crate) fn ensure_if_default>>( + pub(crate) fn ensure_if_default>( &'a self, step: S, kind: Kind, - ) -> S::Output { + ) -> Option { let desc = StepDescription::from::(kind); let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind)); @@ -1721,7 +1731,7 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s } // Only execute if it's supposed to run as default - if desc.default && should_run.is_really_default() { self.ensure(step) } else { None } + if desc.default && should_run.is_really_default() { Some(self.ensure(step)) } else { None } } /// Checks if any of the "should_run" paths is in the `Builder` paths. diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index f012645b7ef5c..139ddc9ed2496 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -279,13 +279,6 @@ mod defaults { first(cache.all::()), &[tool::ErrorIndex { compiler: Compiler::new(1, a) }] ); - // docs should be built with the stage0 compiler, not with the stage0 artifacts. - // recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to, - // not the one it was built by. - assert_eq!( - first(cache.all::()), - &[tool::Rustdoc { compiler: Compiler::new(1, a) },] - ); } } @@ -337,12 +330,6 @@ mod dist { first(builder.cache.all::()), &[tool::ErrorIndex { compiler: Compiler::new(1, a) }] ); - // This is actually stage 1, but Rustdoc::run swaps out the compiler with - // stage minus 1 if --stage is not 0. Very confusing! - assert_eq!( - first(builder.cache.all::()), - &[tool::Rustdoc { compiler: Compiler::new(2, a) },] - ); } } @@ -569,36 +556,6 @@ fn test_is_builder_target() { } } -#[test] -fn test_get_tool_rustc_compiler() { - let mut config = configure("build", &[], &[]); - config.download_rustc_commit = None; - let build = Build::new(config); - let builder = Builder::new(&build); - - let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1); - - let compiler = Compiler::new(2, target_triple_1); - let expected = Compiler::new(1, target_triple_1); - let actual = tool::get_tool_rustc_compiler(&builder, compiler); - assert_eq!(expected, actual); - - let compiler = Compiler::new(1, target_triple_1); - let expected = Compiler::new(0, target_triple_1); - let actual = tool::get_tool_rustc_compiler(&builder, compiler); - assert_eq!(expected, actual); - - let mut config = configure("build", &[], &[]); - config.download_rustc_commit = Some("".to_owned()); - let build = Build::new(config); - let builder = Builder::new(&build); - - let compiler = Compiler::new(1, target_triple_1); - let expected = Compiler::new(1, target_triple_1); - let actual = tool::get_tool_rustc_compiler(&builder, compiler); - assert_eq!(expected, actual); -} - /// When bootstrap detects a step dependency cycle (which is a bug), its panic /// message should show the actual steps on the stack, not just several copies /// of `Any { .. }`. @@ -657,7 +614,7 @@ mod snapshot { [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 - [build] rustdoc 0 + [build] rustdoc 1 "); } @@ -680,10 +637,10 @@ mod snapshot { [build] rustc 2 -> std 2 [build] rustc 1 -> std 1 [build] rustc 2 -> std 2 - [build] rustdoc 1 + [build] rustdoc 2 [build] llvm [build] rustc 1 -> rustc 2 - [build] rustdoc 1 + [build] rustdoc 2 "); } @@ -762,6 +719,23 @@ mod snapshot { "); } + #[test] + fn build_compiler_codegen_backend() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("build") + .args(&["--set", "rust.codegen-backends=['llvm', 'cranelift']"]) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> rustc_codegen_cranelift 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + " + ); + } + #[test] fn build_compiler_tools() { let ctx = TestCtx::new(); @@ -780,7 +754,7 @@ mod snapshot { [build] rustc 1 -> LldWrapper 2 [build] rustc 1 -> LlvmBitcodeLinker 2 [build] rustc 2 -> std 2 - [build] rustdoc 1 + [build] rustdoc 2 " ); } @@ -809,7 +783,7 @@ mod snapshot { [build] rustc 1 -> rustc 2 [build] rustc 1 -> LldWrapper 2 [build] rustc 1 -> LlvmBitcodeLinker 2 - [build] rustdoc 1 + [build] rustdoc 2 " ); } @@ -998,7 +972,7 @@ mod snapshot { .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 - [build] rustdoc 0 + [build] rustdoc 1 [doc] std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] "); } @@ -1026,6 +1000,15 @@ mod snapshot { "); } + #[test] + fn build_cargo() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("build") + .paths(&["cargo"]) + .render_steps(), @"[build] rustc 0 -> cargo 1 "); + } + #[test] fn dist_default_stage() { let ctx = TestCtx::new(); @@ -1047,7 +1030,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 - [build] rustdoc 1 + [build] rustdoc 2 [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 @@ -1089,7 +1072,7 @@ mod snapshot { [build] rustc 1 -> LldWrapper 2 [build] rustc 1 -> WasmComponentLd 2 [build] rustc 1 -> LlvmBitcodeLinker 2 - [build] rustdoc 1 + [build] rustdoc 2 [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 @@ -1097,16 +1080,19 @@ mod snapshot { [dist] docs [doc] std 2 crates=[] [dist] mingw + [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 [build] rustc 0 -> GenerateCopyright 1 [dist] rustc [dist] rustc 1 -> std 1 [dist] src <> - [build] rustc 0 -> rustfmt 1 - [build] rustc 0 -> cargo-fmt 1 - [build] rustc 0 -> clippy-driver 1 - [build] rustc 0 -> cargo-clippy 1 - [build] rustc 0 -> miri 1 - [build] rustc 0 -> cargo-miri 1 + [build] rustc 1 -> cargo 2 + [build] rustc 1 -> rust-analyzer 2 + [build] rustc 1 -> rustfmt 2 + [build] rustc 1 -> cargo-fmt 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [build] rustc 1 -> miri 2 + [build] rustc 1 -> cargo-miri 2 "); } @@ -1125,7 +1111,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 - [build] rustdoc 1 + [build] rustdoc 2 [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 2 -> std 2 @@ -1162,7 +1148,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 - [build] rustdoc 1 + [build] rustdoc 2 [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 @@ -1176,7 +1162,7 @@ mod snapshot { [dist] rustc [build] llvm [build] rustc 1 -> rustc 2 - [build] rustdoc 1 + [build] rustdoc 2 [dist] rustc [dist] rustc 1 -> std 1 [dist] src <> @@ -1199,7 +1185,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 - [build] rustdoc 1 + [build] rustdoc 2 [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 2 -> std 2 @@ -1217,7 +1203,7 @@ mod snapshot { [dist] rustc [build] llvm [build] rustc 1 -> rustc 2 - [build] rustdoc 1 + [build] rustdoc 2 [dist] rustc [dist] rustc 1 -> std 1 [dist] rustc 1 -> std 1 @@ -1241,7 +1227,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 - [build] rustdoc 1 + [build] rustdoc 2 [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> RustInstaller 1 @@ -1273,7 +1259,7 @@ mod snapshot { [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 [build] rustc 1 -> WasmComponentLd 2 - [build] rustdoc 1 + [build] rustdoc 2 [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 1 -> std 1 @@ -1286,17 +1272,20 @@ mod snapshot { [build] llvm [build] rustc 1 -> rustc 2 [build] rustc 1 -> WasmComponentLd 2 - [build] rustdoc 1 + [build] rustdoc 2 + [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 [build] rustc 0 -> GenerateCopyright 1 [dist] rustc [dist] rustc 1 -> std 1 [dist] src <> - [build] rustc 0 -> rustfmt 1 - [build] rustc 0 -> cargo-fmt 1 - [build] rustc 0 -> clippy-driver 1 - [build] rustc 0 -> cargo-clippy 1 - [build] rustc 0 -> miri 1 - [build] rustc 0 -> cargo-miri 1 + [build] rustc 1 -> cargo 2 + [build] rustc 1 -> rust-analyzer 2 + [build] rustc 1 -> rustfmt 2 + [build] rustc 1 -> cargo-fmt 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [build] rustc 1 -> miri 2 + [build] rustc 1 -> cargo-miri 2 [build] rustc 1 -> LlvmBitcodeLinker 2 "); } @@ -1610,6 +1599,58 @@ mod snapshot { steps.assert_contains_fuzzy(StepMetadata::build("rustc", host)); } + #[test] + fn test_cargo_stage_1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .path("cargo") + .render_steps(), @r" + [build] rustc 0 -> cargo 1 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [build] rustdoc 0 + "); + } + + #[test] + fn test_cargo_stage_2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .path("cargo") + .stage(2) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> cargo 2 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustdoc 2 + [build] rustdoc 1 + "); + } + + #[test] + fn test_cargotest() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .path("cargotest") + .render_steps(), @r" + [build] rustc 0 -> cargo 1 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> CargoTest 1 + [build] rustdoc 1 + [test] cargotest 1 + "); + } + #[test] fn doc_library() { let ctx = TestCtx::new(); @@ -1619,7 +1660,7 @@ mod snapshot { .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 - [build] rustdoc 0 + [build] rustdoc 1 [doc] std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] "); } @@ -1633,7 +1674,7 @@ mod snapshot { .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 - [build] rustdoc 0 + [build] rustdoc 1 [doc] std 1 crates=[core] "); } @@ -1648,7 +1689,7 @@ mod snapshot { .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 - [build] rustdoc 0 + [build] rustdoc 1 [doc] std 1 crates=[core] "); } @@ -1678,7 +1719,7 @@ mod snapshot { .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 - [build] rustdoc 0 + [build] rustdoc 1 [doc] std 1 crates=[alloc,core] "); } @@ -1694,10 +1735,105 @@ mod snapshot { .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 - [build] rustdoc 0 + [build] rustdoc 1 [doc] std 1 crates=[alloc,core] "); } + + #[test] + fn doc_compiler_stage_0() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("compiler") + .stage(0) + .render_steps(), @r" + [build] rustdoc 0 + [build] llvm + [doc] rustc 0 + "); + } + + #[test] + fn doc_compiler_stage_1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("compiler") + .stage(1) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] rustc 1 + "); + } + + #[test] + fn doc_compiler_stage_2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("compiler") + .stage(2) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustdoc 2 + [doc] rustc 2 + "); + } + + #[test] + fn doc_compiletest_stage_0() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("src/tools/compiletest") + .stage(0) + .render_steps(), @r" + [build] rustdoc 0 + [doc] Compiletest + "); + } + + #[test] + fn doc_compiletest_stage_1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("src/tools/compiletest") + .stage(1) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] Compiletest + "); + } + + #[test] + fn doc_compiletest_stage_2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("src/tools/compiletest") + .stage(2) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustdoc 2 + [doc] Compiletest + "); + } } struct ExecutedSteps { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 011b52df97bbd..69546e923d0d4 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1100,17 +1100,6 @@ impl Build { self.msg(Kind::Doc, compiler.stage, what, compiler.host, target.into()) } - #[must_use = "Groups should not be dropped until the Step finishes running"] - #[track_caller] - fn msg_build( - &self, - compiler: Compiler, - what: impl Display, - target: impl Into>, - ) -> Option { - self.msg(Kind::Build, compiler.stage, what, compiler.host, target) - } - /// Return a `Group` guard for a [`Step`] that is built for each `--stage`. /// /// [`Step`]: crate::core::builder::Step @@ -1157,20 +1146,21 @@ impl Build { #[must_use = "Groups should not be dropped until the Step finishes running"] #[track_caller] - fn msg_sysroot_tool( + fn msg_rustc_tool( &self, action: impl Into, - stage: u32, + build_stage: u32, what: impl Display, host: TargetSelection, target: TargetSelection, ) -> Option { let action = action.into().description(); let msg = |fmt| format!("{action} {what} {fmt}"); + let msg = if host == target { - msg(format_args!("(stage{stage} -> stage{}, {target})", stage + 1)) + msg(format_args!("(stage{build_stage} -> stage{}, {target})", build_stage + 1)) } else { - msg(format_args!("(stage{stage}:{host} -> stage{}:{target})", stage + 1)) + msg(format_args!("(stage{build_stage}:{host} -> stage{}:{target})", build_stage + 1)) }; self.group(&msg) }