File tree Expand file tree Collapse file tree 5 files changed +70
-24
lines changed Expand file tree Collapse file tree 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> {
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 ) ;
Original file line number Diff line number Diff line change @@ -652,13 +652,36 @@ impl GlobalContext {
652652 /// Falls back to the target directory if not specified.
653653 ///
654654 /// 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 > > {
656656 if !self . cli_unstable ( ) . build_dir {
657657 return self . target_dir ( ) ;
658658 }
659659 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) ;
662685 // Check if the target directory is set to an empty string in the config.toml file.
663686 if val. raw_value ( ) . is_empty ( ) {
664687 bail ! (
Original file line number Diff line number Diff 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 ///
Original file line number Diff line number Diff line change @@ -260,6 +260,13 @@ build-dir = "out"
260260
261261The path to where internal files used as part of the build are placed.
262262
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+
263270
264271## root-dir
265272* 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() {
493493
494494#[ cargo_test]
495495fn template_workspace_root ( ) {
496- let p = project ( ) ;
497- let root = p. root ( ) ;
498- let p = p
496+ let p = project ( )
499497 . file ( "src/main.rs" , r#"fn main() { println!("Hello, World!") }"# )
500498 . file (
501499 ".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+ "# ,
510505 )
511506 . build ( ) ;
512507
@@ -528,14 +523,11 @@ fn template_cargo_cache_home() {
528523 . file ( "src/main.rs" , r#"fn main() { println!("Hello, World!") }"# )
529524 . file (
530525 ".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+ "# ,
539531 )
540532 . build ( ) ;
541533
@@ -569,7 +561,7 @@ fn template_workspace_manfiest_path_hash() {
569561 ".cargo/config.toml" ,
570562 r#"
571563 [build]
572- build-dir = "foo/a7/0a942ddb7da6b4 /build-dir"
564+ build-dir = "foo/{workspace-manifest-path-hash} /build-dir"
573565 target-dir = "target-dir"
574566 "# ,
575567 )
You can’t perform that action at this time.
0 commit comments