diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 9da8b27a91778..93900a9043e7e 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -9,7 +9,7 @@ use std::sync::mpsc::SyncSender; use build_helper::git::get_git_modified_files; use ignore::WalkBuilder; -use crate::core::builder::Builder; +use crate::core::builder::{Builder, Kind}; use crate::utils::build_stamp::BuildStamp; use crate::utils::exec::command; use crate::utils::helpers::{self, t}; @@ -122,6 +122,12 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) { } pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { + if build.kind == Kind::Format && build.top_stage != 0 { + eprintln!("ERROR: `x fmt` only supports stage 0."); + eprintln!("HELP: Use `x run rustfmt` to run in-tree rustfmt."); + crate::exit!(1); + } + if !paths.is_empty() { eprintln!( "fmt error: path arguments are no longer accepted; use `--all` to format everything" diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 7ff385052940e..0bba441c3fa26 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -420,3 +420,56 @@ impl Step for CoverageDump { cmd.run(builder); } } + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Rustfmt; + +impl Step for Rustfmt { + type Output = (); + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/rustfmt") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Rustfmt); + } + + fn run(self, builder: &Builder<'_>) { + let host = builder.build.build; + + // `x run` uses stage 0 by default but rustfmt does not work well with stage 0. + // Change the stage to 1 if it's not set explicitly. + let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 { + builder.top_stage + } else { + 1 + }; + + if stage == 0 { + eprintln!("rustfmt cannot be run at stage 0"); + eprintln!("HELP: Use `x fmt` to use stage 0 rustfmt."); + std::process::exit(1); + } + + let compiler = builder.compiler(stage, host); + let rustfmt_build = builder.ensure(tool::Rustfmt { compiler, target: host }); + + let mut rustfmt = tool::prepare_tool_cargo( + builder, + rustfmt_build.build_compiler, + Mode::ToolRustc, + host, + Kind::Run, + "src/tools/rustfmt", + SourceType::InTree, + &[], + ); + + rustfmt.args(["--bin", "rustfmt", "--"]); + rustfmt.args(builder.config.args()); + + rustfmt.into_cmd().run(builder); + } +} diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 15dc3380a39a3..75cc5d3986b88 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1116,6 +1116,7 @@ impl<'a> Builder<'a> { run::FeaturesStatusDump, run::CyclicStep, run::CoverageDump, + run::Rustfmt, ), Kind::Setup => { describe!(setup::Profile, setup::Hook, setup::Link, setup::Editor) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index d926185ffaf1c..1d0ea3ebf6105 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -406,4 +406,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "Added a new option `rust.debug-assertions-tools` to control debug asssertions for tools.", }, + ChangeInfo { + change_id: 140732, + severity: ChangeSeverity::Info, + summary: "`./x run` now supports running in-tree `rustfmt`, e.g., `./x run rustfmt -- --check /path/to/file.rs`.", + }, ];