diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index a81d640301363..479af4af66665 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -85,7 +85,7 @@ macro_rules! clean_crate_tree { // NOTE: doesn't use `run_cargo` because we don't want to save a stamp file, // and doesn't use `stream_cargo` to avoid passing `--message-format` which `clean` doesn't accept. - builder.run(&mut cargo); + builder.run(cargo); } } )+ } diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 5b18cb3f7e1e6..a6172589dbb0f 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -27,6 +27,7 @@ use crate::core::builder::crate_description; use crate::core::builder::Cargo; use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date, }; @@ -771,7 +772,7 @@ impl Step for StartupObjects { let src_file = &src_dir.join(file.to_string() + ".rs"); let dst_file = &dst_dir.join(file.to_string() + ".o"); if !up_to_date(src_file, dst_file) { - let mut cmd = Command::new(&builder.initial_rustc); + let mut cmd = BootstrapCommand::new(&builder.initial_rustc); cmd.env("RUSTC_BOOTSTRAP", "1"); if !builder.local_rebuild { // a local_rebuild compiler already has stage1 features @@ -2076,7 +2077,7 @@ pub fn stream_cargo( tail_args: Vec, cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { - let mut cargo = Command::from(cargo); + let mut cargo = BootstrapCommand::from(cargo).command; // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. let mut message_format = if builder.config.json_output { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 2dc7cd7de6a05..e420840fdbf25 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -26,6 +26,7 @@ use crate::core::build_steps::tool::{self, Tool}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::channel::{self, Info}; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ exe, is_dylib, move_file, output, t, target_supports_cranelift_backend, timeit, }; @@ -1599,14 +1600,14 @@ impl Step for Extended { let _ = fs::remove_dir_all(&pkg); let pkgbuild = |component: &str| { - let mut cmd = Command::new("pkgbuild"); + let mut cmd = BootstrapCommand::new("pkgbuild"); cmd.arg("--identifier") .arg(format!("org.rust-lang.{}", component)) .arg("--scripts") .arg(pkg.join(component)) .arg("--nopayload") .arg(pkg.join(component).with_extension("pkg")); - builder.run(&mut cmd); + builder.run(cmd); }; let prepare = |name: &str| { @@ -1636,7 +1637,7 @@ impl Step for Extended { builder.create_dir(&pkg.join("res")); builder.create(&pkg.join("res/LICENSE.txt"), &license); builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); - let mut cmd = Command::new("productbuild"); + let mut cmd = BootstrapCommand::new("productbuild"); cmd.arg("--distribution") .arg(xform(&etc.join("pkg/Distribution.xml"))) .arg("--resources") @@ -1649,7 +1650,7 @@ impl Step for Extended { .arg("--package-path") .arg(&pkg); let _time = timeit(builder); - builder.run(&mut cmd); + builder.run(cmd); } if target.is_windows() { @@ -1704,7 +1705,7 @@ impl Step for Extended { let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"]; builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rustc") @@ -1720,7 +1721,7 @@ impl Step for Extended { ); if built_tools.contains("rust-docs") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-docs") @@ -1738,7 +1739,7 @@ impl Step for Extended { ); } builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("cargo") @@ -1755,7 +1756,7 @@ impl Step for Extended { .arg(etc.join("msi/remove-duplicates.xsl")), ); builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-std") @@ -1771,7 +1772,7 @@ impl Step for Extended { ); if built_tools.contains("rust-analyzer") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-analyzer") @@ -1790,7 +1791,7 @@ impl Step for Extended { } if built_tools.contains("clippy") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("clippy") @@ -1809,7 +1810,7 @@ impl Step for Extended { } if built_tools.contains("miri") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("miri") @@ -1827,7 +1828,7 @@ impl Step for Extended { ); } builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-analysis") @@ -1845,7 +1846,7 @@ impl Step for Extended { ); if target.ends_with("windows-gnu") { builder.run( - Command::new(&heat) + BootstrapCommand::new(&heat) .current_dir(&exe) .arg("dir") .arg("rust-mingw") @@ -1864,7 +1865,7 @@ impl Step for Extended { let candle = |input: &Path| { let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj"); let arch = if target.contains("x86_64") { "x64" } else { "x86" }; - let mut cmd = Command::new(&candle); + let mut cmd = BootstrapCommand::new(&candle); cmd.current_dir(&exe) .arg("-nologo") .arg("-dRustcDir=rustc") @@ -1893,7 +1894,7 @@ impl Step for Extended { if target.ends_with("windows-gnu") { cmd.arg("-dGccDir=rust-mingw"); } - builder.run(&mut cmd); + builder.run(cmd); }; candle(&xform(&etc.join("msi/rust.wxs"))); candle(&etc.join("msi/ui.wxs")); @@ -1925,7 +1926,7 @@ impl Step for Extended { builder.info(&format!("building `msi` installer with {light:?}")); let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple); - let mut cmd = Command::new(&light); + let mut cmd = BootstrapCommand::new(&light); cmd.arg("-nologo") .arg("-ext") .arg("WixUIExtension") @@ -1962,7 +1963,7 @@ impl Step for Extended { cmd.arg("-sice:ICE57"); let _time = timeit(builder); - builder.run(&mut cmd); + builder.run(cmd); if !builder.config.dry_run() { t!(move_file(exe.join(&filename), distdir(builder).join(&filename))); @@ -1971,7 +1972,7 @@ impl Step for Extended { } } -fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) { +fn add_env(builder: &Builder<'_>, cmd: &mut BootstrapCommand, target: TargetSelection) { let mut parts = builder.version.split('.'); cmd.env("CFG_RELEASE_INFO", builder.rust_version()) .env("CFG_RELEASE_NUM", &builder.version) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 87c700dad063d..4a5af25b3b2f8 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -249,6 +249,7 @@ impl Step for TheBook { let shared_assets = builder.ensure(SharedAssets { target }); // build the command first so we don't nest GHA groups + // FIXME: this doesn't do anything! builder.rustdoc_cmd(compiler); // build the redirect pages @@ -300,7 +301,7 @@ fn invoke_rustdoc( cmd.arg("-Z").arg("unstable-options").arg("--disable-minification"); } - builder.run(&mut cmd); + builder.run(cmd); } #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -394,7 +395,7 @@ impl Step for Standalone { } else { cmd.arg("--markdown-css").arg("rust.css"); } - builder.run(&mut cmd); + builder.run(cmd); } // We open doc/index.html as the default if invoked as `x.py doc --open` @@ -493,7 +494,7 @@ impl Step for Releases { cmd.arg("--disable-minification"); } - builder.run(&mut cmd); + builder.run(cmd); } // We open doc/RELEASES.html as the default if invoked as `x.py doc --open RELEASES.md` @@ -737,7 +738,7 @@ fn doc_std( format!("library{} in {} format", crate_description(requested_crates), format.as_str()); let _guard = builder.msg_doc(compiler, description, target); - builder.run(&mut cargo.into()); + builder.run(cargo); builder.cp_link_r(&out_dir, out); } @@ -862,7 +863,7 @@ impl Step for Rustc { let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc"); symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); - builder.run(&mut cargo.into()); + builder.run(cargo); if !builder.config.dry_run() { // Sanity check on linked compiler crates @@ -995,7 +996,7 @@ macro_rules! tool_doc { symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); let _guard = builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); - builder.run(&mut cargo.into()); + builder.run(cargo); if !builder.config.dry_run() { // Sanity check on linked doc directories @@ -1079,7 +1080,7 @@ impl Step for ErrorIndex { index.arg(out); index.arg(&builder.version); - builder.run(&mut index); + builder.run(index); } } @@ -1115,7 +1116,7 @@ impl Step for UnstableBookGen { cmd.arg(builder.src.join("src")); cmd.arg(out); - builder.run(&mut cmd); + builder.run(cmd); } } @@ -1210,7 +1211,7 @@ impl Step for RustcBook { self.compiler.host, self.target, ); - builder.run(&mut cmd); + builder.run(cmd); drop(doc_generator_guard); // Run rustbook/mdbook to generate the HTML pages. diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index c47233ca42abe..7ee1aca2abcd4 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -6,11 +6,11 @@ use std::env; use std::fs; use std::path::{Component, Path, PathBuf}; -use std::process::Command; use crate::core::build_steps::dist; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::t; use crate::utils::tarball::GeneratedTarball; use crate::{Compiler, Kind}; @@ -102,7 +102,7 @@ fn install_sh( let empty_dir = builder.out.join("tmp/empty_dir"); t!(fs::create_dir_all(&empty_dir)); - let mut cmd = Command::new(SHELL); + let mut cmd = BootstrapCommand::new(SHELL); cmd.current_dir(&empty_dir) .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh"))) .arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix))) @@ -113,7 +113,7 @@ fn install_sh( .arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir))) .arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir))) .arg("--disable-ldconfig"); - builder.run(&mut cmd); + builder.run(cmd); t!(fs::remove_dir_all(&empty_dir)); } diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 9268b335db7c2..22d5efa5d95dd 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -50,7 +50,7 @@ impl Step for BuildManifest { cmd.arg(&builder.config.channel); builder.create_dir(&distdir(builder)); - builder.run(&mut cmd); + builder.run(cmd); } } @@ -72,7 +72,7 @@ impl Step for BumpStage0 { fn run(self, builder: &Builder<'_>) -> Self::Output { let mut cmd = builder.tool_cmd(Tool::BumpStage0); cmd.args(builder.config.args()); - builder.run(&mut cmd); + builder.run(cmd); } } @@ -94,7 +94,7 @@ impl Step for ReplaceVersionPlaceholder { fn run(self, builder: &Builder<'_>) -> Self::Output { let mut cmd = builder.tool_cmd(Tool::ReplaceVersionPlaceholder); cmd.arg(&builder.src); - builder.run(&mut cmd); + builder.run(cmd); } } @@ -158,8 +158,7 @@ impl Step for Miri { // after another --, so this must be at the end. miri.args(builder.config.args()); - let mut miri = Command::from(miri); - builder.run(&mut miri); + builder.run(miri); } } @@ -189,7 +188,7 @@ impl Step for CollectLicenseMetadata { let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata); cmd.env("REUSE_EXE", reuse); cmd.env("DEST", &dest); - builder.run(&mut cmd); + builder.run(cmd); dest } @@ -219,7 +218,7 @@ impl Step for GenerateCopyright { let mut cmd = builder.tool_cmd(Tool::GenerateCopyright); cmd.env("LICENSE_METADATA", &license_metadata); cmd.env("DEST", &dest); - builder.run(&mut cmd); + builder.run(cmd); dest } @@ -243,7 +242,7 @@ impl Step for GenerateWindowsSys { fn run(self, builder: &Builder<'_>) { let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys); cmd.arg(&builder.src); - builder.run(&mut cmd); + builder.run(cmd); } } diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 754d1e61da8c6..7c5e0d4e13ebb 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -16,6 +16,7 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { .tool_cmd(Tool::SuggestTests) .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository) .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch) + .command .output() .expect("failed to run `suggest-tests` tool"); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 1ef5af7cc2daf..d891a52f1ef1b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -156,7 +156,7 @@ You can skip linkcheck with --skip src/tools/linkchecker" let _guard = builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host); let _time = helpers::timeit(builder); - builder.run_tracked( + builder.run( BootstrapCommand::from(linkchecker.arg(builder.out.join(host.triple).join("doc"))) .delay_failure(), ); @@ -216,7 +216,7 @@ impl Step for HtmlCheck { builder, )); - builder.run_tracked( + builder.run( BootstrapCommand::from( builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)), ) @@ -267,7 +267,7 @@ impl Step for Cargotest { .env("RUSTC", builder.rustc(compiler)) .env("RUSTDOC", builder.rustdoc(compiler)); add_rustdoc_cargo_linker_args(cmd, builder, compiler.host, LldThreads::No); - builder.run_tracked(BootstrapCommand::from(cmd).delay_failure()); + builder.run(BootstrapCommand::from(cmd).delay_failure()); } } @@ -465,7 +465,7 @@ impl Miri { // Tell it where to put the sysroot. cargo.env("MIRI_SYSROOT", &miri_sysroot); - let mut cargo = Command::from(cargo); + let mut cargo = BootstrapCommand::from(cargo); let _guard = builder.msg(Kind::Build, compiler.stage, "miri sysroot", compiler.host, target); builder.run(&mut cargo); @@ -482,8 +482,10 @@ impl Miri { String::new() } else { builder.verbose(|| println!("running: {cargo:?}")); - let out = - cargo.output().expect("We already ran `cargo miri setup` before and that worked"); + let out = cargo + .command + .output() + .expect("We already ran `cargo miri setup` before and that worked"); assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code"); // Output is "\n". let stdout = String::from_utf8(out.stdout) @@ -596,7 +598,7 @@ impl Step for Miri { target, ); let _time = helpers::timeit(builder); - builder.run(&mut cargo); + builder.run(cargo); } } } @@ -661,11 +663,11 @@ impl Step for CargoMiri { // Finally, pass test-args and run everything. cargo.arg("--").args(builder.config.test_args()); - let mut cargo = Command::from(cargo); + let cargo = BootstrapCommand::from(cargo); { let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "cargo-miri", host, target); let _time = helpers::timeit(builder); - builder.run(&mut cargo); + builder.run(cargo); } } } @@ -766,7 +768,7 @@ impl Step for Clippy { let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host); // Clippy reports errors if it blessed the outputs - if builder.run_cmd(BootstrapCommand::from(&mut cargo).allow_failure()) { + if builder.run(BootstrapCommand::from(&mut cargo).allow_failure()).is_success() { // The tests succeeded; nothing to do. return; } @@ -819,7 +821,7 @@ impl Step for RustdocTheme { .env("RUSTC_BOOTSTRAP", "1"); cmd.args(linker_args(builder, self.compiler.host, LldThreads::No)); - builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); + builder.run(BootstrapCommand::from(&mut cmd).delay_failure()); } } @@ -845,7 +847,7 @@ impl Step for RustdocJSStd { fn run(self, builder: &Builder<'_>) { let nodejs = builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests"); - let mut command = Command::new(nodejs); + let mut command = BootstrapCommand::new(nodejs); command .arg(builder.src.join("src/tools/rustdoc-js/tester.js")) .arg("--crate-name") @@ -879,7 +881,7 @@ impl Step for RustdocJSStd { builder.config.build, self.target, ); - builder.run(&mut command); + builder.run(command); } } @@ -1097,7 +1099,7 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to } builder.info("tidy check"); - builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); + builder.run(BootstrapCommand::from(&mut cmd).delay_failure()); builder.info("x.py completions check"); let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"] @@ -1304,8 +1306,7 @@ impl Step for RunMakeSupport { &[], ); - let mut cargo = Command::from(cargo); - builder.run(&mut cargo); + builder.run(cargo); let lib_name = "librun_make_support.rlib"; let lib = builder.tools_dir(self.compiler).join(lib_name); @@ -2066,7 +2067,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--git-repository").arg(git_config.git_repository); cmd.arg("--nightly-branch").arg(git_config.nightly_branch); - builder.ci_env.force_coloring_in_ci(&mut cmd); + // FIXME: Move CiEnv back to bootstrap, it is only used here anyway + builder.ci_env.force_coloring_in_ci(&mut cmd.command); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( @@ -2184,11 +2186,8 @@ impl BookTest { ); let _time = helpers::timeit(builder); let cmd = BootstrapCommand::from(&mut rustbook_cmd).delay_failure(); - let toolstate = if builder.run_tracked(cmd).is_success() { - ToolState::TestPass - } else { - ToolState::TestFail - }; + let toolstate = + if builder.run(cmd).is_success() { ToolState::TestPass } else { ToolState::TestFail }; builder.save_toolstate(self.name, toolstate); } @@ -2317,8 +2316,7 @@ impl Step for ErrorIndex { let guard = builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host); let _time = helpers::timeit(builder); - builder - .run_tracked(BootstrapCommand::from(&mut tool).output_mode(OutputMode::OnlyOnFailure)); + builder.run(BootstrapCommand::from(&mut tool).output_mode(OutputMode::OnlyOnFailure)); drop(guard); // The tests themselves need to link to std, so make sure it is // available. @@ -2347,11 +2345,11 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> let test_args = builder.config.test_args().join(" "); cmd.arg("--test-args").arg(test_args); - let mut cmd = BootstrapCommand::from(&mut cmd).delay_failure(); + cmd = cmd.delay_failure(); if !builder.config.verbose_tests { cmd = cmd.quiet(); } - builder.run_tracked(cmd).is_success() + builder.run(cmd).is_success() } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -2377,11 +2375,8 @@ impl Step for RustcGuide { let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); let cmd = BootstrapCommand::from(rustbook_cmd.arg("linkcheck").arg(&src)).delay_failure(); - let toolstate = if builder.run_tracked(cmd).is_success() { - ToolState::TestPass - } else { - ToolState::TestFail - }; + let toolstate = + if builder.run(cmd).is_success() { ToolState::TestPass } else { ToolState::TestFail }; builder.save_toolstate("rustc-dev-guide", toolstate); } } @@ -2432,7 +2427,7 @@ impl Step for CrateLibrustc { /// Returns whether the test succeeded. #[allow(clippy::too_many_arguments)] // FIXME: reduce the number of args and remove this. fn run_cargo_test<'a>( - cargo: impl Into, + cargo: impl Into, libtest_args: &[&str], crates: &[String], primary_crate: &str, @@ -2463,14 +2458,14 @@ fn run_cargo_test<'a>( /// Given a `cargo test` subcommand, pass it the appropriate test flags given a `builder`. fn prepare_cargo_test( - cargo: impl Into, + cargo: impl Into, libtest_args: &[&str], crates: &[String], primary_crate: &str, compiler: Compiler, target: TargetSelection, builder: &Builder<'_>, -) -> Command { +) -> BootstrapCommand { let mut cargo = cargo.into(); // Propegate `--bless` if it has not already been set/unset @@ -2881,19 +2876,19 @@ impl Step for RemoteCopyLibs { // Spawn the emulator and wait for it to come online let tool = builder.tool_exe(Tool::RemoteTestClient); - let mut cmd = Command::new(&tool); + let mut cmd = BootstrapCommand::new(&tool); cmd.arg("spawn-emulator").arg(target.triple).arg(&server).arg(builder.tempdir()); if let Some(rootfs) = builder.qemu_rootfs(target) { cmd.arg(rootfs); } - builder.run(&mut cmd); + builder.run(cmd); // Push all our dylibs to the emulator for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) { let f = t!(f); let name = f.file_name().into_string().unwrap(); if helpers::is_dylib(&name) { - builder.run(Command::new(&tool).arg("push").arg(f.path())); + builder.run(BootstrapCommand::new(&tool).arg("push").arg(f.path())); } } } @@ -2924,20 +2919,20 @@ impl Step for Distcheck { builder.ensure(dist::PlainSourceTarball); builder.ensure(dist::Src); - let mut cmd = Command::new("tar"); + let mut cmd = BootstrapCommand::new("tar"); cmd.arg("-xf") .arg(builder.ensure(dist::PlainSourceTarball).tarball()) .arg("--strip-components=1") .current_dir(&dir); - builder.run(&mut cmd); + builder.run(cmd); builder.run( - Command::new("./configure") + BootstrapCommand::new("./configure") .args(&builder.config.configure_args) .arg("--enable-vendor") .current_dir(&dir), ); builder.run( - Command::new(helpers::make(&builder.config.build.triple)) + BootstrapCommand::new(helpers::make(&builder.config.build.triple)) .arg("check") .current_dir(&dir), ); @@ -2948,16 +2943,16 @@ impl Step for Distcheck { let _ = fs::remove_dir_all(&dir); t!(fs::create_dir_all(&dir)); - let mut cmd = Command::new("tar"); + let mut cmd = BootstrapCommand::new("tar"); cmd.arg("-xf") .arg(builder.ensure(dist::Src).tarball()) .arg("--strip-components=1") .current_dir(&dir); - builder.run(&mut cmd); + builder.run(cmd); let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml"); builder.run( - Command::new(&builder.initial_cargo) + BootstrapCommand::new(&builder.initial_cargo) // Will read the libstd Cargo.toml // which uses the unstable `public-dependency` feature. .env("RUSTC_BOOTSTRAP", "1") @@ -2986,7 +2981,7 @@ impl Step for Bootstrap { // Some tests require cargo submodule to be present. builder.build.update_submodule(Path::new("src/tools/cargo")); - let mut check_bootstrap = Command::new(builder.python()); + let mut check_bootstrap = BootstrapCommand::new(builder.python()); check_bootstrap .args(["-m", "unittest", "bootstrap_test.py"]) .env("BUILD_DIR", &builder.out) @@ -2994,9 +2989,9 @@ impl Step for Bootstrap { .current_dir(builder.src.join("src/bootstrap/")); // NOTE: we intentionally don't pass test_args here because the args for unittest and cargo test are mutually incompatible. // Use `python -m unittest` manually if you want to pass arguments. - builder.run_tracked(BootstrapCommand::from(&mut check_bootstrap).delay_failure()); + builder.run(check_bootstrap.delay_failure()); - let mut cmd = Command::new(&builder.initial_cargo); + let mut cmd = BootstrapCommand::new(&builder.initial_cargo); cmd.arg("test") .args(["--features", "bootstrap-self-test"]) .current_dir(builder.src.join("src/bootstrap")) @@ -3071,7 +3066,7 @@ impl Step for TierCheck { self.compiler.host, self.compiler.host, ); - builder.run_tracked(BootstrapCommand::from(&mut cargo.into()).delay_failure()); + builder.run(BootstrapCommand::from(cargo).delay_failure()); } } @@ -3147,8 +3142,7 @@ impl Step for RustInstaller { return; } - let mut cmd = - std::process::Command::new(builder.src.join("src/tools/rust-installer/test.sh")); + let mut cmd = BootstrapCommand::new(builder.src.join("src/tools/rust-installer/test.sh")); let tmpdir = testdir(builder, compiler.host).join("rust-installer"); let _ = std::fs::remove_dir_all(&tmpdir); let _ = std::fs::create_dir_all(&tmpdir); @@ -3157,7 +3151,7 @@ impl Step for RustInstaller { cmd.env("CARGO", &builder.initial_cargo); cmd.env("RUSTC", &builder.initial_rustc); cmd.env("TMP_DIR", &tmpdir); - builder.run_tracked(BootstrapCommand::from(&mut cmd).delay_failure()); + builder.run(cmd.delay_failure()); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -3351,8 +3345,7 @@ impl Step for CodegenCranelift { .arg("testsuite.extended_sysroot"); cargo.args(builder.config.test_args()); - let mut cmd: Command = cargo.into(); - builder.run_cmd(BootstrapCommand::from(&mut cmd).fail_fast()); + builder.run(cargo); } } @@ -3477,7 +3470,6 @@ impl Step for CodegenGCC { .arg("--std-tests"); cargo.args(builder.config.test_args()); - let mut cmd: Command = cargo.into(); - builder.run_cmd(BootstrapCommand::from(&mut cmd).fail_fast()); + builder.run(cargo); } } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index a95a7f5491f37..f6258121c50db 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -9,6 +9,7 @@ use crate::core::builder; use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::channel::GitInfo; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::output; use crate::utils::helpers::{add_dylib_path, exe, t}; use crate::Compiler; @@ -432,12 +433,12 @@ pub struct ErrorIndex { } impl ErrorIndex { - pub fn command(builder: &Builder<'_>) -> Command { + pub fn command(builder: &Builder<'_>) -> BootstrapCommand { // Error-index-generator links with the rustdoc library, so we need to add `rustc_lib_paths` // for rustc_private and libLLVM.so, and `sysroot_lib` for libstd, etc. let host = builder.config.build; let compiler = builder.compiler_for(builder.top_stage, host, host); - let mut cmd = Command::new(builder.ensure(ErrorIndex { compiler })); + let mut cmd = BootstrapCommand::new(builder.ensure(ErrorIndex { compiler })); let mut dylib_paths = builder.rustc_lib_paths(compiler); dylib_paths.push(PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))); add_dylib_path(dylib_paths, &mut cmd); @@ -601,7 +602,7 @@ impl Step for Rustdoc { &self.compiler.host, &target, ); - builder.run(&mut cargo.into()); + builder.run(cargo); // 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" @@ -856,7 +857,7 @@ impl Step for LlvmBitcodeLinker { &self.extra_features, ); - builder.run(&mut cargo.into()); + builder.run(cargo); let tool_out = builder .cargo_out(self.compiler, Mode::ToolRustc, self.target) @@ -911,13 +912,13 @@ impl Step for LibcxxVersionTool { } let compiler = builder.cxx(self.target).unwrap(); - let mut cmd = Command::new(compiler); + let mut cmd = BootstrapCommand::new(compiler); cmd.arg("-o") .arg(&executable) .arg(builder.src.join("src/tools/libcxx-version/main.cpp")); - builder.run_cmd(&mut cmd); + builder.run(cmd); if !executable.exists() { panic!("Something went wrong. {} is not present", executable.display()); @@ -1045,10 +1046,10 @@ tool_extended!((self, builder), ); impl<'a> Builder<'a> { - /// Gets a `Command` which is ready to run `tool` in `stage` built for + /// Gets a `BootstrapCommand` which is ready to run `tool` in `stage` built for /// `host`. - pub fn tool_cmd(&self, tool: Tool) -> Command { - let mut cmd = Command::new(self.tool_exe(tool)); + pub fn tool_cmd(&self, tool: Tool) -> BootstrapCommand { + let mut cmd = BootstrapCommand::new(self.tool_exe(tool)); let compiler = self.compiler(0, self.config.build); let host = &compiler.host; // Prepares the `cmd` provided to be able to run the `compiler` provided. diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index e92ab57619b6a..0b999a24a1fb9 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -1,6 +1,6 @@ use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::utils::exec::BootstrapCommand; use std::path::{Path, PathBuf}; -use std::process::Command; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub(crate) struct Vendor { @@ -27,7 +27,7 @@ impl Step for Vendor { } fn run(self, builder: &Builder<'_>) -> Self::Output { - let mut cmd = Command::new(&builder.initial_cargo); + let mut cmd = BootstrapCommand::new(&builder.initial_cargo); cmd.arg("vendor"); if self.versioned_dirs { @@ -59,6 +59,6 @@ impl Step for Vendor { cmd.current_dir(self.root_dir); - builder.run(&mut cmd); + builder.run(cmd); } } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 14ccbfe0267e8..58d6e7a58e308 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -24,6 +24,7 @@ use crate::utils::helpers::{check_cfg_arg, libdir, linker_flags, output, t, LldT use crate::EXTRA_CHECK_CFGS; use crate::{Build, CLang, Crate, DocTests, GitRepo, Mode}; +use crate::utils::exec::BootstrapCommand; pub use crate::Compiler; use clap::ValueEnum; @@ -1217,7 +1218,7 @@ impl<'a> Builder<'a> { /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic /// library lookup path. - pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { + pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut BootstrapCommand) { // Windows doesn't need dylib path munging because the dlls for the // compiler live next to the compiler and the system will find them // automatically. @@ -1250,11 +1251,11 @@ impl<'a> Builder<'a> { self.ensure(tool::Rustdoc { compiler }) } - pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> Command { + pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { if run_compiler.stage == 0 { // `ensure(Clippy { stage: 0 })` *builds* clippy with stage0, it doesn't use the beta clippy. let cargo_clippy = self.build.config.download_clippy(); - let mut cmd = Command::new(cargo_clippy); + let mut cmd = BootstrapCommand::new(cargo_clippy); cmd.env("CARGO", &self.initial_cargo); return cmd; } @@ -1273,13 +1274,13 @@ impl<'a> Builder<'a> { let mut dylib_path = helpers::dylib_path(); dylib_path.insert(0, self.sysroot(run_compiler).join("lib")); - let mut cmd = Command::new(cargo_clippy); + let mut cmd = BootstrapCommand::new(cargo_clippy); cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); cmd.env("CARGO", &self.initial_cargo); cmd } - pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> Command { + pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { assert!(run_compiler.stage > 0, "miri can not be invoked at stage 0"); let build_compiler = self.compiler(run_compiler.stage - 1, self.build.build); @@ -1295,7 +1296,7 @@ impl<'a> Builder<'a> { extra_features: Vec::new(), }); // Invoke cargo-miri, make sure it can find miri and cargo. - let mut cmd = Command::new(cargo_miri); + let mut cmd = BootstrapCommand::new(cargo_miri); cmd.env("MIRI", &miri); cmd.env("CARGO", &self.initial_cargo); // Need to add the `run_compiler` libs. Those are the libs produces *by* `build_compiler`, @@ -1310,8 +1311,8 @@ impl<'a> Builder<'a> { cmd } - pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command { - let mut cmd = Command::new(self.bootstrap_out.join("rustdoc")); + pub fn rustdoc_cmd(&self, compiler: Compiler) -> BootstrapCommand { + let mut cmd = BootstrapCommand::new(self.bootstrap_out.join("rustdoc")); cmd.env("RUSTC_STAGE", compiler.stage.to_string()) .env("RUSTC_SYSROOT", self.sysroot(compiler)) // Note that this is *not* the sysroot_libdir because rustdoc must be linked @@ -1352,7 +1353,7 @@ impl<'a> Builder<'a> { mode: Mode, target: TargetSelection, cmd: &str, // FIXME make this properly typed - ) -> Command { + ) -> BootstrapCommand { let mut cargo; if cmd == "clippy" { cargo = self.cargo_clippy_cmd(compiler); @@ -1365,7 +1366,7 @@ impl<'a> Builder<'a> { cargo = self.cargo_miri_cmd(compiler); cargo.arg("miri").arg(subcmd); } else { - cargo = Command::new(&self.initial_cargo); + cargo = BootstrapCommand::new(&self.initial_cargo); cargo.arg(cmd); } @@ -2104,7 +2105,7 @@ impl<'a> Builder<'a> { // Try to use a sysroot-relative bindir, in case it was configured absolutely. cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative()); - self.ci_env.force_coloring_in_ci(&mut cargo); + self.ci_env.force_coloring_in_ci(&mut cargo.command); // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of @@ -2373,7 +2374,7 @@ impl HostFlags { #[derive(Debug)] pub struct Cargo { - command: Command, + command: BootstrapCommand, compiler: Compiler, target: TargetSelection, rustflags: Rustflags, @@ -2598,8 +2599,8 @@ impl Cargo { } } -impl From for Command { - fn from(mut cargo: Cargo) -> Command { +impl From for BootstrapCommand { + fn from(mut cargo: Cargo) -> BootstrapCommand { let rustflags = &cargo.rustflags.0; if !rustflags.is_empty() { cargo.command.env("RUSTFLAGS", rustflags); @@ -2618,7 +2619,12 @@ impl From for Command { if !cargo.allow_features.is_empty() { cargo.command.env("RUSTC_ALLOW_FEATURES", cargo.allow_features); } - cargo.command } } + +impl From for Command { + fn from(cargo: Cargo) -> Command { + BootstrapCommand::from(cargo).command + } +} diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index fd077ab2d7c7a..c35398e2eb764 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -11,6 +11,7 @@ use std::{ use build_helper::ci::CiEnv; use xz2::bufread::XzDecoder; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::hex_encode; use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date}; use crate::{t, Config}; @@ -56,7 +57,7 @@ impl Config { /// Runs a command, printing out nice contextual information if it fails. /// Returns false if do not execute at all, otherwise returns its /// `status.success()`. - pub(crate) fn check_run(&self, cmd: &mut Command) -> bool { + pub(crate) fn check_run(&self, cmd: &mut BootstrapCommand) -> bool { if self.dry_run() { return true; } @@ -211,7 +212,7 @@ impl Config { fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { println!("downloading {url}"); // Try curl. If that fails and we are on windows, fallback to PowerShell. - let mut curl = Command::new("curl"); + let mut curl = BootstrapCommand::new("curl"); curl.args([ "-y", "30", diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index afba907ee92b4..730d0ae5f3d7c 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -575,19 +575,17 @@ impl Build { }; // NOTE: doesn't use `try_run` because this shouldn't print an error if it fails. if !update(true).status().map_or(false, |status| status.success()) { - self.run(&mut update(false)); + self.run(update(false)); } // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). // diff-index reports the modifications through the exit status - let has_local_modifications = !self.run_cmd( - BootstrapCommand::from(submodule_git().args(["diff-index", "--quiet", "HEAD"])) - .allow_failure() - .output_mode(match self.is_verbose() { - true => OutputMode::All, - false => OutputMode::OnlyOutput, - }), - ); + let has_local_modifications = self + .run( + BootstrapCommand::from(submodule_git().args(["diff-index", "--quiet", "HEAD"])) + .allow_failure(), + ) + .is_failure(); if has_local_modifications { self.run(submodule_git().args(["stash", "push"])); } @@ -939,7 +937,7 @@ impl Build { } /// Adds the `RUST_TEST_THREADS` env var if necessary - fn add_rust_test_threads(&self, cmd: &mut Command) { + fn add_rust_test_threads(&self, cmd: &mut BootstrapCommand) { if env::var_os("RUST_TEST_THREADS").is_none() { cmd.env("RUST_TEST_THREADS", self.jobs().to_string()); } @@ -961,11 +959,14 @@ impl Build { } /// Execute a command and return its output. - fn run_tracked(&self, command: BootstrapCommand<'_>) -> CommandOutput { + /// This method should be used for all command executions in bootstrap. + fn run>(&self, command: C) -> CommandOutput { if self.config.dry_run() { return CommandOutput::default(); } + let mut command = command.into(); + self.verbose(|| println!("running: {command:?}")); let output_mode = command.output_mode.unwrap_or_else(|| match self.is_verbose() { @@ -1024,22 +1025,6 @@ impl Build { output } - /// Runs a command, printing out nice contextual information if it fails. - fn run(&self, cmd: &mut Command) { - self.run_cmd(BootstrapCommand::from(cmd).fail_fast().output_mode( - match self.is_verbose() { - true => OutputMode::All, - false => OutputMode::OnlyOutput, - }, - )); - } - - /// A centralized function for running commands that do not return output. - pub(crate) fn run_cmd<'a, C: Into>>(&self, cmd: C) -> bool { - let command = cmd.into(); - self.run_tracked(command).is_success() - } - /// Check if verbosity is greater than the `level` pub fn is_verbose_than(&self, level: usize) -> bool { self.verbosity > level diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index e8c588b75b381..8bcb2301f1ace 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -1,4 +1,6 @@ -use std::process::{Command, ExitStatus, Output}; +use std::ffi::OsStr; +use std::path::Path; +use std::process::{Command, CommandArgs, CommandEnvs, ExitStatus, Output}; /// What should be done when the command fails. #[derive(Debug, Copy, Clone)] @@ -24,14 +26,71 @@ pub enum OutputMode { } /// Wrapper around `std::process::Command`. +/// +/// By default, the command will exit bootstrap if it fails. +/// If you want to allow failures, use [allow_failure]. +/// If you want to delay failures until the end of bootstrap, use [delay_failure]. +/// +/// By default, the command will print its stdout/stderr to stdout/stderr of bootstrap +/// ([OutputMode::OnlyOutput]). If bootstrap uses verbose mode, then it will also print the +/// command itself in case of failure ([OutputMode::All]). +/// If you want to handle the output programmatically, use `output_mode(OutputMode::OnlyOnFailure)`. +/// +/// [allow_failure]: BootstrapCommand::allow_failure +/// [delay_failure]: BootstrapCommand::delay_failure #[derive(Debug)] -pub struct BootstrapCommand<'a> { - pub command: &'a mut Command, +pub struct BootstrapCommand { + pub command: Command, pub failure_behavior: BehaviorOnFailure, pub output_mode: Option, } -impl<'a> BootstrapCommand<'a> { +impl BootstrapCommand { + pub fn new>(program: S) -> Self { + Command::new(program).into() + } + + pub fn arg>(&mut self, arg: S) -> &mut Self { + self.command.arg(arg.as_ref()); + self + } + + pub fn args(&mut self, args: I) -> &mut Self + where + I: IntoIterator, + S: AsRef, + { + self.command.args(args); + self + } + + pub fn env(&mut self, key: K, val: V) -> &mut Self + where + K: AsRef, + V: AsRef, + { + self.command.env(key, val); + self + } + + pub fn get_envs(&self) -> CommandEnvs<'_> { + self.command.get_envs() + } + + pub fn get_args(&self) -> CommandArgs<'_> { + self.command.get_args() + } + + pub fn env_remove>(&mut self, key: K) -> &mut Self { + self.command.env_remove(key); + self + } + + pub fn current_dir>(&mut self, dir: P) -> &mut Self { + self.command.current_dir(dir); + self + } + pub fn delay_failure(self) -> Self { Self { failure_behavior: BehaviorOnFailure::DelayFail, ..self } } @@ -54,8 +113,41 @@ impl<'a> BootstrapCommand<'a> { } } -impl<'a> From<&'a mut Command> for BootstrapCommand<'a> { +/// This implementation is temporary, until all `Command` invocations are migrated to +/// `BootstrapCommand`. +impl<'a> From<&'a mut Command> for BootstrapCommand { fn from(command: &'a mut Command) -> Self { + // This is essentially a manual `Command::clone` + let mut cmd = Command::new(command.get_program()); + if let Some(dir) = command.get_current_dir() { + cmd.current_dir(dir); + } + cmd.args(command.get_args()); + for (key, value) in command.get_envs() { + match value { + Some(value) => { + cmd.env(key, value); + } + None => { + cmd.env_remove(key); + } + } + } + + cmd.into() + } +} + +/// This implementation is temporary, until all `Command` invocations are migrated to +/// `BootstrapCommand`. +impl<'a> From<&'a mut BootstrapCommand> for BootstrapCommand { + fn from(command: &'a mut BootstrapCommand) -> Self { + BootstrapCommand::from(&mut command.command) + } +} + +impl From for BootstrapCommand { + fn from(command: Command) -> Self { Self { command, failure_behavior: BehaviorOnFailure::Exit, output_mode: None } } } diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 59b29eedb7971..ab53c08ba217f 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -47,6 +47,7 @@ macro_rules! t { } }; } +use crate::utils::exec::BootstrapCommand; pub use t; pub fn exe(name: &str, target: TargetSelection) -> String { @@ -72,7 +73,7 @@ pub fn libdir(target: TargetSelection) -> &'static str { /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path. /// If the dylib_path_var is already set for this cmd, the old value will be overwritten! -pub fn add_dylib_path(path: Vec, cmd: &mut Command) { +pub fn add_dylib_path(path: Vec, cmd: &mut BootstrapCommand) { let mut list = dylib_path(); for path in path { list.insert(0, path); @@ -81,7 +82,7 @@ pub fn add_dylib_path(path: Vec, cmd: &mut Command) { } /// Adds a list of lookup paths to `cmd`'s link library lookup path. -pub fn add_link_lib_path(path: Vec, cmd: &mut Command) { +pub fn add_link_lib_path(path: Vec, cmd: &mut BootstrapCommand) { let mut list = link_lib_path(); for path in path { list.insert(0, path); @@ -241,8 +242,9 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( } } -pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { - let status = match cmd.status() { +// FIXME: get rid of this function +pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool { + let status = match cmd.command.status() { Ok(status) => status, Err(e) => { println!("failed to execute command: {cmd:?}\nERROR: {e}"); @@ -437,7 +439,7 @@ pub fn linker_flags( } pub fn add_rustdoc_cargo_linker_args( - cmd: &mut Command, + cmd: &mut BootstrapCommand, builder: &Builder<'_>, target: TargetSelection, lld_threads: LldThreads, diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index 5c9918bce32e1..2e99bc68a8b75 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -7,14 +7,18 @@ //! to reimplement all the rendering logic in this module because of that. use crate::core::builder::Builder; +use crate::utils::exec::BootstrapCommand; use std::io::{BufRead, BufReader, Read, Write}; -use std::process::{ChildStdout, Command, Stdio}; +use std::process::{ChildStdout, Stdio}; use std::time::Duration; use termcolor::{Color, ColorSpec, WriteColor}; const TERSE_TESTS_PER_LINE: usize = 88; -pub(crate) fn add_flags_and_try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool { +pub(crate) fn add_flags_and_try_run_tests( + builder: &Builder<'_>, + cmd: &mut BootstrapCommand, +) -> bool { if !cmd.get_args().any(|arg| arg == "--") { cmd.arg("--"); } @@ -23,7 +27,11 @@ pub(crate) fn add_flags_and_try_run_tests(builder: &Builder<'_>, cmd: &mut Comma try_run_tests(builder, cmd, false) } -pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool { +pub(crate) fn try_run_tests( + builder: &Builder<'_>, + cmd: &mut BootstrapCommand, + stream: bool, +) -> bool { if builder.config.dry_run() { return true; } @@ -41,7 +49,8 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bo } } -fn run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool { +fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) -> bool { + let cmd = &mut cmd.command; cmd.stdout(Stdio::piped()); builder.verbose(|| println!("running: {cmd:?}")); diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index fd934f18de23f..5cc319826dbf3 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -5,14 +5,12 @@ //! In uplifting, a tarball from Stage N captures essential components //! to assemble Stage N + 1 compiler. -use std::{ - path::{Path, PathBuf}, - process::Command, -}; +use std::path::{Path, PathBuf}; use crate::core::builder::Builder; use crate::core::{build_steps::dist::distdir, builder::Kind}; use crate::utils::channel; +use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{move_file, t}; #[derive(Copy, Clone)] @@ -300,7 +298,7 @@ impl<'a> Tarball<'a> { } } - fn non_bare_args(&self, cmd: &mut Command) { + fn non_bare_args(&self, cmd: &mut BootstrapCommand) { cmd.arg("--rel-manifest-dir=rustlib") .arg("--legacy-manifest-dirs=rustlib,cargo") .arg(format!("--product-name={}", self.product_name)) @@ -312,7 +310,7 @@ impl<'a> Tarball<'a> { .arg(distdir(self.builder)); } - fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> GeneratedTarball { + fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut BootstrapCommand)) -> GeneratedTarball { t!(std::fs::create_dir_all(&self.overlay_dir)); self.builder.create(&self.overlay_dir.join("version"), &self.overlay.version(self.builder)); if let Some(info) = self.builder.rust_info().info() { @@ -353,7 +351,7 @@ impl<'a> Tarball<'a> { }; cmd.args(["--compression-profile", compression_profile]); - self.builder.run(&mut cmd); + self.builder.run(cmd); // Ensure there are no symbolic links in the tarball. In particular, // rustup-toolchain-install-master and most versions of Windows can't handle symbolic links.