From aab7b908180f290b99a86fabdbb7d0fc0b47eed7 Mon Sep 17 00:00:00 2001 From: Ross Sullivan Date: Sat, 25 Jan 2025 21:27:40 +0900 Subject: [PATCH] Added build.build_dir configuration option This commit adds a `build_dir` option to the `build` table in `config.toml` and adds the equivalent field to `Workspace` and `GlobalContext`. --- src/cargo/core/workspace.rs | 16 ++++++++++++++++ src/cargo/util/context/mod.rs | 31 ++++++++++++++++++++++++++++++- src/doc/src/reference/unstable.md | 22 ++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 277af3587d7..60a06bae5d4 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -67,6 +67,10 @@ pub struct Workspace<'gctx> { /// `None` if the default path of `root/target` should be used. target_dir: Option, + /// Shared build directory for intermediate build artifacts. + /// This directory may be shared between multiple workspaces. + build_dir: Option, + /// 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. @@ -209,6 +213,7 @@ impl<'gctx> Workspace<'gctx> { pub fn new(manifest_path: &Path, gctx: &'gctx GlobalContext) -> CargoResult> { 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!( @@ -238,6 +243,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(), @@ -282,6 +288,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()); @@ -418,6 +425,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()); diff --git a/src/cargo/util/context/mod.rs b/src/cargo/util/context/mod.rs index 0b388978d69..72aa2d8735a 100644 --- a/src/cargo/util/context/mod.rs +++ b/src/cargo/util/context/mod.rs @@ -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> { if let Some(dir) = &self.target_dir { Ok(Some(dir.clone())) @@ -634,6 +634,34 @@ impl GlobalContext { } } + /// The directory to use for intermediate build artifacts. + /// + /// Falls back to the target directory if not specified. + /// + /// Callers should prefer [`Workspace::build_dir`] instead. + pub fn build_dir(&self) -> CargoResult> { + 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 @@ -2653,6 +2681,7 @@ pub struct CargoBuildConfig { pub pipelining: Option, pub dep_info_basedir: Option, pub target_dir: Option, + pub build_dir: Option, pub incremental: Option, pub target: Option, pub jobs: Option, diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 6cbad3c49d3..da2ece53686 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -78,6 +78,7 @@ 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 @@ -238,6 +239,27 @@ 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. + + ## root-dir * Original Issue: [#9887](https://github.com/rust-lang/cargo/issues/9887) * Tracking Issue: None (not currently slated for stabilization)