Skip to content
Open
7 changes: 7 additions & 0 deletions crates/cargo-test-support/src/compare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,13 @@ fn add_regex_redactions(subs: &mut snapbox::Redactions) {
regex!(r"\.cargo/target/(?<redacted>[0-9a-f]{2}/[0-9a-f]{14})"),
)
.unwrap();
// Avoid 2 letter crate names being merged into hashes in file paths.
// e.g. target/debug/build/d1/[HASH]/out
subs.insert(
"[HASH]",
regex!(r"build/[a-z0-9]{2}/(?<redacted>[a-f0-9]{16})"),
)
.unwrap();
subs.insert("[HASH]", regex!(r"/[a-z0-9\-_]+-(?<redacted>[0-9a-f]{16})"))
.unwrap();
// Match multi-part hashes like `06/b451d0d6f88b1d` used in directory paths
Expand Down
82 changes: 80 additions & 2 deletions src/cargo/core/features.rs
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any documentation we want to update when stabilizing this? I guess at least unstable.md?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also https://doc.rust-lang.org/cargo/reference/build-cache.html has some details about the build-dir internals.

Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ macro_rules! unstable_cli_options {
/// Cargo, like `rustc`, accepts a suite of `-Z` flags which are intended for
/// gating unstable functionality to Cargo. These flags are only available on
/// the nightly channel of Cargo.
#[derive(Default, Debug, Deserialize)]
#[derive(Debug, Deserialize)]
#[serde(default, rename_all = "kebab-case")]
pub struct CliUnstable {
$(
Expand Down Expand Up @@ -852,6 +852,68 @@ macro_rules! unstable_cli_options {
}
}

// TODO: Move this back to derive(Default) once `build_dir_new_layout` is stabilized and the old
// layout has been removed.
impl Default for CliUnstable {
fn default() -> Self {
Self {
build_dir_new_layout: !is_new_build_dir_layout_opt_out(),

allow_features: Default::default(),
print_im_a_teapot: Default::default(),
advanced_env: Default::default(),
any_build_script_metadata: Default::default(),
asymmetric_token: Default::default(),
avoid_dev_deps: Default::default(),
binary_dep_depinfo: Default::default(),
bindeps: Default::default(),
build_analysis: Default::default(),
build_std: Default::default(),
build_std_features: Default::default(),
cargo_lints: Default::default(),
checksum_freshness: Default::default(),
codegen_backend: Default::default(),
direct_minimal_versions: Default::default(),
dual_proc_macros: Default::default(),
feature_unification: Default::default(),
features: Default::default(),
fine_grain_locking: Default::default(),
fix_edition: Default::default(),
gc: Default::default(),
git: Default::default(),
gitoxide: Default::default(),
host_config: Default::default(),
json_target_spec: Default::default(),
minimal_versions: Default::default(),
msrv_policy: Default::default(),
mtime_on_use: Default::default(),
next_lockfile_bump: Default::default(),
no_embed_metadata: Default::default(),
no_index_update: Default::default(),
panic_abort_tests: Default::default(),
panic_immediate_abort: Default::default(),
profile_hint_mostly_unused: Default::default(),
profile_rustflags: Default::default(),
public_dependency: Default::default(),
publish_timeout: Default::default(),
root_dir: Default::default(),
rustc_unicode: Default::default(),
rustdoc_depinfo: Default::default(),
rustdoc_map: Default::default(),
rustdoc_mergeable_info: Default::default(),
rustdoc_scrape_examples: Default::default(),
sbom: Default::default(),
script: Default::default(),
section_timings: Default::default(),
separate_nightlies: Default::default(),
skip_rustdoc_fingerprint: Default::default(),
target_applies_to_host: Default::default(),
trim_paths: Default::default(),
unstable_options: Default::default(),
}
}
}

unstable_cli_options!(
// Permanently unstable features:
allow_features: Option<AllowFeatures> = ("Allow *only* the listed unstable features"),
Expand Down Expand Up @@ -1003,6 +1065,8 @@ const STABILIZED_LOCKFILE_PATH: &str = "The `lockfile-path` config key is now al

const STABILIZED_WARNINGS: &str = "The `build.warnings` config key is now always available";

const STABILIZED_BUILD_DIR_NEW_LAYOUT: &str = "build.build-dir-new-layout is now always enabled.";

fn deserialize_comma_separated_list<'de, D>(
deserializer: D,
) -> Result<Option<Vec<String>>, D::Error>
Expand Down Expand Up @@ -1268,6 +1332,12 @@ impl CliUnstable {
self.gitoxide = GitoxideFeatures::safe().into();
}

// NOTE: We set this before `implicitly_enable_features_if_needed` as `-Zfine-grain-locking`
// must use the new layout so that takes priority.
if is_new_build_dir_layout_opt_out() {
self.build_dir_new_layout = false;
}

self.implicitly_enable_features_if_needed();

Ok(warnings)
Expand Down Expand Up @@ -1393,6 +1463,7 @@ impl CliUnstable {
"config-include" => stabilized_warn(k, "1.93", STABILIZED_CONFIG_INCLUDE),
"lockfile-path" => stabilized_warn(k, "1.97", STABILIZED_LOCKFILE_PATH),
"warnings" => stabilized_warn(k, "1.97", STABILIZED_WARNINGS),
"build-dir-new-layout" => stabilized_warn(k, "1.97", STABILIZED_BUILD_DIR_NEW_LAYOUT),

// Unstable features
// Sorted alphabetically:
Expand All @@ -1403,7 +1474,6 @@ impl CliUnstable {
"binary-dep-depinfo" => self.binary_dep_depinfo = parse_empty(k, v)?,
"bindeps" => self.bindeps = parse_empty(k, v)?,
"build-analysis" => self.build_analysis = parse_empty(k, v)?,
"build-dir-new-layout" => self.build_dir_new_layout = parse_empty(k, v)?,
"build-std" => self.build_std = Some(parse_list(v)),
"build-std-features" => self.build_std_features = Some(parse_list(v)),
"cargo-lints" => self.cargo_lints = parse_empty(k, v)?,
Expand Down Expand Up @@ -1588,6 +1658,14 @@ fn cargo_use_gitoxide_instead_of_git2() -> bool {
std::env::var_os("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2").map_or(false, |value| value == "1")
}

#[expect(
clippy::disallowed_methods,
reason = "Temporary opt out that is not part of the public interface"
)]
fn is_new_build_dir_layout_opt_out() -> bool {
std::env::var("__CARGO_TEMPORARY_BUILD_DIR_NEW_LAYOUT_OPT_OUT").as_deref() == Ok("1")
}

/// Generate a link to Cargo documentation for the current release channel
/// `path` is the URL component after `https://doc.rust-lang.org/{channel}/cargo/`
pub fn cargo_docs_link(path: &str) -> String {
Expand Down
7 changes: 4 additions & 3 deletions src/doc/src/reference/build-cache.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ change. Some of these directories are:

Directory | Description
----------|------------
<code style="white-space: nowrap">\<build-dir>/debug/deps/</code> | Dependencies and other artifacts.
<code style="white-space: nowrap">\<build-dir>/debug/incremental/</code> | `rustc` [incremental output], a cache used to speed up subsequent builds.
<code style="white-space: nowrap">\<build-dir>/debug/build/</code> | Output from [build scripts].
<code style="white-space: nowrap">\<build-dir>/debug/build/</code> | Compilation artifacts and [build script] output.

> **Note**: The build-dir layout was changed in Cargo 1.97.0, thus prior versions use a different layout. (see [#15010](https://github.com/rust-lang/cargo/issues/15010))
## Dep-info files

Expand Down Expand Up @@ -107,7 +108,7 @@ configuration][config]. Refer to sccache documentation for more details.
[`cargo doc`]: ../commands/cargo-doc.md
[`cargo package`]: ../commands/cargo-package.md
[`cargo publish`]: ../commands/cargo-publish.md
[build scripts]: ../reference/build-scripts.md
[build script]: ../reference/build-scripts.md
[config]: ../reference/config.md
[def-workspace]: ../appendix/glossary.md#workspace '"workspace" (glossary entry)'
[target]: ../appendix/glossary.md#target '"target" (glossary entry)'
Expand Down
13 changes: 4 additions & 9 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ Each new feature described below should explain how to use it.
* [lockfile-publish-time](#lockfile-publish-time) --- Limit resolver to packages older than the specified time
* Output behavior
* [artifact-dir](#artifact-dir) --- Adds a directory where artifacts are copied to.
* [build-dir-new-layout](#build-dir-new-layout) --- Enables the new build-dir filesystem layout
* [Different binary name](#different-binary-name) --- Assign a name to the built binary that is separate from the crate name.
* [root-dir](#root-dir) --- Controls the root directory relative to which paths are printed
* Compile behavior
Expand Down Expand Up @@ -1956,14 +1955,6 @@ The following commands are available under `-Zbuild-analysis`:
- `cargo report rebuilds` --- Reports why crates were rebuilt,
helping diagnose unexpected recompilations.

## build-dir-new-layout

* Tracking Issue: [#15010](https://github.com/rust-lang/cargo/issues/15010)

Enables the new build-dir filesystem layout.
This layout change unblocks work towards caching and locking improvements.


## compile-time-deps

This permanently-unstable flag to only build proc-macros and build scripts (and their required dependencies),
Expand Down Expand Up @@ -2278,6 +2269,10 @@ Multi-package publishing has been stabilized in Rust 1.90.0.
Support for `build.build-dir` was stabilized in the 1.91 release.
See the [config documentation](config.md#buildbuild-dir) for information about changing the build-dir

## build-dir-new-layout

The new build-dir filesystem layout was stabilized in the 1.97.0 release.

## Build-plan

The `--build-plan` argument for the `build` command has been removed in 1.93.0-nightly.
Expand Down
14 changes: 7 additions & 7 deletions tests/build-std/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ fn basic() {
[COMPILING] [..]
...
[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
[RUNNING] unittests src/lib.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH])
[RUNNING] unittests src/main.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH])
[RUNNING] tests/smoke.rs (target/[HOST_TARGET]/debug/deps/smoke-[HASH])
[RUNNING] unittests src/lib.rs (target/[HOST_TARGET]/debug/build/foo/[HASH]/out/foo-[HASH])
[RUNNING] unittests src/main.rs (target/[HOST_TARGET]/debug/build/foo/[HASH]/out/foo-[HASH])
[RUNNING] tests/smoke.rs (target/[HOST_TARGET]/debug/build/foo/[HASH]/out/smoke-[HASH])
[DOCTEST] foo

"#]])
Expand All @@ -180,9 +180,9 @@ fn basic() {
let deps_dir = Path::new("target")
.join(rustc_host())
.join("debug")
.join("deps");
assert!(p.glob(deps_dir.join("*.rlib")).count() > 0);
assert_eq!(p.glob(deps_dir.join("*.dylib")).count(), 0);
.join("build");
assert!(p.glob(deps_dir.join("**/*.rlib")).count() > 0);
assert_eq!(p.glob(deps_dir.join("**/*.dylib")).count(), 0);
}

#[cargo_test(build_std_real)]
Expand Down Expand Up @@ -432,7 +432,7 @@ fn test_proc_macro() {
...
[COMPILING] foo v0.0.0 ([ROOT]/foo)
[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH])
[RUNNING] unittests src/lib.rs (target/debug/build/foo/[HASH]/out/foo-[HASH])

"#]])
.run();
Expand Down
Loading
Loading