AI & ML

Build Dir Layout v2 Now Available for Developer Testing

· 5 min read

The Cargo team invites developers to test the nightly-only cargo -Zbuild-dir-new-layout flag and report any issues. While the build directory layout is officially internal, many projects depend on its unspecified structure due to gaps in Cargo's feature set. Although a crater run has been performed, it can't catch everything. Community help is needed to identify affected tools and workflows, report issues to maintainers, and ensure compatibility with both old and new layouts.

How to test this?

Using nightly 2026-03-10 or later, run your tests, release processes, and any workflow that touches the build or target directory with the -Zbuild-dir-new-layout flag.

For example:

$ cargo test -Zbuild-dir-new-layout

If you encounter failures, they may not be specific to -Zbuild-dir-new-layout. Since Cargo 1.91, users can separate intermediate build artifacts (build-dir) from final artifacts (target-dir). Verify this by testing with only CARGO_BUILD_BUILD_DIR=build set. The Cargo team is considering changing the default build-dir location in #16147.

Possible outcomes include:

Known failure modes:

  • Inferring a [[bin]] path from a [[test]] path:
  • Build scripts deriving target-dir from their binary or OUT_DIR: see Issue #13663
    • Update existing workarounds to handle the new layout
  • Locating user-requested artifacts from rustc: see Issue #13672
    • Update existing workarounds to handle the new layout

Library compatibility status at publication:

What is not changing?

The layout of final artifacts within the target directory remains unchanged.

Build artifacts will continue to be nested under the profile and target tuple when specified.

What is changing?

The organization shifts from grouping by content type to scoping content by package name and a hash of the build unit and its inputs.

Current layout example with packages lib and bin, both having build scripts:

build-dir/
├── CACHEDIR.TAG
└── debug/
 ├── .cargo-lock # file lock protecting access to this location
 ├── .fingerprint/ # build cache tracking
 │ ├── bin-[BUILD_SCRIPT_RUN_HASH]/*
 │ ├── bin-[BUILD_SCRIPT_BIN_HASH]/*
 │ ├── bin-[HASH]/*
 │ ├── lib-[BUILD_SCRIPT_RUN_HASH]/*
 │ ├── lib-[BUILD_SCRIPT_BIN_HASH]/*
 │ └── lib-[HASH]/*
 ├── build/
 │ ├── bin-[BIN_HASH]/* # build script binary
 │ ├── bin-[RUN_HASH]/out/ # build script run OUT_DIR
 │ ├── bin-[RUN_HASH]/* # build script run cache
 │ ├── lib-[BIN_HASH]/* # build script binary
 │ ├── lib-[RUN_HASH]/out/ # build script run OUT_DIR
 │ └── lib-[RUN_HASH]/* # build script run cache
 ├── deps/
 │ ├── bin-[HASH]* # binary and debug information
 │ ├── lib-[HASH]* # library and debug information
 │ └── liblib-[HASH]* # library and debug information
 ├── examples/ # unused in this case
 └── incremental/... # managed by rustc

Proposed layout:

build-dir/
├── CACHEDIR.TAG
└── debug/
 ├── .cargo-lock # file lock protecting access to this location
 ├── build/
 │ ├── bin/ # package name
 │ │ ├── [BUILD_SCRIPT_BIN_HASH]/
 │ │ │ ├── fingerprint/* # build cache tracking
 │ │ │ └── out/* # build script binary
 │ │ ├── [BUILD_SCRIPT_RUN_HASH]/
 │ │ │ ├── fingerprint/* # build cache tracking
 │ │ │ ├── out/* # build script run OUT_DIR
 │ │ │ └── run/* # build script run cache
 │ │ └── [HASH]/
 │ │ ├── fingerprint/* # build cache tracking
 │ │ └── out/* # binary and debug information
 │ └── lib/ # package name
 │ ├── [BUILD_SCRIPT_BIN_HASH]/
 │ │ ├── fingerprint/* # build cache tracking
 │ │ └── out/* # build script binary
 │ ├── [BUILD_SCRIPT_RUN_HASH]/
 │ │ ├── fingerprint/* # build cache tracking
 │ │ ├── out/* # build script run OUT_DIR
 │ │ └── run/* # build script run cache
 │ └── [HASH]/
 │ ├── fingerprint/* # build cache tracking
 │ └── out/* # library and debug information
 └── incremental/... # managed by rustc

For deeper technical details, see the mod layout documentation.

Why is this being done?

ranger-ross has driven this effort as a foundation for cross-workspace caching, which becomes more feasible when each cacheable unit lives in a self-contained directory.

This change also enables future work on:

Additional benefits discovered during development:

While the Cargo team doesn't officially support sharing a build-dir across workspaces, that last improvement should reduce issues for developers who do.

Future work

Lessons from this layout change will inform how and when to implement future modifications, including:

  • Reducing path lengths to minimize Windows-specific errors
  • Experimenting with moving artifacts out of --profile and --target directories to enable broader artifact sharing

Some potential changes weren't included now because they depend on the lock improvements, which in turn depend on this layout change.

The team also aims to reduce project coupling to the unspecified details of build-dir structure.