diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 6ca32aca345eb..8cad5b920b913 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -96,10 +96,36 @@ impl Std { } deps } + + /// Returns true if the standard library will be uplifted from stage 1 for the given + /// `build_compiler` (which determines the stdlib stage) and `target`. + /// + /// Uplifting is enabled if we're building a stage2+ libstd, full bootstrap is + /// disabled and we have a stage1 libstd already compiled for the given target. + pub fn should_be_uplifted_from_stage_1( + builder: &Builder<'_>, + stage: u32, + target: TargetSelection, + ) -> bool { + stage > 1 + && !builder.config.full_bootstrap + // This estimates if a stage1 libstd exists for the given target. If we're not + // cross-compiling, it should definitely exist by the time we're building a stage2 + // libstd. + // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that + // rustc needs to link to a cross-compiled libstd, so again we should have a stage1 + // libstd for the given target prepared. + // Even if we guess wrong in the cross-compiled case, the worst that should happen is + // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we + // don't pay the libstd build cost twice. + && (target == builder.host_target || builder.config.hosts.contains(&target)) + } } impl Step for Std { - type Output = (); + /// Build stamp of std, if it was indeed built or uplifted. + type Output = Option; + const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -136,7 +162,7 @@ impl Step for Std { /// This will build the standard library for a particular stage of the build /// using the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. - fn run(self, builder: &Builder<'_>) { + fn run(self, builder: &Builder<'_>) -> Self::Output { let target = self.target; // We already have std ready to be used for stage 0. @@ -144,7 +170,7 @@ impl Step for Std { let compiler = self.build_compiler; builder.ensure(StdLink::from_std(self, compiler)); - return; + return None; } let build_compiler = if builder.download_rustc() && self.force_recompile { @@ -169,7 +195,7 @@ impl Step for Std { &sysroot, builder.config.ci_rust_std_contents(), ); - return; + return None; } if builder.config.keep_stage.contains(&build_compiler.stage) @@ -185,7 +211,7 @@ impl Step for Std { self.copy_extra_objects(builder, &build_compiler, target); builder.ensure(StdLink::from_std(self, build_compiler)); - return; + return Some(build_stamp::libstd_stamp(builder, build_compiler, target)); } let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target }); @@ -193,24 +219,9 @@ impl Step for Std { // Stage of the stdlib that we're building let stage = build_compiler.stage; - // If we're building a stage2+ libstd, full bootstrap is - // disabled and we have a stage1 libstd already compiled for the given target, - // then simply uplift a previously built stage1 library. - if build_compiler.stage > 1 - && !builder.config.full_bootstrap - // This estimates if a stage1 libstd exists for the given target. If we're not - // cross-compiling, it should definitely exist by the time we're building a stage2 - // libstd. - // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that - // rustc needs to link to a cross-compiled libstd, so again we should have a stage1 - // libstd for the given target prepared. - // Even if we guess wrong in the cross-compiled case, the worst that should happen is - // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we - // don't pay the libstd build cost twice. - && (target == builder.host_target || builder.config.hosts.contains(&target)) - { + if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage, target) { let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target); - builder.std(build_compiler_for_std_to_uplift, target); + let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target); let msg = if build_compiler_for_std_to_uplift.host == target { format!( @@ -231,7 +242,7 @@ impl Step for Std { self.copy_extra_objects(builder, &build_compiler, target); builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift)); - return; + return stage_1_stamp; } target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target)); @@ -284,11 +295,13 @@ impl Step for Std { build_compiler, target, ); + + let stamp = build_stamp::libstd_stamp(builder, build_compiler, target); run_cargo( builder, cargo, vec![], - &build_stamp::libstd_stamp(builder, build_compiler, target), + &stamp, target_deps, self.is_for_mir_opt_tests, // is_check false, @@ -298,6 +311,7 @@ impl Step for Std { self, builder.compiler(build_compiler.stage, builder.config.host_target), )); + Some(stamp) } fn metadata(&self) -> Option { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index daac75c03e2d7..3c322256cf277 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -21,7 +21,9 @@ use tracing::instrument; use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name}; use crate::core::build_steps::doc::DocumentationFormat; -use crate::core::build_steps::tool::{self, RustcPrivateCompilers, Tool}; +use crate::core::build_steps::tool::{ + self, RustcPrivateCompilers, Tool, ToolTargetBuildMode, get_tool_target_compiler, +}; 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}; @@ -75,7 +77,10 @@ impl Step for Docs { /// Builds the `rust-docs` installer component. fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - builder.default_doc(&[]); + // FIXME: explicitly enumerate the steps that should be executed here, and gather their + // documentation, rather than running all default steps and then read their output + // from a shared directory. + builder.run_default_doc_steps(); let dest = "share/doc/rust/html"; @@ -132,13 +137,20 @@ impl Step for JsonDocs { } } +/// Builds the `rustc-docs` installer component. +/// Apart from the documentation of the `rustc_*` crates, it also includes the documentation of +/// various in-tree helper tools (bootstrap, build_helper, tidy), +/// and also rustc_private tools like rustdoc, clippy, miri or rustfmt. +/// +/// It is currently hosted at . #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustcDocs { - pub host: TargetSelection, + target: TargetSelection, } impl Step for RustcDocs { - type Output = Option; + type Output = GeneratedTarball; + const DEFAULT: bool = true; const IS_HOST: bool = true; @@ -148,18 +160,17 @@ impl Step for RustcDocs { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustcDocs { host: run.target }); + run.builder.ensure(RustcDocs { target: run.target }); } - /// Builds the `rustc-docs` installer component. - fn run(self, builder: &Builder<'_>) -> Option { - let host = self.host; - builder.default_doc(&[]); + fn run(self, builder: &Builder<'_>) -> Self::Output { + let target = self.target; + builder.run_default_doc_steps(); - let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple); + let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple); tarball.set_product_name("Rustc Documentation"); - tarball.add_bulk_dir(builder.compiler_doc_out(host), "share/doc/rust/html/rustc"); - Some(tarball.generate()) + tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc"); + tarball.generate() } } @@ -354,9 +365,13 @@ fn get_cc_search_dirs( (bin_path, lib_path) } +/// Builds the `rust-mingw` installer component. +/// +/// This contains all the bits and pieces to run the MinGW Windows targets +/// without any extra installed software (e.g., we bundle gcc, libraries, etc.). #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Mingw { - pub host: TargetSelection, + target: TargetSelection, } impl Step for Mingw { @@ -368,39 +383,46 @@ impl Step for Mingw { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Mingw { host: run.target }); + run.builder.ensure(Mingw { target: run.target }); } - /// Builds the `rust-mingw` installer component. - /// - /// This contains all the bits and pieces to run the MinGW Windows targets - /// without any extra installed software (e.g., we bundle gcc, libraries, etc). fn run(self, builder: &Builder<'_>) -> Option { - let host = self.host; - if !host.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker { + let target = self.target; + if !target.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker { return None; } - let mut tarball = Tarball::new(builder, "rust-mingw", &host.triple); + let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple); tarball.set_product_name("Rust MinGW"); - make_win_dist(tarball.image_dir(), host, builder); + make_win_dist(tarball.image_dir(), target, builder); Some(tarball.generate()) } fn metadata(&self) -> Option { - Some(StepMetadata::dist("mingw", self.host)) + Some(StepMetadata::dist("mingw", self.target)) } } +/// Creates the `rustc` installer component. +/// +/// This includes: +/// - The compiler and LLVM. +/// - Debugger scripts. +/// - Various helper tools, e.g. LLD or Rust Analyzer proc-macro server (if enabled). +/// - The licenses of all code used by the compiler. +/// +/// It does not include any standard library. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Rustc { - pub compiler: Compiler, + /// This is the compiler that we will *ship* in this dist step. + pub target_compiler: Compiler, } impl Step for Rustc { type Output = GeneratedTarball; + const DEFAULT: bool = true; const IS_HOST: bool = true; @@ -409,19 +431,19 @@ impl Step for Rustc { } fn make_run(run: RunConfig<'_>) { - run.builder - .ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.target) }); + run.builder.ensure(Rustc { + target_compiler: run.builder.compiler(run.builder.top_stage, run.target), + }); } - /// Creates the `rustc` installer component. fn run(self, builder: &Builder<'_>) -> GeneratedTarball { - let compiler = self.compiler; - let host = self.compiler.host; + let target_compiler = self.target_compiler; + let target = self.target_compiler.host; - let tarball = Tarball::new(builder, "rustc", &host.triple); + let tarball = Tarball::new(builder, "rustc", &target.triple); // Prepare the rustc "image", what will actually end up getting installed - prepare_image(builder, compiler, tarball.image_dir()); + prepare_image(builder, target_compiler, tarball.image_dir()); // On MinGW we've got a few runtime DLL dependencies that we need to // include. @@ -430,16 +452,16 @@ impl Step for Rustc { // anything requiring us to distribute a license, but it's likely the // install will *also* include the rust-mingw package, which also needs // licenses, so to be safe we just include it here in all MinGW packages. - if host.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker { - runtime_dll_dist(tarball.image_dir(), host, builder); + if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker { + runtime_dll_dist(tarball.image_dir(), target, builder); tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc"); } return tarball.generate(); - fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) { - let host = compiler.host; - let src = builder.sysroot(compiler); + fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) { + let target = target_compiler.host; + let src = builder.sysroot(target_compiler); // Copy rustc binary t!(fs::create_dir_all(image.join("bin"))); @@ -452,17 +474,11 @@ impl Step for Rustc { .as_ref() .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc")) { - let rustdoc = builder.rustdoc_for_compiler(compiler); + let rustdoc = builder.rustdoc_for_compiler(target_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); - let compilers = RustcPrivateCompilers::from_build_compiler( - builder, - ra_proc_macro_srv_compiler, - compiler.host, - ); + let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler); if let Some(ra_proc_macro_srv) = builder.ensure_if_default( tool::RustAnalyzerProcMacroSrv::from_compilers(compilers), @@ -472,11 +488,11 @@ impl Step for Rustc { builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable); } - let libdir_relative = builder.libdir_relative(compiler); + let libdir_relative = builder.libdir_relative(target_compiler); // Copy runtime DLLs needed by the compiler if libdir_relative.to_str() != Some("bin") { - let libdir = builder.rustc_libdir(compiler); + let libdir = builder.rustc_libdir(target_compiler); for entry in builder.read_dir(&libdir) { // A safeguard that we will not ship libgccjit.so from the libdir, in case the // GCC codegen backend is enabled by default. @@ -503,15 +519,15 @@ impl Step for Rustc { // components like the llvm tools and LLD. LLD is included below and // tools/LLDB come later, so let's just throw it in the rustc // component for now. - maybe_install_llvm_runtime(builder, host, image); + maybe_install_llvm_runtime(builder, target, image); - let dst_dir = image.join("lib/rustlib").join(host).join("bin"); + let dst_dir = image.join("lib/rustlib").join(target).join("bin"); t!(fs::create_dir_all(&dst_dir)); // Copy over lld if it's there if builder.config.lld_enabled { - let src_dir = builder.sysroot_target_bindir(compiler, host); - let rust_lld = exe("rust-lld", compiler.host); + let src_dir = builder.sysroot_target_bindir(target_compiler, target); + let rust_lld = exe("rust-lld", target_compiler.host); builder.copy_link( &src_dir.join(&rust_lld), &dst_dir.join(&rust_lld), @@ -521,7 +537,7 @@ impl Step for Rustc { let self_contained_lld_dst_dir = dst_dir.join("gcc-ld"); t!(fs::create_dir(&self_contained_lld_dst_dir)); for name in crate::LLD_FILE_NAMES { - let exe_name = exe(name, compiler.host); + let exe_name = exe(name, target_compiler.host); builder.copy_link( &self_contained_lld_src_dir.join(&exe_name), &self_contained_lld_dst_dir.join(&exe_name), @@ -530,10 +546,12 @@ impl Step for Rustc { } } - if builder.config.llvm_enabled(compiler.host) && builder.config.llvm_tools_enabled { - let src_dir = builder.sysroot_target_bindir(compiler, host); - let llvm_objcopy = exe("llvm-objcopy", compiler.host); - let rust_objcopy = exe("rust-objcopy", compiler.host); + if builder.config.llvm_enabled(target_compiler.host) + && builder.config.llvm_tools_enabled + { + let src_dir = builder.sysroot_target_bindir(target_compiler, target); + let llvm_objcopy = exe("llvm-objcopy", target_compiler.host); + let rust_objcopy = exe("rust-objcopy", target_compiler.host); builder.copy_link( &src_dir.join(&llvm_objcopy), &dst_dir.join(&rust_objcopy), @@ -542,8 +560,8 @@ impl Step for Rustc { } if builder.tool_enabled("wasm-component-ld") { - let src_dir = builder.sysroot_target_bindir(compiler, host); - let ld = exe("wasm-component-ld", compiler.host); + let src_dir = builder.sysroot_target_bindir(target_compiler, target); + let ld = exe("wasm-component-ld", target_compiler.host); builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable); } @@ -564,7 +582,7 @@ impl Step for Rustc { } // Debugger scripts - builder.ensure(DebuggerScripts { sysroot: image.to_owned(), host }); + builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target }); // HTML copyright files let file_list = builder.ensure(super::run::GenerateCopyright); @@ -590,14 +608,16 @@ impl Step for Rustc { } fn metadata(&self) -> Option { - Some(StepMetadata::dist("rustc", self.compiler.host)) + Some(StepMetadata::dist("rustc", self.target_compiler.host)) } } +/// Copies debugger scripts for `target` into the given compiler `sysroot`. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct DebuggerScripts { + /// Sysroot of a compiler into which will the debugger scripts be copied to. pub sysroot: PathBuf, - pub host: TargetSelection, + pub target: TargetSelection, } impl Step for DebuggerScripts { @@ -607,16 +627,15 @@ impl Step for DebuggerScripts { run.never() } - /// Copies debugger scripts for `target` into the `sysroot` specified. fn run(self, builder: &Builder<'_>) { - let host = self.host; + let target = self.target; let sysroot = self.sysroot; let dst = sysroot.join("lib/rustlib/etc"); t!(fs::create_dir_all(&dst)); let cp_debugger_script = |file: &str| { builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular); }; - if host.contains("windows-msvc") { + if target.contains("windows-msvc") { // windbg debugger scripts builder.install( &builder.src.join("src/etc/rust-windbg.cmd"), @@ -730,12 +749,28 @@ fn copy_target_libs( } } +/// Builds the standard library (`rust-std`) dist component for a given `target`. +/// This includes the standard library dynamic library file (e.g. .so/.dll), along with stdlib +/// .rlibs. +/// +/// Note that due to uplifting, we actually ship the stage 1 library +/// (built using the stage1 compiler) even with a stage 2 dist, unless `full-bootstrap` is enabled. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Std { - pub compiler: Compiler, + /// Compiler that will build the standard library. + pub build_compiler: Compiler, pub target: TargetSelection, } +impl Std { + pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self { + Std { + build_compiler: builder.compiler(builder.top_stage, builder.config.host_target), + target, + } + } +} + impl Step for Std { type Output = Option; const DEFAULT: bool = true; @@ -745,31 +780,25 @@ impl Step for Std { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Std { - compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, - ), - target: run.target, - }); + run.builder.ensure(Std::new(run.builder, run.target)); } fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; + let build_compiler = self.build_compiler; let target = self.target; - if skip_host_target_lib(builder, compiler) { + if skip_host_target_lib(builder, build_compiler) { return None; } - builder.std(compiler, target); + // It's possible that std was uplifted and thus built with a different build compiler + // So we need to read the stamp that was actually generated when std was built + let stamp = + builder.std(build_compiler, target).expect("Standard library has to be built for dist"); let mut tarball = Tarball::new(builder, "rust-std", &target.triple); tarball.include_target_in_component_name(true); - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - let stamp = build_stamp::libstd_stamp(builder, compiler_to_use, target); verify_uefi_rlib_format(builder, target, &stamp); copy_target_libs(builder, target, tarball.image_dir(), &stamp); @@ -777,7 +806,7 @@ impl Step for Std { } fn metadata(&self) -> Option { - Some(StepMetadata::dist("std", self.target).built_by(self.compiler)) + Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler)) } } @@ -787,8 +816,9 @@ impl Step for Std { /// (Don't confuse this with [`RustDev`], without the `c`!) #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustcDev { - pub compiler: Compiler, - pub target: TargetSelection, + /// The compiler that will build rustc which will be shipped in this component. + build_compiler: Compiler, + target: TargetSelection, } impl Step for RustcDev { @@ -802,28 +832,27 @@ impl Step for RustcDev { fn make_run(run: RunConfig<'_>) { run.builder.ensure(RustcDev { - compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, - ), + // We currently always ship a stage 2 rustc-dev component, so we build it with the + // stage 1 compiler. This might change in the future. + // The precise stage used here is important, so we hard-code it. + build_compiler: run.builder.compiler(1, run.builder.config.host_target), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; + let build_compiler = self.build_compiler; let target = self.target; - if skip_host_target_lib(builder, compiler) { + if skip_host_target_lib(builder, build_compiler) { return None; } - builder.ensure(compile::Rustc::new(compiler, target)); + // Build the compiler that we will ship + builder.ensure(compile::Rustc::new(build_compiler, target)); let tarball = Tarball::new(builder, "rustc-dev", &target.triple); - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - let stamp = build_stamp::librustc_stamp(builder, compiler_to_use, target); + let stamp = build_stamp::librustc_stamp(builder, build_compiler, target); copy_target_libs(builder, target, tarball.image_dir(), &stamp); let src_files = &["Cargo.lock"]; @@ -847,16 +876,25 @@ impl Step for RustcDev { Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler)) + } } +/// The `rust-analysis` component used to create a tarball of save-analysis metadata. +/// +/// This component has been deprecated and its contents now only include a warning about +/// its non-availability. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Analysis { - pub compiler: Compiler, - pub target: TargetSelection, + build_compiler: Compiler, + target: TargetSelection, } impl Step for Analysis { type Output = Option; + const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -865,24 +903,17 @@ impl Step for Analysis { } fn make_run(run: RunConfig<'_>) { + // The step just produces a deprecation notice, so we just hardcode stage 1 run.builder.ensure(Analysis { - // Find the actual compiler (handling the full bootstrap option) which - // produced the save-analysis data because that data isn't copied - // through the sysroot uplifting. - compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, - ), + build_compiler: run.builder.compiler(1, run.builder.config.host_target), target: run.target, }); } - /// Creates a tarball of (degenerate) save-analysis metadata, if available. fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; + let compiler = self.build_compiler; let target = self.target; - if !builder.config.is_host_target(compiler.host) { + if skip_host_target_lib(builder, compiler) { return None; } @@ -905,6 +936,10 @@ impl Step for Analysis { tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple)); Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler)) + } } /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to @@ -1251,10 +1286,9 @@ impl Step for Cargo { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Cargo { - build_compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, + build_compiler: get_tool_target_compiler( + run.builder, + ToolTargetBuildMode::Build(run.target), ), target: run.target, }); @@ -1285,11 +1319,16 @@ impl Step for Cargo { Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler)) + } } +/// Distribute the rust-analyzer component, which is used as a LSP by various IDEs. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustAnalyzer { - pub build_compiler: Compiler, + pub compilers: RustcPrivateCompilers, pub target: TargetSelection, } @@ -1305,21 +1344,14 @@ impl Step for RustAnalyzer { fn make_run(run: RunConfig<'_>) { run.builder.ensure(RustAnalyzer { - build_compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, - ), + compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { let target = self.target; - let compilers = - RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target); - - let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(compilers)); + let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers)); let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple); tarball.set_overlay(OverlayKind::RustAnalyzer); @@ -1328,11 +1360,18 @@ impl Step for RustAnalyzer { tarball.add_legal_and_readme_to("share/doc/rust-analyzer"); Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some( + StepMetadata::dist("rust-analyzer", self.target) + .built_by(self.compilers.build_compiler()), + ) + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Clippy { - pub build_compiler: Compiler, + pub compilers: RustcPrivateCompilers, pub target: TargetSelection, } @@ -1348,25 +1387,19 @@ impl Step for Clippy { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Clippy { - build_compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, - ), + compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { let target = self.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::from_compilers(compilers)); - let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(compilers)); + let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers)); + let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers)); let mut tarball = Tarball::new(builder, "clippy", &target.triple); tarball.set_overlay(OverlayKind::Clippy); @@ -1376,11 +1409,15 @@ impl Step for Clippy { tarball.add_legal_and_readme_to("share/doc/clippy"); Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler())) + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Miri { - pub build_compiler: Compiler, + pub compilers: RustcPrivateCompilers, pub target: TargetSelection, } @@ -1396,11 +1433,7 @@ impl Step for Miri { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Miri { - build_compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, - ), + compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), target: run.target, }); } @@ -1413,10 +1446,8 @@ impl Step for Miri { return None; } - 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::from_compilers(self.compilers)); + let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers)); let mut tarball = Tarball::new(builder, "miri", &self.target.triple); tarball.set_overlay(OverlayKind::Miri); @@ -1426,11 +1457,15 @@ impl Step for Miri { tarball.add_legal_and_readme_to("share/doc/miri"); Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler())) + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct CraneliftCodegenBackend { - pub build_compiler: Compiler, + pub compilers: RustcPrivateCompilers, pub target: TargetSelection, } @@ -1454,11 +1489,7 @@ impl Step for CraneliftCodegenBackend { fn make_run(run: RunConfig<'_>) { run.builder.ensure(CraneliftCodegenBackend { - build_compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, - ), + compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), target: run.target, }); } @@ -1472,8 +1503,6 @@ impl Step for CraneliftCodegenBackend { } let target = self.target; - let compilers = - RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target); if !target_supports_cranelift_backend(target) { builder.info("target not supported by rustc_codegen_cranelift. skipping"); return None; @@ -1484,6 +1513,7 @@ impl Step for CraneliftCodegenBackend { tarball.is_preview(true); tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift"); + let compilers = self.compilers; let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers }); if builder.config.dry_run() { @@ -1513,15 +1543,15 @@ impl Step for CraneliftCodegenBackend { fn metadata(&self) -> Option { Some( - StepMetadata::dist("rustc_codegen_cranelift", self.build_compiler.host) - .built_by(self.build_compiler), + StepMetadata::dist("rustc_codegen_cranelift", self.target) + .built_by(self.compilers.build_compiler()), ) } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Rustfmt { - pub build_compiler: Compiler, + pub compilers: RustcPrivateCompilers, pub target: TargetSelection, } @@ -1537,21 +1567,14 @@ impl Step for Rustfmt { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Rustfmt { - build_compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.host_target, - run.target, - ), + compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { - let compilers = - RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.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::from_compilers(self.compilers)); + let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers)); let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple); tarball.set_overlay(OverlayKind::Rustfmt); @@ -1561,12 +1584,16 @@ impl Step for Rustfmt { tarball.add_legal_and_readme_to("share/doc/rustfmt"); Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler())) + } } +/// Extended archive that contains the compiler, standard library and a bunch of tools. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Extended { - stage: u32, - host: TargetSelection, + build_compiler: Compiler, target: TargetSelection, } @@ -1582,8 +1609,9 @@ impl Step for Extended { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Extended { - stage: run.builder.top_stage, - host: run.builder.config.host_target, + build_compiler: run + .builder + .compiler(run.builder.top_stage - 1, run.builder.host_target), target: run.target, }); } @@ -1591,10 +1619,7 @@ impl Step for Extended { /// Creates a combined installer for the specified target in the provided stage. fn run(self, builder: &Builder<'_>) { let target = self.target; - let stage = self.stage; - let compiler = builder.compiler_for(self.stage, self.host, self.target); - - builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target)); + builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage)); let mut tarballs = Vec::new(); let mut built_tools = HashSet::new(); @@ -1607,34 +1632,38 @@ impl Step for Extended { }; } - let target_compiler = builder.compiler(stage, target); + let rustc_private_compilers = + RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target); + let build_compiler = rustc_private_compilers.build_compiler(); + let target_compiler = rustc_private_compilers.target_compiler(); + // When rust-std package split from rustc, we needed to ensure that during // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering // the std files during uninstall. To do this ensure that rustc comes // before rust-std in the list below. - tarballs.push(builder.ensure(Rustc { compiler: target_compiler })); - tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std")); + tarballs.push(builder.ensure(Rustc { target_compiler })); + tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std")); if target.is_windows_gnu() { - tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw")); + tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw")); } add_component!("rust-docs" => Docs { host: target }); // Std stage N is documented with compiler stage N add_component!("rust-json-docs" => JsonDocs { build_compiler: target_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!("cargo" => Cargo { build_compiler, target }); + add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target }); + add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target }); add_component!("llvm-components" => LlvmTools { 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!("clippy" => Clippy { compilers: rustc_private_compilers, target }); + add_component!("miri" => Miri { compilers: rustc_private_compilers, target }); + add_component!("analysis" => Analysis { build_compiler, target }); add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend { - build_compiler: compiler, + compilers: rustc_private_compilers, target }); add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker { - build_compiler: compiler, + build_compiler, target }); @@ -2100,6 +2129,10 @@ impl Step for Extended { } } } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler)) + } } fn add_env( @@ -2562,15 +2595,17 @@ impl Step for RustDev { /// Tarball intended for internal consumption to ease rustc/std development. /// +/// It only packages the binaries that were already compiled when bootstrap itself was built. +/// /// Should not be considered stable by end users. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Bootstrap { - pub target: TargetSelection, + target: TargetSelection, } impl Step for Bootstrap { type Output = Option; - const DEFAULT: bool = false; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -2597,6 +2632,10 @@ impl Step for Bootstrap { Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("bootstrap", self.target)) + } } /// Tarball containing a prebuilt version of the build-manifest tool, intended to be used by the @@ -2605,12 +2644,12 @@ impl Step for Bootstrap { /// Should not be considered stable by end users. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct BuildManifest { - pub target: TargetSelection, + target: TargetSelection, } impl Step for BuildManifest { type Output = GeneratedTarball; - const DEFAULT: bool = false; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -2628,16 +2667,20 @@ impl Step for BuildManifest { tarball.add_file(&build_manifest, "bin", FileType::Executable); tarball.generate() } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("build-manifest", self.target)) + } } /// Tarball containing artifacts necessary to reproduce the build of rustc. /// -/// Currently this is the PGO profile data. +/// Currently this is the PGO (and possibly BOLT) profile data. /// /// Should not be considered stable by end users. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct ReproducibleArtifacts { - pub target: TargetSelection, + target: TargetSelection, } impl Step for ReproducibleArtifacts { @@ -2670,6 +2713,10 @@ impl Step for ReproducibleArtifacts { } if added_anything { Some(tarball.generate()) } else { None } } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("reproducible-artifacts", self.target)) + } } /// Tarball containing a prebuilt version of the libgccjit library, @@ -2677,7 +2724,7 @@ impl Step for ReproducibleArtifacts { /// backend needing a prebuilt libLLVM). #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Gcc { - pub target: TargetSelection, + target: TargetSelection, } impl Step for Gcc { @@ -2697,4 +2744,8 @@ impl Step for Gcc { tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary); tarball.generate() } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("gcc", self.target)) + } } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 7fe19c00ef5fa..8c20c8c479af0 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -784,7 +784,7 @@ fn doc_std( let description = format!("library{} in {} format", crate_description(requested_crates), format.as_str()); - let _guard = builder.msg(Kind::Doc, description, None, build_compiler, target); + let _guard = builder.msg(Kind::Doc, description, Mode::Std, build_compiler, target); cargo.into_cmd().run(builder); builder.cp_link_r(&out_dir, out); @@ -994,7 +994,7 @@ macro_rules! tool_doc { (compilers.build_compiler(), Mode::ToolRustc) } else { // bootstrap/host tools have to be documented with the stage 0 compiler - (prepare_doc_compiler(run.builder, target, 1), Mode::ToolBootstrap) + (prepare_doc_compiler(run.builder, run.builder.host_target, 1), Mode::ToolBootstrap) }; run.builder.ensure($tool { build_compiler, mode, target }); diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 4457258e9cdd0..ce68dbf5a2010 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -7,6 +7,7 @@ use std::path::{Component, Path, PathBuf}; use std::{env, fs}; use crate::core::build_steps::dist; +use crate::core::build_steps::tool::RustcPrivateCompilers; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; use crate::utils::exec::command; @@ -64,17 +65,14 @@ fn is_dir_writable_for_user(dir: &Path) -> bool { fn install_sh( builder: &Builder<'_>, package: &str, - stage: u32, - host: Option, + build_compiler: impl Into>, + target: Option, tarball: &GeneratedTarball, ) { - let _guard = builder.msg( - Kind::Install, - package, - None, - (host.unwrap_or(builder.host_target), stage), - host, - ); + let _guard = match build_compiler.into() { + Some(build_compiler) => builder.msg(Kind::Install, package, None, build_compiler, target), + None => builder.msg_unstaged(Kind::Install, package, target.unwrap_or(builder.host_target)), + }; let prefix = default_path(&builder.config.prefix, "/usr/local"); let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc")); @@ -166,10 +164,10 @@ macro_rules! install { IS_HOST: $IS_HOST:expr, $run_item:block $(, $c:ident)*;)+) => { $( - #[derive(Debug, Clone, Hash, PartialEq, Eq)] + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct $name { - pub compiler: Compiler, - pub target: TargetSelection, + build_compiler: Compiler, + target: TargetSelection, } impl $name { @@ -193,7 +191,7 @@ macro_rules! install { fn make_run(run: RunConfig<'_>) { run.builder.ensure($name { - compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target), + build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.builder.config.host_target), target: run.target, }); } @@ -208,96 +206,95 @@ macro_rules! install { install!((self, builder, _config), Docs, path = "src/doc", _config.docs, IS_HOST: false, { let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs"); - install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball); + install_sh(builder, "docs", self.build_compiler, Some(self.target), &tarball); }; Std, path = "library/std", true, IS_HOST: false, { // `expect` should be safe, only None when host != build, but this // only runs when host == build - let tarball = builder.ensure(dist::Std { - compiler: self.compiler, - target: self.target - }).expect("missing std"); - install_sh(builder, "std", self.compiler.stage, Some(self.target), &tarball); + let std = dist::Std::new(builder, self.target); + let build_compiler = std.build_compiler; + let tarball = builder.ensure(std).expect("missing std"); + install_sh(builder, "std", build_compiler, Some(self.target), &tarball); }; Cargo, alias = "cargo", Self::should_build(_config), IS_HOST: true, { let tarball = builder - .ensure(dist::Cargo { build_compiler: self.compiler, target: self.target }) + .ensure(dist::Cargo { build_compiler: self.build_compiler, target: self.target }) .expect("missing cargo"); - install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball); + install_sh(builder, "cargo", self.build_compiler, Some(self.target), &tarball); }; RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), IS_HOST: true, { if let Some(tarball) = - builder.ensure(dist::RustAnalyzer { build_compiler: self.compiler, target: self.target }) + builder.ensure(dist::RustAnalyzer { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target), target: self.target }) { - install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball); + install_sh(builder, "rust-analyzer", self.build_compiler, Some(self.target), &tarball); } else { builder.info( - &format!("skipping Install rust-analyzer stage{} ({})", self.compiler.stage, self.target), + &format!("skipping Install rust-analyzer stage{} ({})", self.build_compiler.stage + 1, self.target), ); } }; Clippy, alias = "clippy", Self::should_build(_config), IS_HOST: true, { let tarball = builder - .ensure(dist::Clippy { build_compiler: self.compiler, target: self.target }) + .ensure(dist::Clippy { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target), target: self.target }) .expect("missing clippy"); - install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball); + install_sh(builder, "clippy", self.build_compiler, Some(self.target), &tarball); }; Miri, alias = "miri", Self::should_build(_config), IS_HOST: true, { - 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); + if let Some(tarball) = builder.ensure(dist::Miri { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target) , target: self.target }) { + install_sh(builder, "miri", self.build_compiler, Some(self.target), &tarball); } else { // Miri is only available on nightly builder.info( - &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target), + &format!("skipping Install miri stage{} ({})", self.build_compiler.stage + 1, self.target), ); } }; LlvmTools, alias = "llvm-tools", _config.llvm_tools_enabled && _config.llvm_enabled(_config.host_target), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) { - install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball); + install_sh(builder, "llvm-tools", None, Some(self.target), &tarball); } else { builder.info( - &format!("skipping llvm-tools stage{} ({}): external LLVM", self.compiler.stage, self.target), + &format!("skipping llvm-tools ({}): external LLVM", self.target), ); } }; Rustfmt, alias = "rustfmt", Self::should_build(_config), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::Rustfmt { - build_compiler: self.compiler, + compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target), target: self.target }) { - install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball); + install_sh(builder, "rustfmt", self.build_compiler, Some(self.target), &tarball); } else { builder.info( - &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target), + &format!("skipping Install Rustfmt stage{} ({})", self.build_compiler.stage + 1, self.target), ); } }; Rustc, path = "compiler/rustc", true, IS_HOST: true, { let tarball = builder.ensure(dist::Rustc { - compiler: builder.compiler(builder.top_stage, self.target), + target_compiler: builder.compiler(self.build_compiler.stage + 1, self.target), }); - install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball); + install_sh(builder, "rustc", self.build_compiler, Some(self.target), &tarball); }; RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::CraneliftCodegenBackend { - build_compiler: self.compiler, + compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target), target: self.target }) { - install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball); + install_sh(builder, "rustc-codegen-cranelift", self.build_compiler, Some(self.target), &tarball); } else { builder.info( &format!("skipping Install CodegenBackend(\"cranelift\") stage{} ({})", - self.compiler.stage, self.target), + self.build_compiler.stage + 1, self.target), ); } }; LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), IS_HOST: true, { - if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.compiler, target: self.target }) { - install_sh(builder, "llvm-bitcode-linker", self.compiler.stage, Some(self.target), &tarball); + if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.build_compiler, target: self.target }) { + install_sh(builder, "llvm-bitcode-linker", self.build_compiler, Some(self.target), &tarball); } else { builder.info( - &format!("skipping llvm-bitcode-linker stage{} ({})", self.compiler.stage, self.target), + &format!("skipping llvm-bitcode-linker stage{} ({})", self.build_compiler.stage + 1, self.target), ); } }; @@ -305,7 +302,7 @@ install!((self, builder, _config), #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Src { - pub stage: u32, + stage: u32, } impl Step for Src { @@ -325,6 +322,6 @@ impl Step for Src { fn run(self, builder: &Builder<'_>) { let tarball = builder.ensure(dist::Src); - install_sh(builder, "src", self.stage, None, &tarball); + install_sh(builder, "src", None, None, &tarball); } } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 269e7da8d7b24..318287df08a2f 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -153,7 +153,7 @@ You can skip linkcheck with --skip src/tools/linkchecker" } // Build all the default documentation. - builder.default_doc(&[]); + builder.run_default_doc_steps(); // Build the linkchecker before calling `msg`, since GHA doesn't support nested groups. let linkchecker = builder.tool_cmd(Tool::Linkchecker); @@ -208,7 +208,7 @@ impl Step for HtmlCheck { panic!("Cannot run html-check tests"); } // Ensure that a few different kinds of documentation are available. - builder.default_doc(&[]); + builder.run_default_doc_steps(); builder.ensure(crate::core::build_steps::doc::Rustc::for_stage( builder, builder.top_stage, @@ -1719,7 +1719,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the if suite == "debuginfo" { builder.ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler).to_path_buf(), - host: target, + target, }); } if suite == "run-make" { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index b62c9a906b79c..c10b82536467d 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1581,6 +1581,10 @@ impl Builder<'_> { /// `host`. pub fn tool_cmd(&self, tool: Tool) -> BootstrapCommand { let mut cmd = command(self.tool_exe(tool)); + + // Do not cache tool invocations, as they can have side effects + cmd.do_not_cache(); + let compiler = self.compiler(0, self.config.host_target); let host = &compiler.host; // Prepares the `cmd` provided to be able to run the `compiler` provided. diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 40460bf168dc0..4f1bed13c13e7 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -22,6 +22,7 @@ use crate::core::build_steps::{ }; use crate::core::config::flags::Subcommand; use crate::core::config::{DryRun, TargetSelection}; +use crate::utils::build_stamp::BuildStamp; use crate::utils::cache::Cache; use crate::utils::exec::{BootstrapCommand, ExecutionContext, command}; use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t}; @@ -1308,8 +1309,9 @@ impl<'a> Builder<'a> { self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths); } - pub fn default_doc(&self, paths: &[PathBuf]) { - self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths); + /// Run all default documentation steps to build documentation. + pub fn run_default_doc_steps(&self) { + self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]); } pub fn doc_rust_lang_org_channel(&self) -> String { @@ -1411,6 +1413,8 @@ impl<'a> Builder<'a> { /// The standard library will be linked to the sysroot of the passed compiler. /// /// Prefer using this method rather than manually invoking `Std::new`. + /// + /// Returns an optional build stamp, if libstd was indeed built. #[cfg_attr( feature = "tracing", instrument( @@ -1424,7 +1428,7 @@ impl<'a> Builder<'a> { ), ), )] - pub fn std(&self, compiler: Compiler, target: TargetSelection) { + pub fn std(&self, compiler: Compiler, target: TargetSelection) -> Option { // FIXME: make the `Std` step return some type-level "proof" that std was indeed built, // and then require passing that to all Cargo invocations that we do. @@ -1443,10 +1447,11 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s // We still need to link the prebuilt standard library into the ephemeral stage0 sysroot self.ensure(StdLink::from_std(Std::new(compiler, target), compiler)); + None } else { // This step both compiles the std and links it into the compiler's sysroot. // Yes, it's quite magical and side-effecty.. would be nice to refactor later. - self.ensure(Std::new(compiler, target)); + self.ensure(Std::new(compiler, target)) } } diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 2afba25ae5922..5260b43f706cd 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1133,8 +1133,11 @@ mod snapshot { [dist] mingw [build] rustc 0 -> GenerateCopyright 1 [dist] rustc - [dist] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 + [dist] rustc 1 -> rustc-dev 2 [dist] src <> + [dist] reproducible-artifacts " ); } @@ -1195,16 +1198,27 @@ mod snapshot { [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 [build] rustc 0 -> GenerateCopyright 1 [dist] rustc - [dist] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> analysis 2 [dist] src <> [build] rustc 1 -> cargo 2 + [dist] rustc 1 -> cargo 2 [build] rustc 1 -> rust-analyzer 2 + [dist] rustc 1 -> rust-analyzer 2 [build] rustc 1 -> rustfmt 2 [build] rustc 1 -> cargo-fmt 2 + [dist] rustc 1 -> rustfmt 2 [build] rustc 1 -> clippy-driver 2 [build] rustc 1 -> cargo-clippy 2 + [dist] rustc 1 -> clippy 2 [build] rustc 1 -> miri 2 [build] rustc 1 -> cargo-miri 2 + [dist] rustc 1 -> miri 2 + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> extended 2 + [dist] reproducible-artifacts "); } @@ -1273,10 +1287,13 @@ mod snapshot { [dist] mingw [build] rustc 0 -> GenerateCopyright 1 [dist] rustc - [dist] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 [build] rustc 2 -> std 2 [dist] rustc 2 -> std 2 + [dist] rustc 1 -> rustc-dev 2 [dist] src <> + [dist] reproducible-artifacts " ); } @@ -1333,8 +1350,13 @@ mod snapshot { [dist] rustc [build] rustdoc 2 [dist] rustc - [dist] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> rustc-dev 2 [dist] src <> + [dist] reproducible-artifacts + [dist] reproducible-artifacts " ); } @@ -1411,9 +1433,15 @@ mod snapshot { [dist] rustc [build] rustdoc 2 [dist] rustc - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> rustc-dev 2 [dist] src <> + [dist] reproducible-artifacts + [dist] reproducible-artifacts " ); } @@ -1517,18 +1545,29 @@ mod snapshot { [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 [build] rustc 0 -> GenerateCopyright 1 [dist] rustc - [dist] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> analysis 2 [dist] src <> [build] rustc 1 -> cargo 2 + [dist] rustc 1 -> cargo 2 [build] rustc 1 -> rust-analyzer 2 + [dist] rustc 1 -> rust-analyzer 2 [build] rustc 1 -> rustfmt 2 [build] rustc 1 -> cargo-fmt 2 + [dist] rustc 1 -> rustfmt 2 [build] rustc 1 -> clippy-driver 2 [build] rustc 1 -> cargo-clippy 2 + [dist] rustc 1 -> clippy 2 [build] rustc 1 -> miri 2 [build] rustc 1 -> cargo-miri 2 + [dist] rustc 1 -> miri 2 [build] rustc 1 -> LlvmBitcodeLinker 2 + [dist] rustc 1 -> std 1 [doc] rustc 2 -> std 2 crates=[] + [dist] rustc 1 -> extended 2 + [dist] reproducible-artifacts "); } @@ -1580,8 +1619,24 @@ mod snapshot { [build] rustc 0 -> GenerateCopyright 1 [dist] rustc [dist] rustc 1 -> rustc_codegen_cranelift 2 - [dist] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 + [dist] rustc 1 -> rustc-dev 2 [dist] src <> + [dist] reproducible-artifacts + "); + } + + #[test] + fn dist_bootstrap() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .path("bootstrap") + .render_steps(), @r" + [build] rustc 0 -> RustInstaller 1 + [dist] bootstrap "); } @@ -2126,6 +2181,197 @@ mod snapshot { [doc] rustc 1 -> reference (book) 2 "); } + + #[test] + fn clippy_ci() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("ci") + .stage(2) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> clippy-driver 1 + [build] rustc 0 -> cargo-clippy 1 + [clippy] rustc 1 -> bootstrap 2 + [clippy] rustc 1 -> std 1 + [clippy] rustc 1 -> rustc 2 + [check] rustc 1 -> rustc 2 + [clippy] rustc 1 -> rustc_codegen_gcc 2 + "); + } + + #[test] + fn clippy_compiler_stage1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("compiler") + .render_steps(), @r" + [build] llvm + [clippy] rustc 0 -> rustc 1 + "); + } + + #[test] + fn clippy_compiler_stage2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("compiler") + .stage(2) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> clippy-driver 1 + [build] rustc 0 -> cargo-clippy 1 + [clippy] rustc 1 -> rustc 2 + "); + } + + #[test] + fn clippy_std_stage1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("std") + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> clippy-driver 1 + [build] rustc 0 -> cargo-clippy 1 + [clippy] rustc 1 -> std 1 + "); + } + + #[test] + fn clippy_std_stage2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("std") + .stage(2) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [clippy] rustc 2 -> std 2 + "); + } + + #[test] + fn clippy_miri_stage1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("miri") + .stage(1) + .render_steps(), @r" + [build] llvm + [check] rustc 0 -> rustc 1 + [clippy] rustc 0 -> miri 1 + "); + } + + #[test] + fn clippy_miri_stage2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("miri") + .stage(2) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [check] rustc 1 -> rustc 2 + [build] rustc 0 -> clippy-driver 1 + [build] rustc 0 -> cargo-clippy 1 + [clippy] rustc 1 -> miri 2 + "); + } + + #[test] + fn clippy_bootstrap() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("bootstrap") + .render_steps(), @"[clippy] rustc 0 -> bootstrap 1 "); + } + + #[test] + fn install_extended() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("install") + .args(&[ + // Using backslashes fails with `--set` + "--set", &format!("install.prefix={}", ctx.dir().display()).replace("\\", "/"), + "--set", &format!("install.sysconfdir={}", ctx.dir().display()).replace("\\", "/"), + "--set", "build.extended=true" + ]) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> WasmComponentLd 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [build] rustc 1 -> std 1 + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> WasmComponentLd 2 + [build] rustdoc 2 + [doc] rustc 2 -> 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 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std 2 + [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [build] rustc 1 -> cargo 2 + [dist] rustc 1 -> cargo 2 + [build] rustc 1 -> rust-analyzer 2 + [dist] rustc 1 -> rust-analyzer 2 + [build] rustc 1 -> rustfmt 2 + [build] rustc 1 -> cargo-fmt 2 + [dist] rustc 1 -> rustfmt 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [dist] rustc 1 -> clippy 2 + [build] rustc 1 -> miri 2 + [build] rustc 1 -> cargo-miri 2 + [dist] rustc 1 -> miri 2 + [dist] src <> + "); + } } struct ExecutedSteps { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f579bdd847f66..9ac8143439a23 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1041,6 +1041,14 @@ impl Config { eprintln!("ERROR: cannot run clippy on stage 0. Use at least stage 1."); exit!(1); } + (0, Subcommand::Dist) => { + eprintln!("ERROR: cannot dist anything on stage 0. Use at least stage 1."); + exit!(1); + } + (0, Subcommand::Install) => { + eprintln!("ERROR: cannot install anything on stage 0. Use at least stage 1."); + exit!(1); + } _ => {} } diff --git a/src/bootstrap/src/utils/build_stamp.rs b/src/bootstrap/src/utils/build_stamp.rs index 6c79385190e8e..4c35388a181aa 100644 --- a/src/bootstrap/src/utils/build_stamp.rs +++ b/src/bootstrap/src/utils/build_stamp.rs @@ -136,13 +136,13 @@ pub fn codegen_backend_stamp( } /// Cargo's output path for the standard library in a given stage, compiled -/// by a particular compiler for the specified target. +/// by a particular `build_compiler` for the specified `target`. pub fn libstd_stamp( builder: &Builder<'_>, - compiler: Compiler, + build_compiler: Compiler, target: TargetSelection, ) -> BuildStamp { - BuildStamp::new(&builder.cargo_out(compiler, Mode::Std, target)).with_prefix("libstd") + BuildStamp::new(&builder.cargo_out(build_compiler, Mode::Std, target)).with_prefix("libstd") } /// Cargo's output path for librustc in a given stage, compiled by a particular diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 4fb5891ed181a..54f563fe68c70 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -516,4 +516,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "Build/check now supports forwarding `--timings` flag to cargo.", }, + ChangeInfo { + change_id: 145472, + severity: ChangeSeverity::Warning, + summary: "It is no longer possible to `x dist` or `x install` with stage 0. All dist and install commands have to be on stage 1+.", + }, ]; diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs index 983680b0385c1..3332187e2a853 100644 --- a/src/bootstrap/src/utils/tests/mod.rs +++ b/src/bootstrap/src/utils/tests/mod.rs @@ -31,6 +31,10 @@ impl TestCtx { Self { directory } } + pub fn dir(&self) -> &Path { + self.directory.path() + } + /// Starts a new invocation of bootstrap that executes `kind` as its top level command /// (i.e. `x `). Returns a builder that configures the created config through CLI flags. pub fn config(&self, kind: &str) -> ConfigBuilder {