diff --git a/crates/cargo-test-support/src/compare.rs b/crates/cargo-test-support/src/compare.rs index 2338d81ce7d..6d3df478f5a 100644 --- a/crates/cargo-test-support/src/compare.rs +++ b/crates/cargo-test-support/src/compare.rs @@ -235,6 +235,9 @@ fn add_regex_redactions(subs: &mut snapbox::Redactions) { // Match file name hashes like `foo-06b451d0d6f88b1d` subs.insert("[HASH]", regex!(r"[a-z0-9]+-(?[a-f0-9]{16})")) .unwrap(); + // Match path hashes like `../06b451d0d6f88b1d/..` used in directory paths + subs.insert("[HASH]", regex!(r"\/(?[0-9a-f]{16})\/")) + .unwrap(); subs.insert( "[AVG_ELAPSED]", regex!(r"(?[0-9]+(\.[0-9]+)?) ns/iter"), diff --git a/src/cargo/core/compiler/build_runner/compilation_files.rs b/src/cargo/core/compiler/build_runner/compilation_files.rs index f70a870cf46..23ea9867fd4 100644 --- a/src/cargo/core/compiler/build_runner/compilation_files.rs +++ b/src/cargo/core/compiler/build_runner/compilation_files.rs @@ -230,17 +230,21 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { self.export_dir.clone() } - /// Directory name to use for a package in the form `NAME-HASH`. + /// Directory name to use for a package in the form `{NAME}/{HASH}`. /// /// Note that some units may share the same directory, so care should be /// taken in those cases! fn pkg_dir(&self, unit: &Unit) -> String { + let seperator = match self.ws.gctx().cli_unstable().build_dir_new_layout { + true => "/", + false => "-", + }; let name = unit.pkg.package_id().name(); let meta = self.metas[unit]; if let Some(c_extra_filename) = meta.c_extra_filename() { - format!("{}-{}", name, c_extra_filename) + format!("{}{}{}", name, seperator, c_extra_filename) } else { - format!("{}-{}", name, self.target_short_hash(unit)) + format!("{}{}{}", name, seperator, self.target_short_hash(unit)) } } @@ -255,20 +259,27 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { } /// Returns the host `deps` directory path. - pub fn host_deps(&self) -> &Path { - self.host.deps() + pub fn host_deps(&self, unit: &Unit) -> PathBuf { + let dir = self.pkg_dir(unit); + self.host.deps(&dir) } /// Returns the directories where Rust crate dependencies are found for the /// specified unit. - pub fn deps_dir(&self, unit: &Unit) -> &Path { - self.layout(unit.kind).deps() + pub fn deps_dir(&self, unit: &Unit) -> PathBuf { + let dir = self.pkg_dir(unit); + self.layout(unit.kind).deps(&dir) } /// Directory where the fingerprint for the given unit should go. pub fn fingerprint_dir(&self, unit: &Unit) -> PathBuf { let dir = self.pkg_dir(unit); - self.layout(unit.kind).fingerprint().join(dir) + self.layout(unit.kind).fingerprint(&dir) + } + + /// Directory where incremental output for the given unit should go. + pub fn incremental_dir(&self, unit: &Unit) -> &Path { + self.layout(unit.kind).incremental() } /// Returns the path for a file in the fingerprint directory. @@ -303,7 +314,7 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { assert!(!unit.mode.is_run_custom_build()); assert!(self.metas.contains_key(unit)); let dir = self.pkg_dir(unit); - self.layout(CompileKind::Host).build().join(dir) + self.layout(CompileKind::Host).build_script(&dir) } /// Returns the directory for compiled artifacts files. @@ -337,7 +348,7 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { assert!(unit.target.is_custom_build()); assert!(unit.mode.is_run_custom_build()); let dir = self.pkg_dir(unit); - self.layout(unit.kind).build().join(dir) + self.layout(unit.kind).build_script_execution(&dir) } /// Returns the "`OUT_DIR`" directory for running a build script. diff --git a/src/cargo/core/compiler/build_runner/mod.rs b/src/cargo/core/compiler/build_runner/mod.rs index f6f2a287137..bb3bf67fe2e 100644 --- a/src/cargo/core/compiler/build_runner/mod.rs +++ b/src/cargo/core/compiler/build_runner/mod.rs @@ -10,6 +10,7 @@ use crate::core::compiler::{self, Unit, artifact}; use crate::util::cache_lock::CacheLockMode; use crate::util::errors::CargoResult; use anyhow::{Context as _, bail}; +use cargo_util::paths; use filetime::FileTime; use itertools::Itertools; use jobserver::Client; @@ -401,9 +402,17 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> { self.compilation .root_output .insert(kind, layout.dest().to_path_buf()); - self.compilation - .deps_output - .insert(kind, layout.deps().to_path_buf()); + if self.bcx.gctx.cli_unstable().build_dir_new_layout { + for (unit, _) in self.bcx.unit_graph.iter() { + let dep_dir = self.files().deps_dir(unit); + paths::create_dir_all(&dep_dir)?; + self.compilation.deps_output.insert(kind, dep_dir); + } + } else { + self.compilation + .deps_output + .insert(kind, layout.legacy_deps().to_path_buf()); + } } Ok(()) } diff --git a/src/cargo/core/compiler/layout.rs b/src/cargo/core/compiler/layout.rs index b1d54c85e4a..6049e90ec22 100644 --- a/src/cargo/core/compiler/layout.rs +++ b/src/cargo/core/compiler/layout.rs @@ -142,6 +142,7 @@ pub struct Layout { /// Will be `None` when the build-dir and target-dir are the same path as we cannot /// lock the same path twice. _build_lock: Option, + is_new_layout: bool, } impl Layout { @@ -156,6 +157,7 @@ impl Layout { target: Option, dest: &str, ) -> CargoResult { + let is_new_layout = ws.gctx().cli_unstable().build_dir_new_layout; let mut root = ws.target_dir(); let mut build_root = ws.build_dir(); if let Some(target) = target { @@ -212,14 +214,17 @@ impl Layout { dest, _lock: lock, _build_lock: build_lock, + is_new_layout, }) } /// Makes sure all directories stored in the Layout exist on the filesystem. pub fn prepare(&mut self) -> CargoResult<()> { - paths::create_dir_all(&self.deps)?; + if !self.is_new_layout { + paths::create_dir_all(&self.deps)?; + paths::create_dir_all(&self.fingerprint)?; + } paths::create_dir_all(&self.incremental)?; - paths::create_dir_all(&self.fingerprint)?; paths::create_dir_all(&self.examples)?; paths::create_dir_all(&self.build_examples)?; paths::create_dir_all(&self.build)?; @@ -232,7 +237,15 @@ impl Layout { &self.dest } /// Fetch the deps path. - pub fn deps(&self) -> &Path { + pub fn deps(&self, pkg_dir: &str) -> PathBuf { + if self.is_new_layout { + self.build_unit(pkg_dir).join("deps") + } else { + self.legacy_deps().to_path_buf() + } + } + /// Fetch the deps path. (old layout) + pub fn legacy_deps(&self) -> &Path { &self.deps } /// Fetch the examples path. @@ -256,17 +269,45 @@ impl Layout { &self.incremental } /// Fetch the fingerprint path. - pub fn fingerprint(&self) -> &Path { + pub fn fingerprint(&self, pkg_dir: &str) -> PathBuf { + if self.is_new_layout { + self.build_unit(pkg_dir).join("fingerprint") + } else { + self.legacy_fingerprint().to_path_buf().join(pkg_dir) + } + } + /// Fetch the fingerprint path. (old layout) + pub fn legacy_fingerprint(&self) -> &Path { &self.fingerprint } - /// Fetch the build script path. + /// Fetch the build path. pub fn build(&self) -> &Path { &self.build } + /// Fetch the build script path. + pub fn build_script(&self, pkg_dir: &str) -> PathBuf { + if self.is_new_layout { + self.build_unit(pkg_dir).join("build-script") + } else { + self.build().join(pkg_dir) + } + } + /// Fetch the build script execution path. + pub fn build_script_execution(&self, pkg_dir: &str) -> PathBuf { + if self.is_new_layout { + self.build_unit(pkg_dir).join("build-script-execution") + } else { + self.build().join(pkg_dir) + } + } /// Fetch the artifact path. pub fn artifact(&self) -> &Path { &self.artifact } + /// Fetch the build unit path + pub fn build_unit(&self, pkg_dir: &str) -> PathBuf { + self.build().join(pkg_dir) + } /// Create and return the tmp path. pub fn prepare_tmp(&self) -> CargoResult<&Path> { paths::create_dir_all(&self.tmp)?; diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 04cd50fccaa..6fa0945a703 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -56,7 +56,7 @@ pub mod unit_dependencies; pub mod unit_graph; use std::borrow::Cow; -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::env; use std::ffi::{OsStr, OsString}; use std::fmt::Display; @@ -69,6 +69,7 @@ use std::sync::{Arc, LazyLock}; use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; use anyhow::{Context as _, Error}; use cargo_platform::{Cfg, Platform}; +use itertools::Itertools; use lazycell::LazyCell; use regex::Regex; use tracing::{debug, instrument, trace}; @@ -1353,12 +1354,8 @@ fn build_base_args( .map(|s| s.as_ref()), ); if incremental { - let dir = build_runner - .files() - .layout(unit.kind) - .incremental() - .as_os_str(); - opt(cmd, "-C", "incremental=", Some(dir)); + let dir = build_runner.files().incremental_dir(&unit); + opt(cmd, "-C", "incremental=", Some(dir.as_os_str())); } let pkg_hint_mostly_unused = match hints.mostly_unused { @@ -1668,18 +1665,35 @@ fn build_deps_args( unit: &Unit, ) -> CargoResult<()> { let bcx = build_runner.bcx; - cmd.arg("-L").arg(&{ - let mut deps = OsString::from("dependency="); - deps.push(build_runner.files().deps_dir(unit)); - deps - }); + if build_runner.bcx.gctx.cli_unstable().build_dir_new_layout { + let mut map = BTreeMap::new(); + + // Recursively add all depenendency args to rustc process + add_dep_arg(&mut map, build_runner, unit); + + let paths = map.into_iter().map(|(_, path)| path).sorted_unstable(); + + for path in paths { + cmd.arg("-L").arg(&{ + let mut deps = OsString::from("dependency="); + deps.push(path); + deps + }); + } + } else { + cmd.arg("-L").arg(&{ + let mut deps = OsString::from("dependency="); + deps.push(build_runner.files().deps_dir(unit)); + deps + }); + } // Be sure that the host path is also listed. This'll ensure that proc macro // dependencies are correctly found (for reexported macros). if !unit.kind.is_host() { cmd.arg("-L").arg(&{ let mut deps = OsString::from("dependency="); - deps.push(build_runner.files().host_deps()); + deps.push(build_runner.files().host_deps(unit)); deps }); } @@ -1755,6 +1769,21 @@ fn build_deps_args( Ok(()) } +fn add_dep_arg<'a, 'b: 'a>( + map: &mut BTreeMap<&'a Unit, PathBuf>, + build_runner: &'b BuildRunner<'b, '_>, + unit: &'a Unit, +) { + if map.contains_key(&unit) { + return; + } + map.insert(&unit, build_runner.files().deps_dir(&unit)); + + for dep in build_runner.unit_deps(unit) { + add_dep_arg(map, build_runner, &dep.unit); + } +} + /// Adds extra rustc flags and environment variables collected from the output /// of a build-script to the command to execute, include custom environment /// variables and `cfg`. diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 7ab4f75f50a..1ab8dd5e937 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -200,7 +200,7 @@ fn clean_specs( // Clean fingerprints. for (_, layout) in &layouts_with_host { - let dir = escape_glob_path(layout.fingerprint())?; + let dir = escape_glob_path(layout.legacy_fingerprint())?; clean_ctx .rm_rf_package_glob_containing_hash(&pkg.name(), &Path::new(&dir).join(&pkg_dir))?; } @@ -226,8 +226,13 @@ fn clean_specs( CompileMode::Check { test: false }, ] { for (compile_kind, layout) in &layouts { - let triple = target_data.short_name(compile_kind); + if clean_ctx.gctx.cli_unstable().build_dir_new_layout { + let dir = layout.build_unit(&pkg.name()); + clean_ctx.rm_rf_glob(&dir)?; + continue; + } + let triple = target_data.short_name(compile_kind); let (file_types, _unsupported) = target_data .info(*compile_kind) .rustc_outputs(mode, target.kind(), triple, clean_ctx.gctx)?; @@ -236,8 +241,8 @@ fn clean_specs( (layout.build_examples(), Some(layout.examples())) } // Tests/benchmarks are never uplifted. - TargetKind::Test | TargetKind::Bench => (layout.deps(), None), - _ => (layout.deps(), Some(layout.dest())), + TargetKind::Test | TargetKind::Bench => (layout.legacy_deps(), None), + _ => (layout.legacy_deps(), Some(layout.dest())), }; let mut dir_glob_str = escape_glob_path(dir)?; let dir_glob = Path::new(&dir_glob_str); diff --git a/tests/testsuite/build_dir.rs b/tests/testsuite/build_dir.rs index 6af2799037f..5a3f2494939 100644 --- a/tests/testsuite/build_dir.rs +++ b/tests/testsuite/build_dir.rs @@ -11,7 +11,7 @@ use std::path::PathBuf; use crate::prelude::*; -use cargo_test_support::registry::RegistryBuilder; +use cargo_test_support::registry::{Package, RegistryBuilder}; use cargo_test_support::{paths, prelude::*, project, str}; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX, EXE_SUFFIX}; @@ -29,7 +29,10 @@ fn binary_with_debug() { ) .build(); - p.cargo("build").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); assert_not_exists(&p.root().join("target")); @@ -37,12 +40,12 @@ fn binary_with_debug() { [ROOT]/foo/build-dir/.rustc_info.json [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d "#]]); @@ -71,14 +74,17 @@ fn binary_with_release() { ) .build(); - p.cargo("build --release").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build --release") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); assert_exists_patterns_with_base_dir( &p.root(), &[ // Check the pre-uplifted binary in the build-dir - &format!("build-dir/release/deps/foo*{EXE_SUFFIX}"), - "build-dir/release/deps/foo*.d", + &format!("build-dir/release/build/foo/*/deps/foo*{EXE_SUFFIX}"), + "build-dir/release/build/foo/*/deps/foo*.d", // Verify the binary was copied to the target-dir &format!("target-dir/release/foo{EXE_SUFFIX}"), "target-dir/release/foo.d", @@ -88,12 +94,12 @@ fn binary_with_release() { [ROOT]/foo/build-dir/.rustc_info.json [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/release/.cargo-lock -[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/release/deps/foo[..][EXE] -[ROOT]/foo/build-dir/release/deps/foo[..].d +[ROOT]/foo/build-dir/release/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/release/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/build-dir/release/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/release/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/release/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/release/build/foo/[HASH]/deps/foo[..].d "#]]); @@ -172,7 +178,10 @@ fn libs() { ) .build(); - p.cargo("build").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); // Verify lib artifacts were copied into the artifact dir assert_exists_patterns_with_base_dir(&p.root().join("target-dir/debug"), &expected_files); @@ -185,18 +194,21 @@ fn should_default_to_target() { .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) .build(); - p.cargo("build").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); p.root().join("target").assert_build_dir_layout(str![[r#" [ROOT]/foo/target/.rustc_info.json [ROOT]/foo/target/CACHEDIR.TAG [ROOT]/foo/target/debug/.cargo-lock -[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/target/debug/deps/foo[..][EXE] -[ROOT]/foo/target/debug/deps/foo[..].d +[ROOT]/foo/target/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/target/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/target/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/target/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/target/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/target/debug/build/foo/[HASH]/deps/foo[..].d [ROOT]/foo/target/debug/foo[EXE] [ROOT]/foo/target/debug/foo.d @@ -209,7 +221,8 @@ fn should_respect_env_var() { .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) .build(); - p.cargo("build") + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) .env("CARGO_BUILD_BUILD_DIR", "build-dir") .enable_mac_dsym() .run(); @@ -218,12 +231,12 @@ fn should_respect_env_var() { [ROOT]/foo/build-dir/.rustc_info.json [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d "#]]); } @@ -254,32 +267,35 @@ fn build_script_should_output_to_build_dir() { ) .build(); - p.cargo("build").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); p.root().join("build-dir").assert_build_dir_layout(str![[r#" [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/deps/foo[..].d -[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json [ROOT]/foo/build-dir/.rustc_info.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/run-build-script-build-script-build -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/run-build-script-build-script-build.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-build-script-build-script-build -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/build-script-build-script-build -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/build-script-build-script-build.json -[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build_script_build[..].d -[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build_script_build[..][EXE] -[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build-script-build[EXE] -[ROOT]/foo/build-dir/debug/build/foo-[HASH]/out/foo.txt -[ROOT]/foo/build-dir/debug/build/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/build/foo-[HASH]/output -[ROOT]/foo/build-dir/debug/build/foo-[HASH]/stderr -[ROOT]/foo/build-dir/debug/build/foo-[HASH]/root-output +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/run-build-script-build-script-build +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/run-build-script-build-script-build.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-build-script-build-script-build +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/build-script-build-script-build +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/build-script-build-script-build.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/build-script/build_script_build[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/build-script/build_script_build[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/build-script/build-script-build[EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/build-script-execution/out/foo.txt +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/build-script-execution/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/build-script-execution/output +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/build-script-execution/root-output +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/build-script-execution/stderr "#]]); } @@ -311,29 +327,32 @@ fn cargo_tmpdir_should_output_to_build_dir() { ) .build(); - p.cargo("test").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout test") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); p.root().join("build-dir").assert_build_dir_layout(str![[r#" [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d -[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d -[ROOT]/foo/build-dir/debug/deps/foo[..].d -[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE] -[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE] -[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bin-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-integration-test-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-integration-test-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-integration-test-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo-[HASH].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo-[HASH].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo-[HASH][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo-[HASH][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-test-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-test-integration-test-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-integration-test-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-integration-test-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json [ROOT]/foo/build-dir/tmp/foo.txt [ROOT]/foo/build-dir/.rustc_info.json @@ -364,16 +383,19 @@ fn examples_should_output_to_build_dir_and_uplift_to_target_dir() { ) .build(); - p.cargo("build --examples").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build --examples") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); p.root().join("build-dir").assert_build_dir_layout(str![[r#" [ROOT]/foo/build-dir/.rustc_info.json [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-example-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/example-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/example-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-example-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/example-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/example-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp [ROOT]/foo/build-dir/debug/examples/foo[..][EXE] [ROOT]/foo/build-dir/debug/examples/foo[..].d @@ -405,23 +427,26 @@ fn benches_should_output_to_build_dir() { ) .build(); - p.cargo("build --bench=foo").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build --bench=foo") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); p.root().join("build-dir").assert_build_dir_layout(str![[r#" [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d -[ROOT]/foo/build-dir/debug/deps/foo[..].d -[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE] -[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-bench-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bench-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bench-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo-[HASH].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo-[HASH][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-test-bench-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-bench-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-bench-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json [ROOT]/foo/build-dir/.rustc_info.json "#]]); @@ -450,7 +475,10 @@ fn cargo_doc_should_output_to_target_dir() { ) .build(); - p.cargo("doc").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout doc") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); let docs_dir = p.root().join("target-dir/doc"); @@ -472,7 +500,10 @@ fn cargo_package_should_build_in_build_dir_and_output_to_target_dir() { ) .build(); - p.cargo("package").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout package") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); let package_artifact_dir = p.root().join("target-dir/package"); assert_exists(&package_artifact_dir); @@ -481,12 +512,12 @@ fn cargo_package_should_build_in_build_dir_and_output_to_target_dir() { p.root().join("build-dir").assert_build_dir_layout(str![[r#" [ROOT]/foo/build-dir/.rustc_info.json [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d [ROOT]/foo/build-dir/debug/foo[EXE] [ROOT]/foo/build-dir/debug/foo.d [ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.lock @@ -521,7 +552,8 @@ fn cargo_publish_should_only_touch_build_dir() { ) .build(); - p.cargo("publish") + p.cargo("-Zbuild-dir-new-layout publish") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) .replace_crates_io(registry.index_url()) .enable_mac_dsym() .run(); @@ -549,18 +581,21 @@ fn cargo_clean_should_clean_the_target_dir_and_build_dir() { ) .build(); - p.cargo("build").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); p.root().join("build-dir").assert_build_dir_layout(str![[r#" [ROOT]/foo/build-dir/.rustc_info.json [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d "#]]); @@ -574,12 +609,91 @@ fn cargo_clean_should_clean_the_target_dir_and_build_dir() { "#]]); - p.cargo("clean").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout clean") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); assert_not_exists(&p.root().join("build-dir")); assert_not_exists(&p.root().join("target-dir")); } +#[cargo_test] +fn cargo_clean_should_remove_correct_files() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = ["*.txt"] + license = "MIT" + description = "foo" + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("Hello, World!"); }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/build/bar/[HASH]/deps/bar-[HASH].d +[ROOT]/foo/build-dir/debug/build/bar/[HASH]/deps/libbar-[HASH].rlib +[ROOT]/foo/build-dir/debug/build/bar/[HASH]/deps/libbar-[HASH].rmeta +[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/dep-lib-bar +[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/lib-bar +[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/lib-bar.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp + +"#]]); + + p.cargo("-Zbuild-dir-new-layout clean -p bar") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp + +"#]]); +} + #[cargo_test] fn timings_report_should_output_to_target_dir() { let p = project() @@ -594,7 +708,10 @@ fn timings_report_should_output_to_target_dir() { ) .build(); - p.cargo("build --timings").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build --timings") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); assert_exists(&p.root().join("target-dir/cargo-timings/cargo-timing.html")); } @@ -616,7 +733,8 @@ fn future_incompat_should_output_to_build_dir() { ) .build(); - p.cargo("build") + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) .arg("--future-incompat-report") .env("RUSTFLAGS", "-Zfuture-incompat-test") .run(); @@ -638,7 +756,8 @@ fn template_should_error_for_invalid_variables() { ) .build(); - p.cargo("build") + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) .enable_mac_dsym() .with_status(101) .with_stderr_data(str![[r#" @@ -663,7 +782,8 @@ fn template_should_suggest_nearest_variable() { ) .build(); - p.cargo("build") + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) .with_status(101) .with_stderr_data(str![[r#" [ERROR] unexpected variable `workspace-ro` in build.build-dir path `{workspace-ro}/build-dir` @@ -688,7 +808,10 @@ fn template_workspace_root() { ) .build(); - p.cargo("build").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); // Verify the binary was uplifted to the target-dir assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}"))); @@ -696,12 +819,12 @@ fn template_workspace_root() { [ROOT]/foo/build-dir/.rustc_info.json [ROOT]/foo/build-dir/CACHEDIR.TAG [ROOT]/foo/build-dir/debug/.cargo-lock -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d "#]]); @@ -730,7 +853,10 @@ fn template_cargo_cache_home() { ) .build(); - p.cargo("build").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); // Verify the binary was uplifted to the target-dir assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}"))); @@ -740,12 +866,12 @@ fn template_cargo_cache_home() { [ROOT]/home/.cargo/build-dir/.rustc_info.json [ROOT]/home/.cargo/build-dir/CACHEDIR.TAG [ROOT]/home/.cargo/build-dir/debug/.cargo-lock -[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/home/.cargo/build-dir/debug/deps/foo[..][EXE] -[ROOT]/home/.cargo/build-dir/debug/deps/foo[..].d +[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/deps/foo[..].d "#]]); @@ -784,7 +910,10 @@ fn template_workspace_path_hash() { ) .build(); - p.cargo("build").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); let foo_dir = p.root().join("foo"); assert_exists(&foo_dir); @@ -798,12 +927,12 @@ fn template_workspace_path_hash() { [ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json [ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG [ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo[..][EXE] -[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo[..].d +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/deps/foo[..][EXE] +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/deps/foo[..].d "#]]); @@ -851,7 +980,10 @@ fn template_workspace_path_hash_should_handle_symlink() { .build(); // Build from the non-symlinked directory - p.cargo("check").enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout check") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .run(); // Parse and verify the hash dir created from the non-symlinked dir let foo_dir = p.root().join("foo"); @@ -862,12 +994,12 @@ fn template_workspace_path_hash_should_handle_symlink() { [ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json [ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG [ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-lib-foo -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo.json -[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo-[HASH].d -[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/libfoo-[HASH].rmeta +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/dep-lib-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/lib-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/lib-foo.json +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/deps/foo-[HASH].d +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/deps/libfoo-[HASH].rmeta "#]]); @@ -887,7 +1019,11 @@ fn template_workspace_path_hash_should_handle_symlink() { foo_dir.rm_rf(); // Run cargo from the symlinked dir - p.cargo("check").cwd(&symlinked_dir).enable_mac_dsym().run(); + p.cargo("-Zbuild-dir-new-layout check") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) + .enable_mac_dsym() + .cwd(&symlinked_dir) + .run(); // Parse and verify the hash created from the symlinked dir assert_exists(&foo_dir); @@ -897,12 +1033,12 @@ fn template_workspace_path_hash_should_handle_symlink() { [ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json [ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG [ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-lib-foo -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo -[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo.json -[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo-[HASH].d -[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/libfoo-[HASH].rmeta +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/dep-lib-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/lib-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/lib-foo.json +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/deps/foo-[HASH].d +[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/deps/libfoo-[HASH].rmeta "#]]); @@ -929,7 +1065,8 @@ fn template_should_handle_reject_unmatched_brackets() { ) .build(); - p.cargo("build") + p.cargo("-Zbuild-dir-new-layout build") + .masquerade_as_nightly_cargo(&["new build-dir layout"]) .with_status(101) .with_stderr_data(str![[r#" [ERROR] unexpected opening bracket `{` in build.build-dir path `foo/{bar` diff --git a/tests/testsuite/build_dir_legacy.rs b/tests/testsuite/build_dir_legacy.rs new file mode 100644 index 00000000000..062fd9c05aa --- /dev/null +++ b/tests/testsuite/build_dir_legacy.rs @@ -0,0 +1,1119 @@ +//! Tests for `build.build-dir` config property. +//! +//! The testing strategy for build-dir functionality is primarily checking if directories / files +//! are in the expected locations. +//! The rational is that other tests will verify each individual feature, while the tests in this +//! file verify the files saved to disk are in the correct locations according to the `build-dir` +//! configuration. +//! +//! Tests check if directories match some "layout" by using [`CargoPathExt::assert_file_layout`] + +use std::path::PathBuf; + +use crate::prelude::*; +use cargo_test_support::registry::{Package, RegistryBuilder}; +use cargo_test_support::{paths, prelude::*, project, str}; +use std::env::consts::{DLL_PREFIX, DLL_SUFFIX, EXE_SUFFIX}; + +#[cargo_test] +fn binary_with_debug() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + assert_not_exists(&p.root().join("target")); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..].d + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/debug/.cargo-lock +[ROOT]/foo/target-dir/debug/foo[EXE] +[ROOT]/foo/target-dir/debug/foo.d + +"#]]); +} + +#[cargo_test] +fn binary_with_release() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build --release").enable_mac_dsym().run(); + + assert_exists_patterns_with_base_dir( + &p.root(), + &[ + // Check the pre-uplifted binary in the build-dir + &format!("build-dir/release/deps/foo*{EXE_SUFFIX}"), + "build-dir/release/deps/foo*.d", + // Verify the binary was copied to the target-dir + &format!("target-dir/release/foo{EXE_SUFFIX}"), + "target-dir/release/foo.d", + ], + ); + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/release/.cargo-lock +[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/release/deps/foo[..][EXE] +[ROOT]/foo/build-dir/release/deps/foo[..].d + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/release/.cargo-lock +[ROOT]/foo/target-dir/release/foo[EXE] +[ROOT]/foo/target-dir/release/foo.d + +"#]]); +} + +#[cargo_test] +fn libs() { + // https://doc.rust-lang.org/reference/linkage.html#r-link.staticlib + let (staticlib_prefix, staticlib_suffix) = + if cfg!(target_os = "windows") && cfg!(target_env = "msvc") { + ("", ".lib") + } else { + ("lib", ".a") + }; + + // (crate-type, list of final artifacts) + let lib_types = [ + ("lib", ["libfoo.rlib", "libfoo.d"]), + ( + "dylib", + [ + &format!("{DLL_PREFIX}foo{DLL_SUFFIX}"), + &format!("{DLL_PREFIX}foo.d"), + ], + ), + ( + "cdylib", + [ + &format!("{DLL_PREFIX}foo{DLL_SUFFIX}"), + &format!("{DLL_PREFIX}foo.d"), + ], + ), + ( + "staticlib", + [ + &format!("{staticlib_prefix}foo{staticlib_suffix}"), + &format!("{staticlib_prefix}foo.d"), + ], + ), + ]; + + for (lib_type, expected_files) in lib_types { + let p = project() + .file("src/lib.rs", r#"fn foo() { println!("Hello, World!") }"#) + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [lib] + crate-type = ["{lib_type}"] + "# + ), + ) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + // Verify lib artifacts were copied into the artifact dir + assert_exists_patterns_with_base_dir(&p.root().join("target-dir/debug"), &expected_files); + } +} + +#[cargo_test] +fn should_default_to_target() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + p.root().join("target").assert_build_dir_layout(str![[r#" +[ROOT]/foo/target/.rustc_info.json +[ROOT]/foo/target/CACHEDIR.TAG +[ROOT]/foo/target/debug/.cargo-lock +[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/target/debug/deps/foo[..][EXE] +[ROOT]/foo/target/debug/deps/foo[..].d +[ROOT]/foo/target/debug/foo[EXE] +[ROOT]/foo/target/debug/foo.d + +"#]]); +} + +#[cargo_test] +fn should_respect_env_var() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .build(); + + p.cargo("build") + .env("CARGO_BUILD_BUILD_DIR", "build-dir") + .enable_mac_dsym() + .run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..].d + +"#]]); +} + +#[cargo_test] +fn build_script_should_output_to_build_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + "build.rs", + r#" + fn main() { + std::fs::write( + format!("{}/foo.txt", std::env::var("OUT_DIR").unwrap()), + "Hello, world!", + ) + .unwrap(); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/run-build-script-build-script-build +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/run-build-script-build-script-build.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-build-script-build-script-build +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/build-script-build-script-build +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/build-script-build-script-build.json +[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build_script_build[..].d +[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build_script_build[..][EXE] +[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build-script-build[EXE] +[ROOT]/foo/build-dir/debug/build/foo-[HASH]/out/foo.txt +[ROOT]/foo/build-dir/debug/build/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/build/foo-[HASH]/output +[ROOT]/foo/build-dir/debug/build/foo-[HASH]/stderr +[ROOT]/foo/build-dir/debug/build/foo-[HASH]/root-output + +"#]]); +} + +#[cargo_test] +fn cargo_tmpdir_should_output_to_build_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + "tests/foo.rs", + r#" + #[test] + fn test() { + std::fs::write( + format!("{}/foo.txt", env!("CARGO_TARGET_TMPDIR")), + "Hello, world!", + ) + .unwrap(); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("test").enable_mac_dsym().run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d +[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d +[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE] +[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bin-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-integration-test-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-integration-test-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-integration-test-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/tmp/foo.txt +[ROOT]/foo/build-dir/.rustc_info.json + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/debug/.cargo-lock +[ROOT]/foo/target-dir/debug/foo[EXE] + +"#]]); +} + +#[cargo_test] +fn examples_should_output_to_build_dir_and_uplift_to_target_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file("examples/foo.rs", r#"fn main() { }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build --examples").enable_mac_dsym().run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-example-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/example-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/example-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/examples/foo[..][EXE] +[ROOT]/foo/build-dir/debug/examples/foo[..].d + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/debug/.cargo-lock +[ROOT]/foo/target-dir/debug/examples/foo[EXE] +[ROOT]/foo/target-dir/debug/examples/foo.d + +"#]]); +} + +#[cargo_test] +fn benches_should_output_to_build_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file("benches/foo.rs", r#"fn main() { }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build --bench=foo").enable_mac_dsym().run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d +[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-bench-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bench-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bench-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/.rustc_info.json + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/debug/.cargo-lock +[ROOT]/foo/target-dir/debug/foo[EXE] + +"#]]); +} + +#[cargo_test] +fn cargo_doc_should_output_to_target_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("doc").enable_mac_dsym().run(); + + let docs_dir = p.root().join("target-dir/doc"); + + assert_exists(&docs_dir); + assert_exists(&docs_dir.join("foo/index.html")); +} + +#[cargo_test] +fn cargo_package_should_build_in_build_dir_and_output_to_target_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("package").enable_mac_dsym().run(); + + let package_artifact_dir = p.root().join("target-dir/package"); + assert_exists(&package_artifact_dir); + assert_exists(&package_artifact_dir.join("foo-0.0.1.crate")); + assert!(package_artifact_dir.join("foo-0.0.1.crate").is_file()); + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/foo[EXE] +[ROOT]/foo/build-dir/debug/foo.d +[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.lock +[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.toml +[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.toml.orig +[ROOT]/foo/build-dir/package/foo-0.0.1/src/main.rs +[ROOT]/foo/build-dir/package/foo-0.0.1.crate + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/package/foo-0.0.1.crate + +"#]]); +} + +#[cargo_test] +fn cargo_publish_should_only_touch_build_dir() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .enable_mac_dsym() + .run(); + + let package_artifact_dir = p.root().join("target-dir/package"); + assert!(!package_artifact_dir.exists()); + + let package_build_dir = p.root().join("build-dir/package"); + assert_exists(&package_build_dir); + assert_exists(&package_build_dir.join("foo-0.0.1")); + assert!(package_build_dir.join("foo-0.0.1").is_dir()); +} + +#[cargo_test] +fn cargo_clean_should_clean_the_target_dir_and_build_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..].d + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/debug/.cargo-lock +[ROOT]/foo/target-dir/debug/foo[EXE] +[ROOT]/foo/target-dir/debug/foo.d + +"#]]); + + p.cargo("clean").enable_mac_dsym().run(); + + assert_not_exists(&p.root().join("build-dir")); + assert_not_exists(&p.root().join("target-dir")); +} + +#[cargo_test] +fn cargo_clean_should_remove_correct_files() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = ["*.txt"] + license = "MIT" + description = "foo" + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("Hello, World!"); }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..].d +[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/lib-bar +[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/lib-bar.json +[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/dep-lib-bar +[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/deps/bar[..].d +[ROOT]/foo/build-dir/debug/deps/libbar[..].rlib +[ROOT]/foo/build-dir/debug/deps/libbar[..].rmeta + +"#]]); + + p.cargo("clean -p bar").enable_mac_dsym().run(); + + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..].d + +"#]]); +} + +#[cargo_test] +fn timings_report_should_output_to_target_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build --timings").enable_mac_dsym().run(); + + assert_exists(&p.root().join("target-dir/cargo-timings/cargo-timing.html")); +} + +#[cargo_test( + nightly, + reason = "-Zfuture-incompat-test requires nightly (permanently)" +)] +fn future_incompat_should_output_to_build_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { let x = 1; }"#) + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "target-dir" + build-dir = "build-dir" + "#, + ) + .build(); + + p.cargo("build") + .arg("--future-incompat-report") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .run(); + + assert_exists(&p.root().join("build-dir/.future-incompat-report.json")); +} + +#[cargo_test] +fn template_should_error_for_invalid_variables() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "{fake}/build-dir" + target-dir = "target-dir" + "#, + ) + .build(); + + p.cargo("build") + .enable_mac_dsym() + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unexpected variable `fake` in build.build-dir path `{fake}/build-dir` + +[HELP] available template variables are `{workspace-root}`, `{cargo-cache-home}`, `{workspace-path-hash}` + +"#]]) + .run(); +} + +#[cargo_test] +fn template_should_suggest_nearest_variable() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "{workspace-ro}/build-dir" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unexpected variable `workspace-ro` in build.build-dir path `{workspace-ro}/build-dir` + +[HELP] a template variable with a similar name exists: `workspace-root` + +"#]]) + .run(); +} + +#[cargo_test] +fn template_workspace_root() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "{workspace-root}/build-dir" + target-dir = "target-dir" + "#, + ) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + // Verify the binary was uplifted to the target-dir + assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}"))); + p.root().join("build-dir").assert_build_dir_layout(str![[r#" +[ROOT]/foo/build-dir/.rustc_info.json +[ROOT]/foo/build-dir/CACHEDIR.TAG +[ROOT]/foo/build-dir/debug/.cargo-lock +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/build-dir/debug/deps/foo[..].d + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/debug/.cargo-lock +[ROOT]/foo/target-dir/debug/foo[EXE] +[ROOT]/foo/target-dir/debug/foo.d + +"#]]); +} + +#[cargo_test] +fn template_cargo_cache_home() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "{cargo-cache-home}/build-dir" + target-dir = "target-dir" + "#, + ) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + // Verify the binary was uplifted to the target-dir + assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}"))); + paths::cargo_home() + .join("build-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/home/.cargo/build-dir/.rustc_info.json +[ROOT]/home/.cargo/build-dir/CACHEDIR.TAG +[ROOT]/home/.cargo/build-dir/debug/.cargo-lock +[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/home/.cargo/build-dir/debug/deps/foo[..][EXE] +[ROOT]/home/.cargo/build-dir/debug/deps/foo[..].d + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/debug/.cargo-lock +[ROOT]/foo/target-dir/debug/foo[EXE] +[ROOT]/foo/target-dir/debug/foo.d + +"#]]); +} + +#[cargo_test] +fn template_workspace_path_hash() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + authors = [] + edition = "2015" + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "foo/{workspace-path-hash}/build-dir" + target-dir = "target-dir" + "#, + ) + .build(); + + p.cargo("build").enable_mac_dsym().run(); + + let foo_dir = p.root().join("foo"); + assert_exists(&foo_dir); + let hash_dir = parse_workspace_manifest_path_hash(&foo_dir); + + let build_dir = hash_dir.as_path().join("build-dir"); + + // Verify the binary was uplifted to the target-dir + assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}"))); + build_dir.assert_build_dir_layout(str![[r#" +[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json +[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG +[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo[..][EXE] +[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo[..].d + +"#]]); + + p.root() + .join("target-dir") + .assert_build_dir_layout(str![[r#" +[ROOT]/foo/target-dir/CACHEDIR.TAG +[ROOT]/foo/target-dir/debug/.cargo-lock +[ROOT]/foo/target-dir/debug/foo[EXE] +[ROOT]/foo/target-dir/debug/foo.d + +"#]]); +} + +/// Verify that the {workspace-path-hash} does not changes if cargo is run from inside of +/// a symlinked directory. +/// The test approach is to build a project twice from the non-symlinked directory and a symlinked +/// directory and then compare the build-dir paths. +#[cargo_test] +fn template_workspace_path_hash_should_handle_symlink() { + #[cfg(unix)] + use std::os::unix::fs::symlink; + #[cfg(windows)] + use std::os::windows::fs::symlink_dir as symlink; + + let p = project() + .file("src/lib.rs", "") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + authors = [] + edition = "2015" + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "foo/{workspace-path-hash}/build-dir" + "#, + ) + .build(); + + // Build from the non-symlinked directory + p.cargo("check").enable_mac_dsym().run(); + + // Parse and verify the hash dir created from the non-symlinked dir + let foo_dir = p.root().join("foo"); + assert_exists(&foo_dir); + let original_hash_dir = parse_workspace_manifest_path_hash(&foo_dir); + + original_hash_dir.assert_build_dir_layout(str![[r#" +[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json +[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG +[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-lib-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo.json +[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo-[HASH].d +[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/libfoo-[HASH].rmeta + +"#]]); + + p.root().join("target").assert_build_dir_layout(str![[r#" +[ROOT]/foo/target/CACHEDIR.TAG +[ROOT]/foo/target/debug/.cargo-lock + +"#]]); + + // Create a symlink of the project root. + let mut symlinked_dir = p.root().clone(); + symlinked_dir.pop(); + symlinked_dir = symlinked_dir.join("symlink-dir"); + symlink(p.root(), &symlinked_dir).unwrap(); + + // Remove the foo dir (which contains the build-dir) before we rebuild from a symlinked dir. + foo_dir.rm_rf(); + + // Run cargo from the symlinked dir + p.cargo("check").cwd(&symlinked_dir).enable_mac_dsym().run(); + + // Parse and verify the hash created from the symlinked dir + assert_exists(&foo_dir); + let symlink_hash_dir = parse_workspace_manifest_path_hash(&foo_dir); + + symlink_hash_dir.assert_build_dir_layout(str![[r#" +[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json +[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG +[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-lib-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo +[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo.json +[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo-[HASH].d +[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/libfoo-[HASH].rmeta + +"#]]); + + p.root().join("target").assert_build_dir_layout(str![[r#" +[ROOT]/foo/target/CACHEDIR.TAG +[ROOT]/foo/target/debug/.cargo-lock + +"#]]); + + // Verify the hash dir created from the symlinked and non-symlinked dirs are the same. + assert_eq!(original_hash_dir, symlink_hash_dir); +} + +#[cargo_test] +fn template_should_handle_reject_unmatched_brackets() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "foo/{bar" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unexpected opening bracket `{` in build.build-dir path `foo/{bar` + +"#]]) + .run(); + + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "foo/}bar" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unexpected closing bracket `}` in build.build-dir path `foo/}bar` + +"#]]) + .run(); +} + +fn parse_workspace_manifest_path_hash(hash_dir: &PathBuf) -> PathBuf { + // Since the hash will change between test runs simply find the first directories and assume + // that is the hash dir. The format is a 2 char directory followed by the remaining hash in the + // inner directory (ie. `34/f9d02eb8411c05`) + let mut dirs = std::fs::read_dir(hash_dir).unwrap().into_iter(); + let outer_hash_dir = dirs.next().unwrap().unwrap(); + // Validate there are no other directories in `hash_dir` + assert!( + dirs.next().is_none(), + "Found multiple dir entries in {hash_dir:?}" + ); + // Validate the outer hash dir hash is a directory and has the correct hash length + assert!( + outer_hash_dir.path().is_dir(), + "{outer_hash_dir:?} was not a directory" + ); + assert_eq!( + outer_hash_dir.path().file_name().unwrap().len(), + 2, + "Path {:?} should have been 2 chars", + outer_hash_dir.path().file_name() + ); + + let mut dirs = std::fs::read_dir(outer_hash_dir.path()) + .unwrap() + .into_iter(); + let inner_hash_dir = dirs.next().unwrap().unwrap(); + // Validate there are no other directories in first hash dir + assert!( + dirs.next().is_none(), + "Found multiple dir entries in {outer_hash_dir:?}" + ); + // Validate the outer hash dir hash is a directory and has the correct hash length + assert!( + inner_hash_dir.path().is_dir(), + "{inner_hash_dir:?} was not a directory" + ); + assert_eq!( + inner_hash_dir.path().file_name().unwrap().len(), + 14, + "Path {:?} should have been 2 chars", + inner_hash_dir.path().file_name() + ); + return inner_hash_dir.path(); +} + +#[track_caller] +fn assert_exists(path: &PathBuf) { + assert!( + path.exists(), + "Expected `{}` to exist but was not found.", + path.display() + ); +} + +#[track_caller] +fn assert_not_exists(path: &PathBuf) { + assert!( + !path.exists(), + "Expected `{}` to NOT exist but was found.", + path.display() + ); +} + +#[track_caller] +fn assert_exists_patterns_with_base_dir(base: &PathBuf, patterns: &[&str]) { + let root = base.to_str().unwrap(); + let p: Vec<_> = patterns.iter().map(|p| format!("{root}/{p}")).collect(); + let p: Vec<&str> = p.iter().map(|v| v.as_str()).collect(); + assert_exists_patterns(&p); +} + +#[track_caller] +fn assert_exists_patterns(patterns: &[&str]) { + for p in patterns { + assert_exists_pattern(p); + } +} + +#[track_caller] +fn assert_exists_pattern(pattern: &str) { + use glob::glob; + + let mut z = glob(pattern).unwrap(); + + assert!( + z.next().is_some(), + "Expected `{pattern}` to match existing file but was not found.", + ) +} diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs index a7a82df641f..1e57f983c1e 100644 --- a/tests/testsuite/main.rs +++ b/tests/testsuite/main.rs @@ -13,6 +13,7 @@ mod binary_name; mod build; mod build_analysis; mod build_dir; +mod build_dir_legacy; mod build_plan; mod build_script; mod build_script_env;