From a67c933fe6d4f5ec884367840b7b38dd368be86e Mon Sep 17 00:00:00 2001 From: Ross Sullivan Date: Mon, 27 Apr 2026 22:28:48 +0900 Subject: [PATCH 1/5] Enable Cargo's new build-dir layout in boostrap --- src/bootstrap/src/core/build_steps/compile.rs | 21 ++++++++++++------- src/bootstrap/src/core/build_steps/tool.rs | 21 +++++++++++++++++-- src/bootstrap/src/core/builder/cargo.rs | 2 ++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 46d05b9d5d2f7..c2616827439f9 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -2652,8 +2652,8 @@ pub fn run_cargo( ) -> Vec { // `target_root_dir` looks like $dir/$target/release let target_root_dir = stamp.path().parent().unwrap(); - // `target_deps_dir` looks like $dir/$target/release/deps - let target_deps_dir = target_root_dir.join("deps"); + // `target_build_dir` looks like $dir/$target/release/build + let target_build_dir = target_root_dir.join("build"); // `host_root_dir` looks like $dir/release let host_root_dir = target_root_dir .parent() @@ -2724,7 +2724,7 @@ pub fn run_cargo( // If this was output in the `deps` dir then this is a precise file // name (hash included) so we start tracking it. - if filename.starts_with(&target_deps_dir) { + if filename.starts_with(&target_build_dir) { deps.push((filename.to_path_buf(), DependencyType::Target)); continue; } @@ -2759,11 +2759,18 @@ pub fn run_cargo( // Ok now we need to actually find all the files listed in `toplevel`. We've // got a list of prefix/extensions and we basically just need to find the - // most recent file in the `deps` folder corresponding to each one. - let contents = target_deps_dir + // most recent file in the `build` folder corresponding to each one. + // + // Cargo's build folder is structured as `build///out/` so + // we need to traverse multiple directory layers to get to actual files. + let read_dir = |path: &Path| path.read_dir().ok().into_iter().flatten().filter_map(Result::ok); + let contents = target_build_dir .read_dir() - .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e)) - .map(|e| t!(e)) + .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_build_dir.display(), e)) + .map(|e| e.unwrap()) + .flat_map(|e| read_dir(&e.path())) + .flat_map(|e| read_dir(&e.path())) + .flat_map(|e| read_dir(&e.path())) .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata()))) .collect::>(); for (prefix, extension, expected_len) in toplevel { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index e6148af617674..04668a86172ec 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -10,7 +10,7 @@ //! return `ToolBuildResult` and should never prepare `cargo` invocations manually. use std::ffi::OsStr; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::{env, fs}; use crate::core::build_steps::compile::is_lto_stage; @@ -1623,7 +1623,7 @@ impl Builder<'_> { // Notably this munges the dynamic library lookup path to point to the // right location to run `compiler`. let mut lib_paths: Vec = - vec![self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("deps")]; + discover_out_dirs(self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("build")); // On MSVC a tool may invoke a C compiler (e.g., compiletest in run-make // mode) and that C compiler may need some extra PATH modification. Do @@ -1651,3 +1651,20 @@ impl Builder<'_> { cmd } } + +/// Gets all of the `out` dirs in a given Cargo `build-dir//build` dir. +fn discover_out_dirs(dir: PathBuf) -> Vec { + if !dir.exists() { + return Vec::new(); + } + + let read_dir = |path: &Path| path.read_dir().ok().into_iter().flatten().filter_map(Result::ok); + dir.read_dir() + .unwrap_or_else(|e| panic!("Couldn't read {}: {}", dir.display(), e)) + .map(|e| e.unwrap()) + .flat_map(|e| read_dir(&e.path())) + .flat_map(|e| read_dir(&e.path())) + .map(|e| e.path()) + .filter(|path| path.ends_with("out")) + .collect::>() +} diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 473c5f3e0faab..ea2352d1b5e77 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -596,6 +596,8 @@ impl Builder<'_> { let mut hostflags = HostFlags::default(); + cargo.arg("-Zbuild-dir-new-layout"); + // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, // so we need to explicitly clear out if they've been updated. for backend in self.codegen_backends(compiler) { From 0c79f672e1063178573bac8411fdbffefb089212 Mon Sep 17 00:00:00 2001 From: Ross Sullivan Date: Thu, 30 Apr 2026 01:05:08 +0900 Subject: [PATCH 2/5] test: Enable Cargo's new layout in tests --- src/tools/compiletest/src/runtest/run_make.rs | 33 +++++++++++++++---- src/tools/miri/test-cargo-miri/run-test.py | 2 +- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 1044683ae6426..7c56fd345e5ff 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -1,3 +1,4 @@ +use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; use std::{env, fs}; @@ -66,8 +67,8 @@ impl TestCx<'_> { // build// // ├── bootstrap-tools/ // │ ├── /release/librun_make_support.rlib // <- support rlib itself - // │ ├── /release/deps/ // <- deps - // │ └── release/deps/ // <- deps of deps + // │ ├── /release/build///out // <- deps + // │ └── release/build///out // <- deps of deps // ``` // // FIXME(jieyouxu): there almost certainly is a better way to do this (specifically how the @@ -77,8 +78,8 @@ impl TestCx<'_> { let support_host_path = tools_bin.join(&self.config.host).join("release"); let support_lib_path = support_host_path.join("librun_make_support.rlib"); - let support_lib_deps = support_host_path.join("deps"); - let support_lib_deps_deps = tools_bin.join("release").join("deps"); + let support_lib_deps = discover_out_dirs(support_host_path.join("build")); + let support_lib_deps_deps = discover_out_dirs(tools_bin.join("release").join("build")); // To compile the recipe with rustc, we need to provide suitable dynamic library search // paths to rustc. This includes both: @@ -100,6 +101,10 @@ impl TestCx<'_> { p }; + let out_dirs_to_args = |paths: Vec| { + paths.into_iter().map(|p| format!("-Ldependency={}", p.display())).collect::>() + }; + // run-make-support and run-make tests are compiled using the stage0 compiler // If the stage is 0, then the compiler that we test (either bootstrap or an explicitly // set compiler) is the one that actually compiled run-make-support. @@ -119,8 +124,8 @@ impl TestCx<'_> { .arg(&recipe_bin) // Specify library search paths for `run_make_support`. .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap())) - .arg(format!("-Ldependency={}", &support_lib_deps)) - .arg(format!("-Ldependency={}", &support_lib_deps_deps)) + .args(out_dirs_to_args(support_lib_deps)) + .args(out_dirs_to_args(support_lib_deps_deps)) // Provide `run_make_support` as extern prelude, so test writers don't need to write // `extern run_make_support;`. .arg("--extern") @@ -337,3 +342,19 @@ impl TestCx<'_> { } } } + +/// Gets all of the `out` dirs in a given Cargo `build-dir//build` dir. +fn discover_out_dirs(dir: Utf8PathBuf) -> Vec { + let read_dir = |path: &Path| path.read_dir().ok().into_iter().flatten().filter_map(Result::ok); + let contents = dir + .read_dir() + .unwrap_or_else(|e| panic!("Couldn't read {}: {}", dir, e)) + .map(|e| e.unwrap()) + .flat_map(|e| read_dir(&e.path())) + .flat_map(|e| read_dir(&e.path())) + .map(|e| e.path()) + .filter(|path| path.ends_with("out")) + .collect::>(); + + return contents; +} diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py index 6b3b6343b8258..bf1272f5bca0b 100755 --- a/src/tools/miri/test-cargo-miri/run-test.py +++ b/src/tools/miri/test-cargo-miri/run-test.py @@ -215,7 +215,7 @@ def test_cargo_miri_multi_target(): if os.listdir(target_dir) != ["miri"]: fail(f"`{target_dir}` contains unexpected files") # Ensure something exists inside that target dir. - os.access(os.path.join(target_dir, "miri", "debug", "deps"), os.F_OK) + os.access(os.path.join(target_dir, "miri", "debug"), os.F_OK) print("\nTEST SUCCESSFUL!") sys.exit(0) From 0fd06e334a39548c3e03029bc6e2c197a5b14e6b Mon Sep 17 00:00:00 2001 From: Ross Sullivan Date: Thu, 30 Apr 2026 01:17:54 +0900 Subject: [PATCH 3/5] test: Add support for cargo's build-dir v2 layout (rustfmt) --- src/tools/rustfmt/src/test/mod.rs | 19 +++++++++++++++++-- src/tools/rustfmt/tests/cargo-fmt/main.rs | 9 +++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs index 36e6aa84fc2d5..4eded7c49eb50 100644 --- a/src/tools/rustfmt/src/test/mod.rs +++ b/src/tools/rustfmt/src/test/mod.rs @@ -1077,8 +1077,23 @@ fn rustfmt() -> PathBuf { let mut me = env::current_exe().expect("failed to get current executable"); // Chop of the test name. me.pop(); - // Chop off `deps`. - me.pop(); + + // Handle Cargo's old and new filesystem layouts + // * v1: `target//deps/test-bin-[HASH][EXE]` + // * v2: `target//build//[HASH]/out/test-bin-[HASH][EXE]` + if me.ends_with("deps") { + // Chop off `deps`. + me.pop(); + } else if me.ends_with("out") { + // Chop off `out`. + me.pop(); + // Chop off ``. + me.pop(); + // Chop off ``. + me.pop(); + // Chop off `build`. + me.pop(); + } me.push("rustfmt"); assert!( diff --git a/src/tools/rustfmt/tests/cargo-fmt/main.rs b/src/tools/rustfmt/tests/cargo-fmt/main.rs index dcdbca07a77c9..63cc12521a8f7 100644 --- a/src/tools/rustfmt/tests/cargo-fmt/main.rs +++ b/src/tools/rustfmt/tests/cargo-fmt/main.rs @@ -10,8 +10,17 @@ use rustfmt_config_proc_macro::rustfmt_only_ci_test; fn cargo_fmt(args: &[&str]) -> (String, String) { let mut bin_dir = env::current_exe().unwrap(); bin_dir.pop(); // chop off test exe name + + // Handle Cargo's old and new filesystem layouts + // * v1: `target//deps/test-bin-[HASH][EXE]` + // * v2: `target//build//[HASH]/out/test-bin-[HASH][EXE]` if bin_dir.ends_with("deps") { bin_dir.pop(); + } else if bin_dir.ends_with("out") { + bin_dir.pop(); // chop off `out` + bin_dir.pop(); // chop off `` + bin_dir.pop(); // chop off `` + bin_dir.pop(); // chop off `build` } let cmd = bin_dir.join(format!("cargo-fmt{}", env::consts::EXE_SUFFIX)); From 4a1caec3ad95174462c9acad0312328243948908 Mon Sep 17 00:00:00 2001 From: Ross Sullivan Date: Thu, 30 Apr 2026 01:21:21 +0900 Subject: [PATCH 4/5] chore: Move CI to use Cargo's v2 layout (rustfmt) This also syncs `RUSTFLAGS: -D warnings` which is added in rust-lang/rustfmt --- src/tools/rustfmt/.github/workflows/linux.yml | 3 +++ src/tools/rustfmt/.github/workflows/mac.yml | 3 +++ src/tools/rustfmt/.github/workflows/windows.yml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/tools/rustfmt/.github/workflows/linux.yml b/src/tools/rustfmt/.github/workflows/linux.yml index 369b048f12fec..c8cbf00804bc3 100644 --- a/src/tools/rustfmt/.github/workflows/linux.yml +++ b/src/tools/rustfmt/.github/workflows/linux.yml @@ -36,4 +36,7 @@ jobs: rustup target add ${{ matrix.target }} - name: Build and Test + env: + RUSTFLAGS: -D warnings + CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT: true run: ./ci/build_and_test.sh diff --git a/src/tools/rustfmt/.github/workflows/mac.yml b/src/tools/rustfmt/.github/workflows/mac.yml index b2e8401131b73..0838800dff06e 100644 --- a/src/tools/rustfmt/.github/workflows/mac.yml +++ b/src/tools/rustfmt/.github/workflows/mac.yml @@ -32,4 +32,7 @@ jobs: rustup target add ${{ matrix.target }} - name: Build and Test + env: + RUSTFLAGS: -D warnings + CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT: true run: ./ci/build_and_test.sh diff --git a/src/tools/rustfmt/.github/workflows/windows.yml b/src/tools/rustfmt/.github/workflows/windows.yml index ef8d54fb93f57..af47fddcf59e1 100644 --- a/src/tools/rustfmt/.github/workflows/windows.yml +++ b/src/tools/rustfmt/.github/workflows/windows.yml @@ -59,4 +59,7 @@ jobs: - name: Build and Test shell: cmd + env: + RUSTFLAGS: -D warnings + CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT: true run: ci\build_and_test.bat From 8f955464486abe410e28a7761cfa90dade650955 Mon Sep 17 00:00:00 2001 From: Ross Sullivan Date: Fri, 1 May 2026 11:25:01 +0900 Subject: [PATCH 5/5] tmp: Enable CARGO_LOG fingerprint logging to debug ci --- src/bootstrap/src/core/builder/cargo.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index ea2352d1b5e77..d5a3cca66eaab 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1216,10 +1216,10 @@ impl Builder<'_> { cargo.env("RUSTC_BACKTRACE_ON_ICE", "1"); } - if self.verbosity >= 2 { - // This provides very useful logs especially when debugging build cache-related stuff. - cargo.env("CARGO_LOG", "cargo::core::compiler::fingerprint=info"); - } + // if self.verbosity >= 2 { + // This provides very useful logs especially when debugging build cache-related stuff. + cargo.env("CARGO_LOG", "cargo::core::compiler::fingerprint=info"); + // } cargo.env("RUSTC_VERBOSE", self.verbosity.to_string());