Skip to content

Stabilize build.build-dir #15833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,6 @@ unstable_cli_options!(
avoid_dev_deps: bool = ("Avoid installing dev-dependencies if possible"),
binary_dep_depinfo: bool = ("Track changes to dependency artifacts"),
bindeps: bool = ("Allow Cargo packages to depend on bin, cdylib, and staticlib crates, and use the artifacts built by those crates"),
build_dir: bool = ("Enable the `build.build-dir` option in .cargo/config.toml file"),
#[serde(deserialize_with = "deserialize_comma_separated_list")]
build_std: Option<Vec<String>> = ("Enable Cargo to compile the standard library itself as part of a crate graph compilation"),
#[serde(deserialize_with = "deserialize_comma_separated_list")]
Expand Down Expand Up @@ -970,6 +969,8 @@ const STABILIZED_DOCTEST_XCOMPILE: &str = "Doctest cross-compiling is now always
const STABILIZED_PACKAGE_WORKSPACE: &str =
"Workspace packaging and publishing (a.k.a. `-Zpackage-workspace`) is now always enabled.";

const STABILIZED_BUILD_DIR: &str = "build.build-dir is now always enabled.";

fn deserialize_comma_separated_list<'de, D>(
deserializer: D,
) -> Result<Option<Vec<String>>, D::Error>
Expand Down Expand Up @@ -1352,6 +1353,7 @@ impl CliUnstable {
"registry-auth" => stabilized_warn(k, "1.74", STABILIZED_REGISTRY_AUTH),
"check-cfg" => stabilized_warn(k, "1.80", STABILIZED_CHECK_CFG),
"package-workspace" => stabilized_warn(k, "1.89", STABILIZED_PACKAGE_WORKSPACE),
"build-dir" => stabilized_warn(k, "1.91", STABILIZED_BUILD_DIR),

// Unstable features
// Sorted alphabetically:
Expand All @@ -1360,7 +1362,6 @@ impl CliUnstable {
"avoid-dev-deps" => self.avoid_dev_deps = parse_empty(k, v)?,
"binary-dep-depinfo" => self.binary_dep_depinfo = parse_empty(k, v)?,
"bindeps" => self.bindeps = parse_empty(k, v)?,
"build-dir" => self.build_dir = 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
3 changes: 0 additions & 3 deletions src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,6 @@ impl<'gctx> Workspace<'gctx> {
}

pub fn build_dir(&self) -> Filesystem {
if !self.gctx().cli_unstable().build_dir {
return self.target_dir();
}
self.build_dir.clone().unwrap_or_else(|| self.target_dir())
}

Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
// Note that we don't bother grabbing a lock here as we're just going to
// blow it all away anyway.
if opts.spec.is_empty() {
let paths: &[PathBuf] = if gctx.cli_unstable().build_dir && build_dir != target_dir {
let paths: &[PathBuf] = if build_dir != target_dir {
&[
target_dir.into_path_unlocked(),
build_dir.into_path_unlocked(),
Expand Down
9 changes: 2 additions & 7 deletions src/cargo/ops/cargo_output_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,7 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo
.collect(),
resolve,
target_directory: ws.target_dir().into_path_unlocked(),
build_directory: ws
.gctx()
.cli_unstable()
.build_dir
.then(|| ws.build_dir().into_path_unlocked()),
build_directory: ws.build_dir().into_path_unlocked(),
version: VERSION,
workspace_root: ws.root().to_path_buf(),
metadata: ws.custom_metadata().cloned(),
Expand All @@ -73,8 +69,7 @@ pub struct ExportInfo {
workspace_default_members: Vec<PackageIdSpec>,
resolve: Option<MetadataResolve>,
target_directory: PathBuf,
#[serde(skip_serializing_if = "Option::is_none")]
build_directory: Option<PathBuf>,
build_directory: PathBuf,
version: u32,
workspace_root: PathBuf,
metadata: Option<toml::Value>,
Expand Down
8 changes: 1 addition & 7 deletions src/cargo/ops/cargo_package/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,7 @@ pub fn run_verify(
// When packaging we use an ephemeral workspace but reuse the build cache to reduce
// verification time if the user has already compiled the dependencies and the fingerprint
// is unchanged.
let target_dir = if gctx.cli_unstable().build_dir {
Some(ws.build_dir())
} else {
Some(ws.target_dir())
};

let mut ws = Workspace::ephemeral(new_pkg, gctx, target_dir, true)?;
let mut ws = Workspace::ephemeral(new_pkg, gctx, Some(ws.build_dir()), true)?;
if let Some(local_reg) = local_reg {
ws.add_local_overlay(
local_reg.upstream,
Expand Down
3 changes: 0 additions & 3 deletions src/cargo/util/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,9 +650,6 @@ impl GlobalContext {
///
/// Callers should prefer [`Workspace::build_dir`] instead.
pub fn build_dir(&self, workspace_manifest_path: &PathBuf) -> CargoResult<Option<Filesystem>> {
if !self.cli_unstable().build_dir {
return self.target_dir();
}
if let Some(val) = &self.build_config()?.build_dir {
let replacements = vec![
(
Expand Down
30 changes: 21 additions & 9 deletions src/doc/src/reference/build-cache.md
Copy link
Member

Choose a reason for hiding this comment

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

https://doc.rust-lang.org/nightly/cargo/appendix/glossary.html#target

Should we update this glossary page as well, or at least link to the "Build cache" page?

Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
# Build cache

Cargo stores the output of a build into the "target" directory. By default,
this is the directory named `target` in the root of your
[*workspace*][def-workspace]. To change the location, you can set the
Cargo stores the output of a build into the "target" and "build" directories. By default,
both directories point to a directory named `target` in the root of your
[*workspace*][def-workspace]. To change the location of the target-dir, you can set the
`CARGO_TARGET_DIR` [environment variable], the [`build.target-dir`] config
value, or the `--target-dir` command-line flag.
value, or the `--target-dir` command-line flag. To change the location of the build-dir, you can set the
`CARGO_BUILD_BUILD_DIR` [environment variable] or the [`build.build-dir`] config value.

Artifacts are split in two catagories:
* Final build artifacts
* Final build artifacts are output meant for end users of Cargo
* e.g. binaries for bin crates, output of `cargo doc`, Cargo `--timings` reports
* Stored in the target-dir
* Intermediate build artifacts
* Intermediate build artifacts are internal to Cargo and the Rust compiler
* End users will generally not need to interact with intermediate build artifacts
* Stored in the Cargo build-dir

The directory layout depends on whether or not you are using the `--target`
flag to build for a specific platform. If `--target` is not specified, Cargo
Expand Down Expand Up @@ -53,15 +64,15 @@ Directory | Description
<code style="white-space: nowrap">target/doc/</code> | Contains rustdoc documentation ([`cargo doc`]).
<code style="white-space: nowrap">target/package/</code> | Contains the output of the [`cargo package`] and [`cargo publish`] commands.

Cargo also creates several other directories and files needed for the build
process. Their layout is considered internal to Cargo, and is subject to
Cargo also creates several other directories and files in the build-dir needed for the build
process. The build-dir layout is considered internal to Cargo, and is subject to
change. Some of these directories are:

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

Choose a reason for hiding this comment

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

Should we write <build-dir>/debug/deps to disambiguate that it is a placeholder?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

both suggestions seem reasonable, I will open a follow up docs PR :)

<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].

## Dep-info files

Expand Down Expand Up @@ -92,6 +103,7 @@ configuration][config]. Refer to sccache documentation for more details.
[`build.dep-info-basedir`]: ../reference/config.md#builddep-info-basedir
[`build.rustc-wrapper`]: ../reference/config.md#buildrustc-wrapper
[`build.target-dir`]: ../reference/config.md#buildtarget-dir
[`build.build-dir`]: ../reference/config.md#buildbuild-dir
[`cargo doc`]: ../commands/cargo-doc.md
[`cargo package`]: ../commands/cargo-package.md
[`cargo publish`]: ../commands/cargo-publish.md
Expand Down
23 changes: 22 additions & 1 deletion src/doc/src/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ rustc-wrapper = "…" # run this wrapper instead of `rustc`
rustc-workspace-wrapper = "…" # run this wrapper instead of `rustc` for workspace members
rustdoc = "rustdoc" # the doc generator tool
target = "triple" # build for the target triple (ignored by `cargo install`)
target-dir = "target" # path of where to place all generated artifacts
target-dir = "target" # path of where to place generated artifacts
build-dir = "target" # path of where to place intermediate build artifacts
rustflags = ["…", "…"] # custom flags to pass to all compiler invocations
rustdocflags = ["…", "…"] # custom flags to pass to rustdoc
incremental = true # whether or not to enable incremental compilation
Expand Down Expand Up @@ -482,6 +483,26 @@ is a directory named `target` located at the root of the workspace.

Can be overridden with the `--target-dir` CLI option.

For more information see the [build cache documentation](../reference/build-cache.md).

#### `build.build-dir`

* Type: string (path)
* Default: Defaults to the value of `build.target-dir`
* Environment: `CARGO_BUILD_BUILD_DIR`

The directory where intermediate build artifacts will be stored.
Intermediate artifacts are produced by Rustc/Cargo during the build process.

This option supports path templating.

Available template variables:
* `{workspace-root}` resolves to root of the current workspace.
* `{cargo-cache-home}` resolves to `CARGO_HOME`
* `{workspace-path-hash}` resolves to a hash of the manifest path

For more information see the [build cache documentation](../reference/build-cache.md).

#### `build.rustflags`
* Type: string or array of strings
* Default: none
Expand Down
2 changes: 2 additions & 0 deletions src/doc/src/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ In summary, the supported environment variables are:
* `CARGO_BUILD_RUSTDOC` --- The `rustdoc` executable, see [`build.rustdoc`].
* `CARGO_BUILD_TARGET` --- The default target platform, see [`build.target`].
* `CARGO_BUILD_TARGET_DIR` --- The default output directory, see [`build.target-dir`].
* `CARGO_BUILD_BUILD_DIR` --- The default build directory, see [`build.build-dir`].
* `CARGO_BUILD_RUSTFLAGS` --- Extra `rustc` flags, see [`build.rustflags`].
* `CARGO_BUILD_RUSTDOCFLAGS` --- Extra `rustdoc` flags, see [`build.rustdocflags`].
* `CARGO_BUILD_INCREMENTAL` --- Incremental compilation, see [`build.incremental`].
Expand Down Expand Up @@ -160,6 +161,7 @@ In summary, the supported environment variables are:
[`build.rustdoc`]: config.md#buildrustdoc
[`build.target`]: config.md#buildtarget
[`build.target-dir`]: config.md#buildtarget-dir
[`build.build-dir`]: config.md#buildbuild-dir
[`build.rustflags`]: config.md#buildrustflags
[`build.rustdocflags`]: config.md#buildrustdocflags
[`build.incremental`]: config.md#buildincremental
Expand Down
35 changes: 6 additions & 29 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ Each new feature described below should explain how to use it.
* [feature-unification](#feature-unification) --- Enable new feature unification modes in workspaces
* Output behavior
* [artifact-dir](#artifact-dir) --- Adds a directory where artifacts are copied to.
* [build-dir](#build-dir) --- Adds a directory where intermediate build artifacts are stored.
* [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 @@ -247,34 +246,6 @@ This can also be specified in `.cargo/config.toml` files.
artifact-dir = "out"
```

## build-dir
* Original Issue: [#14125](https://github.com/rust-lang/cargo/issues/14125)
* Tracking Issue: [#14125](https://github.com/rust-lang/cargo/issues/14125)

The directory where intermediate build artifacts will be stored.
Intermediate artifacts are produced by Rustc/Cargo during the build process.

```toml
[build]
build-dir = "out"
```

### `build.build-dir`

* Type: string (path)
* Default: Defaults to the value of `build.target-dir`
* Environment: `CARGO_BUILD_BUILD_DIR`

The path to where internal files used as part of the build are placed.

This option supports path templating.

Available template variables:
* `{workspace-root}` resolves to root of the current workspace.
* `{cargo-cache-home}` resolves to `CARGO_HOME`
* `{workspace-path-hash}` resolves to a hash of the manifest path


## root-dir
* Original Issue: [#9887](https://github.com/rust-lang/cargo/issues/9887)
* Tracking Issue: None (not currently slated for stabilization)
Expand Down Expand Up @@ -2230,3 +2201,9 @@ Example:
cargo +nightly build --compile-time-deps -Z unstable-options
cargo +nightly check --compile-time-deps --all-targets -Z unstable-options
```

## build-dir

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

3 changes: 3 additions & 0 deletions tests/testsuite/alt_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ fn alt_reg_metadata() {
],
"resolve": null,
"target_directory": "[ROOT]/foo/target",
"build_directory": "[ROOT]/foo/target",
"version": 1,
"workspace_default_members": [
"path+[ROOTURL]/foo#0.0.1"
Expand Down Expand Up @@ -1347,6 +1348,7 @@ fn alt_reg_metadata() {
"root": "path+[ROOTURL]/foo#0.0.1"
},
"target_directory": "[ROOT]/foo/target",
"build_directory": "[ROOT]/foo/target",
"version": 1,
"workspace_default_members": [
"path+[ROOTURL]/foo#0.0.1"
Expand Down Expand Up @@ -1609,6 +1611,7 @@ fn unknown_registry() {
"root": "path+[ROOTURL]/foo#0.0.1"
},
"target_directory": "[ROOT]/foo/target",
"build_directory": "[ROOT]/foo/target",
"version": 1,
"workspace_default_members": [
"path+[ROOTURL]/foo#0.0.1"
Expand Down
Loading
Loading