From 7b863bb8c91ab408233215bdcbbad600ce6db37f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 15 Nov 2025 16:44:08 +1100 Subject: [PATCH] Split out `Step::is_really_default` from `Step::should_run` --- src/bootstrap/src/core/build_steps/dist.rs | 104 ++++++++++++------ src/bootstrap/src/core/build_steps/doc.rs | 86 ++++++++++----- src/bootstrap/src/core/build_steps/install.rs | 17 ++- src/bootstrap/src/core/build_steps/test.rs | 88 +++++++++------ src/bootstrap/src/core/build_steps/tool.rs | 78 +++++++------ src/bootstrap/src/core/build_steps/vendor.rs | 2 +- src/bootstrap/src/core/builder/cli_paths.rs | 2 +- src/bootstrap/src/core/builder/mod.rs | 80 +++++++------- 8 files changed, 292 insertions(+), 165 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 411d42962644d..e2ede329ec772 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -66,8 +66,11 @@ impl Step for Docs { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = run.builder.config.docs; - run.alias("rust-docs").default_condition(default) + run.alias("rust-docs") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -110,8 +113,11 @@ impl Step for JsonDocs { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = run.builder.config.docs; - run.alias("rust-docs-json").default_condition(default) + run.alias("rust-docs-json") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -161,8 +167,11 @@ impl Step for RustcDocs { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.alias("rustc-docs").default_condition(builder.config.compiler_docs) + run.alias("rustc-docs") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.compiler_docs } fn make_run(run: RunConfig<'_>) { @@ -931,8 +940,11 @@ impl Step for Analysis { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = should_build_extended_tool(run.builder, "analysis"); - run.alias("rust-analysis").default_condition(default) + run.alias("rust-analysis") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + should_build_extended_tool(builder, "analysis") } fn make_run(run: RunConfig<'_>) { @@ -1165,8 +1177,11 @@ impl Step for PlainSourceTarball { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.alias("rustc-src").default_condition(builder.config.rust_dist_src) + run.alias("rustc-src") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.rust_dist_src } fn make_run(run: RunConfig<'_>) { @@ -1313,8 +1328,11 @@ impl Step for Cargo { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = should_build_extended_tool(run.builder, "cargo"); - run.alias("cargo").default_condition(default) + run.alias("cargo") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + should_build_extended_tool(builder, "cargo") } fn make_run(run: RunConfig<'_>) { @@ -1371,8 +1389,11 @@ impl Step for RustAnalyzer { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = should_build_extended_tool(run.builder, "rust-analyzer"); - run.alias("rust-analyzer").default_condition(default) + run.alias("rust-analyzer") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + should_build_extended_tool(builder, "rust-analyzer") } fn make_run(run: RunConfig<'_>) { @@ -1414,8 +1435,11 @@ impl Step for Clippy { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = should_build_extended_tool(run.builder, "clippy"); - run.alias("clippy").default_condition(default) + run.alias("clippy") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + should_build_extended_tool(builder, "clippy") } fn make_run(run: RunConfig<'_>) { @@ -1460,8 +1484,11 @@ impl Step for Miri { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = should_build_extended_tool(run.builder, "miri"); - run.alias("miri").default_condition(default) + run.alias("miri") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + should_build_extended_tool(builder, "miri") } fn make_run(run: RunConfig<'_>) { @@ -1508,16 +1535,18 @@ impl Step for CraneliftCodegenBackend { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("rustc_codegen_cranelift") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { // We only want to build the cranelift backend in `x dist` if the backend was enabled // in rust.codegen-backends. // Sadly, we don't have access to the actual target for which we're disting clif here.. // So we just use the host target. - let clif_enabled_by_default = run - .builder + builder .config - .enabled_codegen_backends(run.builder.host_target) - .contains(&CodegenBackendKind::Cranelift); - run.alias("rustc_codegen_cranelift").default_condition(clif_enabled_by_default) + .enabled_codegen_backends(builder.host_target) + .contains(&CodegenBackendKind::Cranelift) } fn make_run(run: RunConfig<'_>) { @@ -1594,8 +1623,11 @@ impl Step for Rustfmt { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = should_build_extended_tool(run.builder, "rustfmt"); - run.alias("rustfmt").default_condition(default) + run.alias("rustfmt") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + should_build_extended_tool(builder, "rustfmt") } fn make_run(run: RunConfig<'_>) { @@ -1636,8 +1668,11 @@ impl Step for Extended { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.alias("extended").default_condition(builder.config.extended) + run.alias("extended") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.extended } fn make_run(run: RunConfig<'_>) { @@ -2382,14 +2417,16 @@ impl Step for LlvmTools { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = should_build_extended_tool(run.builder, "llvm-tools"); - let mut run = run.alias("llvm-tools"); for tool in LLVM_TOOLS { run = run.alias(tool); } - run.default_condition(default) + run + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + should_build_extended_tool(builder, "llvm-tools") } fn make_run(run: RunConfig<'_>) { @@ -2486,8 +2523,11 @@ impl Step for LlvmBitcodeLinker { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker"); - run.alias("llvm-bitcode-linker").default_condition(default) + run.alias("llvm-bitcode-linker") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + should_build_extended_tool(builder, "llvm-bitcode-linker") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 30e7fbb265ac4..27398b452463b 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -35,8 +35,11 @@ macro_rules! book { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path($path).default_condition(builder.config.docs) + run.path($path) + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -88,8 +91,11 @@ impl Step for UnstableBook { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/doc/unstable-book").default_condition(builder.config.docs) + run.path("src/doc/unstable-book") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -216,8 +222,11 @@ impl Step for TheBook { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/doc/book").default_condition(builder.config.docs) + run.path("src/doc/book") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -340,8 +349,11 @@ impl Step for Standalone { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/doc").alias("standalone").default_condition(builder.config.docs) + run.path("src/doc").alias("standalone") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -450,8 +462,11 @@ impl Step for Releases { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("RELEASES.md").alias("releases").default_condition(builder.config.docs) + run.path("RELEASES.md").alias("releases") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -634,8 +649,11 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.crate_or_deps("sysroot").path("library").default_condition(builder.config.docs) + run.crate_or_deps("sysroot").path("library") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -862,10 +880,11 @@ impl Step for Rustc { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.crate_or_deps("rustc-main") - .path("compiler") - .default_condition(builder.config.compiler_docs) + run.crate_or_deps("rustc-main").path("compiler") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.compiler_docs } fn make_run(run: RunConfig<'_>) { @@ -1009,8 +1028,11 @@ macro_rules! tool_doc { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path($path).default_condition(builder.config.compiler_docs) + run.path($path) + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.compiler_docs } fn make_run(run: RunConfig<'_>) { @@ -1210,8 +1232,11 @@ impl Step for ErrorIndex { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/tools/error_index_generator").default_condition(builder.config.docs) + run.path("src/tools/error_index_generator") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -1255,8 +1280,11 @@ impl Step for UnstableBookGen { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/tools/unstable-book-gen").default_condition(builder.config.docs) + run.path("src/tools/unstable-book-gen") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -1322,8 +1350,11 @@ impl Step for RustcBook { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/doc/rustc").default_condition(builder.config.docs) + run.path("src/doc/rustc") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -1418,8 +1449,11 @@ impl Step for Reference { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/doc/reference").default_condition(builder.config.docs) + run.path("src/doc/reference") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index ce68dbf5a2010..9e1050b85d1af 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -185,8 +185,12 @@ macro_rules! install { $(const $c: bool = true;)* fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let $_config = &run.builder.config; - run.$condition_name($path_or_alias).default_condition($default_cond) + run.$condition_name($path_or_alias) + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + let $_config = &builder.config; + $default_cond } fn make_run(run: RunConfig<'_>) { @@ -311,9 +315,12 @@ impl Step for Src { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let config = &run.builder.config; - let cond = config.extended && config.tools.as_ref().is_none_or(|t| t.contains("src")); - run.path("src").default_condition(cond) + run.path("src") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + let config = &builder.config; + config.extended && config.tools.as_ref().is_none_or(|t| t.contains("src")) } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 9c9bb7cc1ed3f..e9b4b5207e2f5 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -171,9 +171,11 @@ You can skip linkcheck with --skip src/tools/linkchecker" } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - let run = run.path("src/tools/linkchecker"); - run.default_condition(builder.config.docs) + run.path("src/tools/linkchecker") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.docs } fn make_run(run: RunConfig<'_>) { @@ -186,7 +188,9 @@ You can skip linkcheck with --skip src/tools/linkchecker" } fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool { - command("tidy").allow_failure().arg("--version").run_capture_stdout(builder).is_success() + *builder.html_tidy_is_available_memo.get_or_init(|| { + command("tidy").allow_failure().arg("--version").run_capture_stdout(builder).is_success() + }) } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -200,9 +204,11 @@ impl Step for HtmlCheck { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - let run = run.path("src/tools/html-checker"); - run.lazy_default_condition(Box::new(|| check_if_tidy_is_installed(builder))) + run.path("src/tools/html-checker") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + check_if_tidy_is_installed(builder) } fn make_run(run: RunConfig<'_>) { @@ -990,8 +996,11 @@ impl Step for RustdocJSStd { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = run.builder.config.nodejs.is_some(); - run.suite_path("tests/rustdoc-js-std").default_condition(default) + run.suite_path("tests/rustdoc-js-std") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.nodejs.is_some() } fn make_run(run: RunConfig<'_>) { @@ -1051,8 +1060,11 @@ impl Step for RustdocJSNotStd { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = run.builder.config.nodejs.is_some(); - run.suite_path("tests/rustdoc-js").default_condition(default) + run.suite_path("tests/rustdoc-js") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.nodejs.is_some() } fn make_run(run: RunConfig<'_>) { @@ -1094,6 +1106,13 @@ fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option) -> bool { + *builder.browser_ui_test_is_available_memo.get_or_init(|| { + let Some(npm) = builder.config.npm.as_deref() else { return false }; + get_browser_ui_test_version(builder, npm).is_some() + }) +} + /// Run GUI tests on a given rustdoc. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustdocGUI { @@ -1108,18 +1127,13 @@ impl Step for RustdocGUI { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - let run = run.suite_path("tests/rustdoc-gui"); - run.lazy_default_condition(Box::new(move || { - builder.config.nodejs.is_some() - && builder.doc_tests != DocTests::Only - && builder - .config - .npm - .as_ref() - .map(|p| get_browser_ui_test_version(builder, p).is_some()) - .unwrap_or(false) - })) + run.suite_path("tests/rustdoc-gui") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.config.nodejs.is_some() + && builder.doc_tests != DocTests::Only + && check_if_browser_ui_test_is_available(builder) } fn make_run(run: RunConfig<'_>) { @@ -1311,8 +1325,11 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = run.builder.doc_tests != DocTests::Only; - run.path("src/tools/tidy").default_condition(default) + run.path("src/tools/tidy") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.doc_tests != DocTests::Only } fn make_run(run: RunConfig<'_>) { @@ -3349,11 +3366,14 @@ impl Step for BootstrapPy { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("bootstrap-py") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { // Bootstrap tests might not be perfectly self-contained and can depend // on the environment, so only run them by default in CI, not locally. // See `test::Bootstrap::should_run`. - let is_ci = run.builder.config.is_running_on_ci; - run.alias("bootstrap-py").default_condition(is_ci) + builder.config.is_running_on_ci } fn make_run(run: RunConfig<'_>) { @@ -3424,11 +3444,14 @@ impl Step for Bootstrap { } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/bootstrap") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { // Bootstrap tests might not be perfectly self-contained and can depend on the external // environment, submodules that are checked out, etc. // Therefore we only run them by default on CI. - let runs_on_ci = run.builder.config.is_running_on_ci; - run.path("src/bootstrap").default_condition(runs_on_ci) + builder.config.is_running_on_ci } fn make_run(run: RunConfig<'_>) { @@ -3502,10 +3525,13 @@ impl Step for LintDocs { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let stage = run.builder.top_stage; + run.path("src/tools/lint-docs") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { // Lint docs tests might not work with stage 1, so do not run this test by default in // `x test` below stage 2. - run.path("src/tools/lint-docs").default_condition(stage > 1) + builder.top_stage >= 2 } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 79df9d3a49da2..83c38acdf2825 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -808,8 +808,11 @@ impl Step for Cargo { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/tools/cargo").default_condition(builder.tool_enabled("cargo")) + run.path("src/tools/cargo") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.tool_enabled("cargo") } fn make_run(run: RunConfig<'_>) { @@ -1030,8 +1033,11 @@ impl Step for RustAnalyzer { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; - run.path("src/tools/rust-analyzer").default_condition(builder.tool_enabled("rust-analyzer")) + run.path("src/tools/rust-analyzer") + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.tool_enabled("rust-analyzer") } fn make_run(run: RunConfig<'_>) { @@ -1083,14 +1089,14 @@ impl Step for RustAnalyzerProcMacroSrv { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; // Allow building `rust-analyzer-proc-macro-srv` both as part of the `rust-analyzer` and as a stand-alone tool. run.path("src/tools/rust-analyzer") .path("src/tools/rust-analyzer/crates/proc-macro-srv-cli") - .default_condition( - builder.tool_enabled("rust-analyzer") - || builder.tool_enabled("rust-analyzer-proc-macro-srv"), - ) + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.tool_enabled("rust-analyzer") + || builder.tool_enabled("rust-analyzer-proc-macro-srv") } fn make_run(run: RunConfig<'_>) { @@ -1173,9 +1179,11 @@ impl Step for LlvmBitcodeLinker { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let builder = run.builder; run.path("src/tools/llvm-bitcode-linker") - .default_condition(builder.tool_enabled("llvm-bitcode-linker")) + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + builder.tool_enabled("llvm-bitcode-linker") } fn make_run(run: RunConfig<'_>) { @@ -1386,8 +1394,14 @@ macro_rules! tool_rustc_extended { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { should_run_extended_rustc_tool( run, - $tool_name, $path, + ) + } + + fn is_really_default(builder: &Builder<'_>) -> bool { + is_really_default_extended_rustc_tool( + builder, + $tool_name, $stable, ) } @@ -1421,28 +1435,28 @@ macro_rules! tool_rustc_extended { } } -fn should_run_extended_rustc_tool<'a>( - run: ShouldRun<'a>, +fn should_run_extended_rustc_tool<'a>(run: ShouldRun<'a>, path: &'static str) -> ShouldRun<'a> { + run.path(path) +} + +fn is_really_default_extended_rustc_tool( + builder: &Builder<'_>, tool_name: &'static str, - path: &'static str, stable: bool, -) -> ShouldRun<'a> { - let builder = run.builder; - run.path(path).default_condition( - builder.config.extended - && builder.config.tools.as_ref().map_or( - // By default, on nightly/dev enable all tools, else only - // build stable tools. - stable || builder.build.unstable_features(), - // If `tools` is set, search list for this tool. - |tools| { - tools.iter().any(|tool| match tool.as_ref() { - "clippy" => tool_name == "clippy-driver", - x => tool_name == x, - }) - }, - ), - ) +) -> bool { + builder.config.extended + && builder.config.tools.as_ref().map_or( + // By default, on nightly/dev enable all tools, else only + // build stable tools. + stable || builder.build.unstable_features(), + // If `tools` is set, search list for this tool. + |tools| { + tools.iter().any(|tool| match tool.as_ref() { + "clippy" => tool_name == "clippy-driver", + x => tool_name == x, + }) + }, + ) } fn build_extended_rustc_tool( diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index 72250a26f376e..f6bebfdae9cba 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -57,7 +57,7 @@ impl Step for Vendor { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.alias("placeholder").default_condition(true) + run.alias("placeholder") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/builder/cli_paths.rs b/src/bootstrap/src/core/builder/cli_paths.rs index fef1979465e8b..e23cc3a6e1823 100644 --- a/src/bootstrap/src/core/builder/cli_paths.rs +++ b/src/bootstrap/src/core/builder/cli_paths.rs @@ -136,7 +136,7 @@ pub(crate) fn match_paths_to_steps_and_run( if paths.is_empty() || builder.config.include_default_paths { for StepExtra { desc, should_run } in &steps { - if desc.default && should_run.is_really_default() { + if desc.default && (desc.is_really_default_fn)(builder) { desc.maybe_run(builder, should_run.paths.iter().cloned().collect()); } } diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 9124442e7f376..166fd6596a5b7 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -5,7 +5,7 @@ use std::fmt::{Debug, Write}; use std::hash::Hash; use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::sync::{LazyLock, OnceLock}; +use std::sync::OnceLock; use std::time::{Duration, Instant}; use std::{env, fs}; @@ -67,6 +67,11 @@ pub struct Builder<'a> { /// Cached list of submodules from self.build.src. submodule_paths_cache: OnceLock>, + /// Caches the check for whether `tidy` (HTML Tidy) is installed. + pub(crate) html_tidy_is_available_memo: OnceLock, + /// Caches the check for whether `https://www.npmjs.com/package/browser-ui-test` is installed. + pub(crate) browser_ui_test_is_available_memo: OnceLock, + /// When enabled by tests, this causes the top-level steps that _would_ be /// executed to be logged instead. Used by snapshot tests of command-line /// paths-to-steps handling. @@ -104,8 +109,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// Whether this step is run by default as part of its respective phase, as defined by the `describe` /// macro in [`Builder::get_step_descriptions`]. /// - /// Note: Even if set to `true`, it can still be overridden with [`ShouldRun::default_condition`] - /// by `Step::should_run`. + /// Note: Even if set to `true`, it can still be overridden by [`Step::is_really_default`]. const DEFAULT: bool = false; /// If this value is true, then the values of `run.target` passed to the `make_run` function of @@ -131,7 +135,26 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// depending on the `Step::run` implementation of the caller. fn run(self, builder: &Builder<'_>) -> Self::Output; - /// Determines if this `Step` should be run when given specific paths (e.g., `x build $path`). + /// Some steps that are marked `DEFAULT = true` want to only be treated as + /// default steps on a conditional basis, depending on factors like config + /// settings or the availability of external tools. + /// + /// Those steps can override this function, which will be called just before + /// the step would actually be run as part of the default set of steps, so + /// that the step can conditionally decide whether to run or not. + /// + /// If the underlying check should not be performed repeatedly + /// (e.g. because it probes command-line tools), + /// consider memoizing its outcome via a field in the builder. + fn is_really_default(builder: &Builder<'_>) -> bool { + // This default impl doesn't use the builder, but we want it to be + // named `builder` for IDE autocompletion. + let _ = builder; + Self::DEFAULT + } + + /// Called to allow steps to register the command-line paths that should + /// cause them to run. fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_>; /// Called directly by the bootstrap `Step` handler when not triggered indirectly by other `Step`s using [`Builder::ensure`]. @@ -316,6 +339,7 @@ struct StepDescription { default: bool, is_host: bool, should_run: fn(ShouldRun<'_>) -> ShouldRun<'_>, + is_really_default_fn: fn(&Builder<'_>) -> bool, make_run: fn(RunConfig<'_>), name: &'static str, kind: Kind, @@ -437,6 +461,7 @@ impl StepDescription { default: S::DEFAULT, is_host: S::IS_HOST, should_run: S::should_run, + is_really_default_fn: S::is_really_default, make_run: S::make_run, name: std::any::type_name::(), kind, @@ -488,48 +513,23 @@ impl StepDescription { } } -enum ReallyDefault<'a> { - Bool(bool), - Lazy(LazyLock bool + 'a>>), -} - +/// Builder that allows steps to register command-line paths/aliases that +/// should cause those steps to be run. +/// +/// For example, if the user invokes `./x test compiler` or `./x doc unstable-book`, +/// this allows bootstrap to determine what steps "compiler" or "unstable-book" +/// correspond to. pub struct ShouldRun<'a> { pub builder: &'a Builder<'a>, kind: Kind, // use a BTreeSet to maintain sort order paths: BTreeSet, - - // If this is a default rule, this is an additional constraint placed on - // its run. Generally something like compiler docs being enabled. - is_really_default: ReallyDefault<'a>, } impl<'a> ShouldRun<'a> { fn new(builder: &'a Builder<'_>, kind: Kind) -> ShouldRun<'a> { - ShouldRun { - builder, - kind, - paths: BTreeSet::new(), - is_really_default: ReallyDefault::Bool(true), // by default no additional conditions - } - } - - pub fn default_condition(mut self, cond: bool) -> Self { - self.is_really_default = ReallyDefault::Bool(cond); - self - } - - pub fn lazy_default_condition(mut self, lazy_cond: Box bool + 'a>) -> Self { - self.is_really_default = ReallyDefault::Lazy(LazyLock::new(lazy_cond)); - self - } - - pub fn is_really_default(&self) -> bool { - match &self.is_really_default { - ReallyDefault::Bool(val) => *val, - ReallyDefault::Lazy(lazy) => *lazy.deref(), - } + ShouldRun { builder, kind, paths: BTreeSet::new() } } /// Indicates it should run if the command-line selects the given crate or @@ -1092,6 +1092,8 @@ impl<'a> Builder<'a> { time_spent_on_dependencies: Cell::new(Duration::new(0, 0)), paths, submodule_paths_cache: Default::default(), + html_tidy_is_available_memo: OnceLock::new(), + browser_ui_test_is_available_memo: OnceLock::new(), log_cli_step_for_tests: None, } } @@ -1648,7 +1650,11 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler } // Only execute if it's supposed to run as default - if desc.default && should_run.is_really_default() { Some(self.ensure(step)) } else { None } + if desc.default && (desc.is_really_default_fn)(self) { + Some(self.ensure(step)) + } else { + None + } } /// Checks if any of the "should_run" paths is in the `Builder` paths.