File tree 5 files changed +70
-24
lines changed
5 files changed +70
-24
lines changed Original file line number Diff line number Diff line change @@ -213,7 +213,6 @@ impl<'gctx> Workspace<'gctx> {
213
213
pub fn new ( manifest_path : & Path , gctx : & ' gctx GlobalContext ) -> CargoResult < Workspace < ' gctx > > {
214
214
let mut ws = Workspace :: new_default ( manifest_path. to_path_buf ( ) , gctx) ;
215
215
ws. target_dir = gctx. target_dir ( ) ?;
216
- ws. build_dir = gctx. build_dir ( ) ?;
217
216
218
217
if manifest_path. is_relative ( ) {
219
218
bail ! (
@@ -224,6 +223,12 @@ impl<'gctx> Workspace<'gctx> {
224
223
ws. root_manifest = ws. find_root ( manifest_path) ?;
225
224
}
226
225
226
+ ws. build_dir = gctx. build_dir (
227
+ ws. root_manifest
228
+ . as_ref ( )
229
+ . unwrap_or ( & manifest_path. to_path_buf ( ) ) ,
230
+ ) ?;
231
+
227
232
ws. custom_metadata = ws
228
233
. load_workspace_config ( ) ?
229
234
. and_then ( |cfg| cfg. custom_metadata ) ;
Original file line number Diff line number Diff line change @@ -652,13 +652,36 @@ impl GlobalContext {
652
652
/// Falls back to the target directory if not specified.
653
653
///
654
654
/// Callers should prefer [`Workspace::build_dir`] instead.
655
- pub fn build_dir ( & self ) -> CargoResult < Option < Filesystem > > {
655
+ pub fn build_dir ( & self , workspace_manifest_path : & PathBuf ) -> CargoResult < Option < Filesystem > > {
656
656
if !self . cli_unstable ( ) . build_dir {
657
657
return self . target_dir ( ) ;
658
658
}
659
659
if let Some ( val) = & self . build_config ( ) ?. build_dir {
660
- let path = val. resolve_path ( self ) ;
661
-
660
+ let replacements = vec ! [
661
+ (
662
+ "{workspace-root}" ,
663
+ workspace_manifest_path
664
+ . parent( )
665
+ . unwrap( )
666
+ . to_str( )
667
+ . context( "workspace root was not valid utf-8" ) ?
668
+ . to_string( ) ,
669
+ ) ,
670
+ (
671
+ "{cargo-cache-home}" ,
672
+ self . home( )
673
+ . as_path_unlocked( )
674
+ . to_str( )
675
+ . context( "cargo home was not valid utf-8" ) ?
676
+ . to_string( ) ,
677
+ ) ,
678
+ ( "{workspace-manifest-path-hash}" , {
679
+ let hash = crate :: util:: hex:: short_hash( & workspace_manifest_path) ;
680
+ format!( "{}{}{}" , & hash[ 0 ..2 ] , std:: path:: MAIN_SEPARATOR , & hash[ 2 ..] )
681
+ } ) ,
682
+ ] ;
683
+
684
+ let path = val. resolve_templated_path ( self , replacements) ;
662
685
// Check if the target directory is set to an empty string in the config.toml file.
663
686
if val. raw_value ( ) . is_empty ( ) {
664
687
bail ! (
Original file line number Diff line number Diff line change @@ -32,6 +32,25 @@ impl ConfigRelativePath {
32
32
self . 0 . definition . root ( gctx) . join ( & self . 0 . val )
33
33
}
34
34
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
+
35
54
/// Resolves this configuration-relative path to either an absolute path or
36
55
/// something appropriate to execute from `PATH`.
37
56
///
Original file line number Diff line number Diff line change @@ -260,6 +260,13 @@ build-dir = "out"
260
260
261
261
The path to where internal files used as part of the build are placed.
262
262
263
+ This option supports path templating.
264
+
265
+ Avaiable template variables:
266
+ * ` {workspace-root} ` resolves to root of the current workspace.
267
+ * ` {cargo-cache-home} ` resolves to ` CARGO_HOME `
268
+ * ` {workspace-manifest-path-hash} ` resolves to a hash of the manifest path
269
+
263
270
264
271
## root-dir
265
272
* Original Issue: [ #9887 ] ( https://github.com/rust-lang/cargo/issues/9887 )
Original file line number Diff line number Diff line change @@ -493,20 +493,15 @@ fn future_incompat_should_output_to_build_dir() {
493
493
494
494
#[ cargo_test]
495
495
fn template_workspace_root ( ) {
496
- let p = project ( ) ;
497
- let root = p. root ( ) ;
498
- let p = p
496
+ let p = project ( )
499
497
. file ( "src/main.rs" , r#"fn main() { println!("Hello, World!") }"# )
500
498
. file (
501
499
".cargo/config.toml" ,
502
- & format ! (
503
- r#"
504
- [build]
505
- build-dir = "{}/build-dir"
506
- target-dir = "target-dir"
507
- "# ,
508
- root. display( )
509
- ) ,
500
+ r#"
501
+ [build]
502
+ build-dir = "{workspace-root}/build-dir"
503
+ target-dir = "target-dir"
504
+ "# ,
510
505
)
511
506
. build ( ) ;
512
507
@@ -528,14 +523,11 @@ fn template_cargo_cache_home() {
528
523
. file ( "src/main.rs" , r#"fn main() { println!("Hello, World!") }"# )
529
524
. file (
530
525
".cargo/config.toml" ,
531
- & format ! (
532
- r#"
533
- [build]
534
- build-dir = "{}/build-dir"
535
- target-dir = "target-dir"
536
- "# ,
537
- paths:: home( ) . join( ".cargo" ) . display( )
538
- ) ,
526
+ r#"
527
+ [build]
528
+ build-dir = "{cargo-cache-home}/build-dir"
529
+ target-dir = "target-dir"
530
+ "# ,
539
531
)
540
532
. build ( ) ;
541
533
@@ -569,7 +561,7 @@ fn template_workspace_manfiest_path_hash() {
569
561
".cargo/config.toml" ,
570
562
r#"
571
563
[build]
572
- build-dir = "foo/a7/0a942ddb7da6b4 /build-dir"
564
+ build-dir = "foo/{workspace-manifest-path-hash} /build-dir"
573
565
target-dir = "target-dir"
574
566
"# ,
575
567
)
You can’t perform that action at this time.
0 commit comments