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