Skip to content

Commit 10a4f4c

Browse files
committed
Implemented templating support for build.build-dir
1 parent 125858a commit 10a4f4c

File tree

4 files changed

+63
-24
lines changed

4 files changed

+63
-24
lines changed

src/cargo/core/workspace.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ impl<'gctx> Workspace<'gctx> {
213213
pub fn new(manifest_path: &Path, gctx: &'gctx GlobalContext) -> CargoResult<Workspace<'gctx>> {
214214
let mut ws = Workspace::new_default(manifest_path.to_path_buf(), gctx);
215215
ws.target_dir = gctx.target_dir()?;
216-
ws.build_dir = gctx.build_dir()?;
217216

218217
if manifest_path.is_relative() {
219218
bail!(
@@ -224,6 +223,12 @@ impl<'gctx> Workspace<'gctx> {
224223
ws.root_manifest = ws.find_root(manifest_path)?;
225224
}
226225

226+
ws.build_dir = gctx.build_dir(
227+
ws.root_manifest
228+
.as_ref()
229+
.unwrap_or(&manifest_path.to_path_buf()),
230+
)?;
231+
227232
ws.custom_metadata = ws
228233
.load_workspace_config()?
229234
.and_then(|cfg| cfg.custom_metadata);

src/cargo/util/context/mod.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -636,13 +636,36 @@ impl GlobalContext {
636636
/// Falls back to the target directory if not specified.
637637
///
638638
/// Callers should prefer [`Workspace::build_dir`] instead.
639-
pub fn build_dir(&self) -> CargoResult<Option<Filesystem>> {
639+
pub fn build_dir(&self, manifest_path: &PathBuf) -> CargoResult<Option<Filesystem>> {
640640
if !self.cli_unstable().build_dir {
641641
return self.target_dir();
642642
}
643643
if let Some(val) = &self.build_config()?.build_dir {
644-
let path = val.resolve_path(self);
645-
644+
let replacements = vec![
645+
(
646+
"{workspace-root}",
647+
manifest_path
648+
.parent()
649+
.unwrap()
650+
.to_str()
651+
.context("workspace root was not valid utf-8")?
652+
.to_string(),
653+
),
654+
(
655+
"{cargo-cache}",
656+
self.home()
657+
.as_path_unlocked()
658+
.to_str()
659+
.context("cargo home was not valid utf-8")?
660+
.to_string(),
661+
),
662+
(
663+
"{workspace-manifest-path-hash}",
664+
crate::util::hex::short_hash(manifest_path),
665+
),
666+
];
667+
668+
let path = val.resolve_templated_path(self, replacements);
646669
// Check if the target directory is set to an empty string in the config.toml file.
647670
if val.raw_value().is_empty() {
648671
bail!(

src/cargo/util/context/path.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,25 @@ impl ConfigRelativePath {
3232
self.0.definition.root(gctx).join(&self.0.val)
3333
}
3434

35+
/// Same as [`Self::resolve_path`] but will make string replacements
36+
/// before resolving the path.
37+
///
38+
/// `replacements` should be an an [`IntoIterator`] of tuples with the "from" and "to" for the
39+
/// string replacement
40+
pub fn resolve_templated_path(
41+
&self,
42+
gctx: &GlobalContext,
43+
replacements: impl IntoIterator<Item = (impl AsRef<str>, impl AsRef<str>)>,
44+
) -> PathBuf {
45+
let mut value = self.0.val.clone();
46+
47+
for (from, to) in replacements {
48+
value = value.replace(from.as_ref(), to.as_ref());
49+
}
50+
51+
self.0.definition.root(gctx).join(&value)
52+
}
53+
3554
/// Resolves this configuration-relative path to either an absolute path or
3655
/// something appropriate to execute from `PATH`.
3756
///

tests/testsuite/build_dir.rs

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -498,20 +498,15 @@ mod templating {
498498

499499
#[cargo_test]
500500
fn workspace_root() {
501-
let p = project();
502-
let root = p.root();
503-
let p = p
501+
let p = project()
504502
.file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#)
505503
.file(
506504
".cargo/config.toml",
507-
&format!(
508-
r#"
509-
[build]
510-
build-dir = "{}/build-dir"
511-
target-dir = "target-dir"
512-
"#,
513-
root.display()
514-
),
505+
r#"
506+
[build]
507+
build-dir = "{workspace-root}/build-dir"
508+
target-dir = "target-dir"
509+
"#,
515510
)
516511
.build();
517512

@@ -533,14 +528,11 @@ mod templating {
533528
.file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#)
534529
.file(
535530
".cargo/config.toml",
536-
&format!(
537-
r#"
538-
[build]
539-
build-dir = "{}/build-dir"
540-
target-dir = "target-dir"
541-
"#,
542-
paths::home().join(".cargo").display()
543-
),
531+
r#"
532+
[build]
533+
build-dir = "{cargo-cache}/build-dir"
534+
target-dir = "target-dir"
535+
"#,
544536
)
545537
.build();
546538

@@ -574,7 +566,7 @@ mod templating {
574566
".cargo/config.toml",
575567
r#"
576568
[build]
577-
build-dir = "foo/a70a942ddb7da6b4/build-dir"
569+
build-dir = "foo/{workspace-manifest-path-hash}/build-dir"
578570
target-dir = "target-dir"
579571
"#,
580572
)

0 commit comments

Comments
 (0)