Skip to content

Commit

Permalink
Added build.build_dir configuration option
Browse files Browse the repository at this point in the history
This commit adds a `build_dir` option to the `build` table in
`config.toml` and adds the equivalent field to `Workspace` and `GlobalContext`.
  • Loading branch information
ranger-ross committed Feb 7, 2025
1 parent dea3702 commit 417b9a9
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ pub struct Workspace<'gctx> {
/// `None` if the default path of `root/target` should be used.
target_dir: Option<Filesystem>,

/// Shared build directory for intermediate build artifacts.
/// This directory may be shared between multiple workspaces.
build_dir: Option<Filesystem>,

/// List of members in this workspace with a listing of all their manifest
/// paths. The packages themselves can be looked up through the `packages`
/// set above.
Expand Down Expand Up @@ -207,6 +211,7 @@ impl<'gctx> Workspace<'gctx> {
pub fn new(manifest_path: &Path, gctx: &'gctx GlobalContext) -> CargoResult<Workspace<'gctx>> {
let mut ws = Workspace::new_default(manifest_path.to_path_buf(), gctx);
ws.target_dir = gctx.target_dir()?;
ws.build_dir = gctx.build_dir()?;

if manifest_path.is_relative() {
bail!(
Expand Down Expand Up @@ -236,6 +241,7 @@ impl<'gctx> Workspace<'gctx> {
},
root_manifest: None,
target_dir: None,
build_dir: None,
members: Vec::new(),
member_ids: HashSet::new(),
default_members: Vec::new(),
Expand Down Expand Up @@ -279,6 +285,7 @@ impl<'gctx> Workspace<'gctx> {
} else {
ws.gctx.target_dir()?
};
ws.build_dir = ws.target_dir.clone();
ws.members.push(ws.current_manifest.clone());
ws.member_ids.insert(id);
ws.default_members.push(ws.current_manifest.clone());
Expand Down Expand Up @@ -408,6 +415,15 @@ impl<'gctx> Workspace<'gctx> {
.unwrap_or_else(|| self.default_target_dir())
}

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.default_target_dir())
}

fn default_target_dir(&self) -> Filesystem {
if self.root_maybe().is_embedded() {
let hash = crate::util::hex::short_hash(&self.root_manifest().to_string_lossy());
Expand Down
32 changes: 31 additions & 1 deletion src/cargo/util/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ impl GlobalContext {
///
/// Returns `None` if the user has not chosen an explicit directory.
///
/// Callers should prefer `Workspace::target_dir` instead.
/// Callers should prefer [`Workspace::target_dir`] instead.
pub fn target_dir(&self) -> CargoResult<Option<Filesystem>> {
if let Some(dir) = &self.target_dir {
Ok(Some(dir.clone()))
Expand Down Expand Up @@ -634,6 +634,35 @@ impl GlobalContext {
}
}

/// The directory to use for intermediate build artifacts.
///
/// Fallsback to the target directory if not specified.
///
/// Callers should prefer [`Workspace::build_dir`] instead.
pub fn build_dir(&self) -> CargoResult<Option<Filesystem>> {
if !self.cli_unstable().build_dir {
return self.target_dir();
}

if let Some(val) = &self.build_config()?.build_dir {
let path = val.resolve_path(self);

// Check if the target directory is set to an empty string in the config.toml file.
if val.raw_value().is_empty() {
bail!(
"the build directory is set to an empty string in {}",
val.value().definition
)
}

Ok(Some(Filesystem::new(path)))
} else {
// For now, fallback to the previous implementation.
// This will change in the future.
return self.target_dir();
}
}

/// Get a configuration value by key.
///
/// This does NOT look at environment variables. See `get_cv_with_env` for
Expand Down Expand Up @@ -2653,6 +2682,7 @@ pub struct CargoBuildConfig {
pub pipelining: Option<bool>,
pub dep_info_basedir: Option<ConfigRelativePath>,
pub target_dir: Option<ConfigRelativePath>,
pub build_dir: Option<ConfigRelativePath>,
pub incremental: Option<bool>,
pub target: Option<BuildTargetConfig>,
pub jobs: Option<JobsConfig>,
Expand Down
17 changes: 17 additions & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ Each new feature described below should explain how to use it.
* [update-breaking](#update-breaking) --- Allows upgrading to breaking versions with `update --breaking`
* 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 @@ -237,6 +238,22 @@ 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)

This feature allows you to specify the directory where intermediate build artifacts will be stored.
The final artifacts will also be contained in this directory but will be hardlinked into the artifact directory (usually `target`)

This can be specified in `.cargo/config.toml` files using the `build.build-dir`.

Example:

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

## root-dir
* Original Issue: [#9887](https://github.com/rust-lang/cargo/issues/9887)
* Tracking Issue: None (not currently slated for stabilization)
Expand Down

0 comments on commit 417b9a9

Please sign in to comment.