@@ -858,7 +858,7 @@ impl AppSettings for RustAppSettings {
858858 let bin_name = self . cargo_package_settings ( ) . name . clone ( ) ;
859859
860860 let out_dir = self
861- . out_dir ( options. target . clone ( ) , get_profile_dir ( options ) . to_string ( ) )
861+ . out_dir ( options)
862862 . with_context ( || "failed to get project out directory" ) ?;
863863
864864 let binary_extension: String = if self . target_triple . contains ( "windows" ) {
@@ -1081,13 +1081,15 @@ impl RustAppSettings {
10811081 & self . cargo_package_settings
10821082 }
10831083
1084- pub fn out_dir ( & self , target : Option < String > , profile : String ) -> crate :: Result < PathBuf > {
1085- get_target_dir (
1086- target
1087- . as_deref ( )
1088- . or_else ( || self . cargo_config . build ( ) . target ( ) ) ,
1089- profile,
1090- )
1084+ fn target < ' a > ( & ' a self , options : & ' a Options ) -> Option < & ' a str > {
1085+ options
1086+ . target
1087+ . as_deref ( )
1088+ . or_else ( || self . cargo_config . build ( ) . target ( ) )
1089+ }
1090+
1091+ pub fn out_dir ( & self , options : & Options ) -> crate :: Result < PathBuf > {
1092+ get_target_dir ( self . target ( options) , options)
10911093 }
10921094}
10931095
@@ -1115,20 +1117,39 @@ fn get_cargo_metadata() -> crate::Result<CargoMetadata> {
11151117
11161118/// This function determines the 'target' directory and suffixes it with the profile
11171119/// to determine where the compiled binary will be located.
1118- fn get_target_dir ( target : Option < & str > , profile : String ) -> crate :: Result < PathBuf > {
1119- let mut path = get_cargo_metadata ( )
1120- . with_context ( || "failed to get cargo metadata" ) ?
1121- . target_directory ;
1120+ fn get_target_dir ( triple : Option < & str > , options : & Options ) -> crate :: Result < PathBuf > {
1121+ let mut path = if let Some ( target) = get_cargo_option ( & options. args , "--target-dir" ) {
1122+ std:: env:: current_dir ( ) ?. join ( target)
1123+ } else {
1124+ let mut path = get_cargo_metadata ( )
1125+ . with_context ( || "failed to get cargo metadata" ) ?
1126+ . target_directory ;
11221127
1123- if let Some ( triple) = target {
1124- path. push ( triple) ;
1125- }
1128+ if let Some ( triple) = triple {
1129+ path. push ( triple) ;
1130+ }
1131+
1132+ path
1133+ } ;
11261134
1127- path. push ( profile ) ;
1135+ path. push ( get_profile_dir ( options ) ) ;
11281136
11291137 Ok ( path)
11301138}
11311139
1140+ #[ inline]
1141+ fn get_cargo_option < ' a > ( args : & ' a [ String ] , option : & ' a str ) -> Option < & ' a str > {
1142+ args
1143+ . iter ( )
1144+ . position ( |a| a. starts_with ( option) )
1145+ . and_then ( |i| {
1146+ args[ i]
1147+ . split_once ( '=' )
1148+ . map ( |( _, p) | Some ( p) )
1149+ . unwrap_or_else ( || args. get ( i + 1 ) . map ( |s| s. as_str ( ) ) )
1150+ } )
1151+ }
1152+
11321153/// Executes `cargo metadata` to get the workspace directory.
11331154pub fn get_workspace_dir ( ) -> crate :: Result < PathBuf > {
11341155 Ok (
@@ -1139,17 +1160,11 @@ pub fn get_workspace_dir() -> crate::Result<PathBuf> {
11391160}
11401161
11411162pub fn get_profile ( options : & Options ) -> & str {
1142- options
1143- . args
1144- . iter ( )
1145- . position ( |a| a. starts_with ( "--profile" ) )
1146- . and_then ( |i| {
1147- options. args [ i]
1148- . split_once ( '=' )
1149- . map ( |( _, p) | Some ( p) )
1150- . unwrap_or_else ( || options. args . get ( i + 1 ) . map ( |s| s. as_str ( ) ) )
1151- } )
1152- . unwrap_or ( if options. debug { "dev" } else { "release" } )
1163+ get_cargo_option ( & options. args , "--profile" ) . unwrap_or ( if options. debug {
1164+ "dev"
1165+ } else {
1166+ "release"
1167+ } )
11531168}
11541169
11551170pub fn get_profile_dir ( options : & Options ) -> & str {
@@ -1479,6 +1494,25 @@ mod pkgconfig_utils {
14791494mod tests {
14801495 use super :: * ;
14811496
1497+ #[ test]
1498+ fn parse_cargo_option ( ) {
1499+ let args = vec ! [
1500+ "build" . into( ) ,
1501+ "--" . into( ) ,
1502+ "--profile" . into( ) ,
1503+ "holla" . into( ) ,
1504+ "--features" . into( ) ,
1505+ "a" . into( ) ,
1506+ "b" . into( ) ,
1507+ "--target-dir" . into( ) ,
1508+ "path/to/dir" . into( ) ,
1509+ ] ;
1510+
1511+ assert_eq ! ( get_cargo_option( & args, "--profile" ) , Some ( "holla" ) ) ;
1512+ assert_eq ! ( get_cargo_option( & args, "--target-dir" ) , Some ( "path/to/dir" ) ) ;
1513+ assert_eq ! ( get_cargo_option( & args, "--non-existent" ) , None ) ;
1514+ }
1515+
14821516 #[ test]
14831517 fn parse_profile_from_opts ( ) {
14841518 let options = Options {
@@ -1539,4 +1573,77 @@ mod tests {
15391573 } ;
15401574 assert_eq ! ( get_profile( & options) , "release" ) ;
15411575 }
1576+
1577+ #[ test]
1578+ fn parse_target_dir_from_opts ( ) {
1579+ let current_dir = std:: env:: current_dir ( ) . unwrap ( ) ;
1580+
1581+ let options = Options {
1582+ args : vec ! [
1583+ "build" . into( ) ,
1584+ "--" . into( ) ,
1585+ "--target-dir" . into( ) ,
1586+ "path/to/some/dir" . into( ) ,
1587+ "--features" . into( ) ,
1588+ "feat1" . into( ) ,
1589+ ] ,
1590+ debug : false ,
1591+ ..Default :: default ( )
1592+ } ;
1593+
1594+ assert_eq ! (
1595+ get_target_dir( None , & options) . unwrap( ) ,
1596+ current_dir. join( "path/to/some/dir/release" )
1597+ ) ;
1598+ assert_eq ! (
1599+ get_target_dir( Some ( "x86_64-pc-windows-msvc" ) , & options) . unwrap( ) ,
1600+ current_dir. join( "path/to/some/dir/release" )
1601+ ) ;
1602+
1603+ let options = Options {
1604+ args : vec ! [
1605+ "build" . into( ) ,
1606+ "--" . into( ) ,
1607+ "--features" . into( ) ,
1608+ "feat1" . into( ) ,
1609+ ] ,
1610+ debug : false ,
1611+ ..Default :: default ( )
1612+ } ;
1613+
1614+ #[ cfg( windows) ]
1615+ assert ! ( get_target_dir( Some ( "x86_64-pc-windows-msvc" ) , & options)
1616+ . unwrap( )
1617+ . ends_with( "x86_64-pc-windows-msvc\\ release" ) ) ;
1618+ #[ cfg( not( windows) ) ]
1619+ assert ! ( get_target_dir( Some ( "x86_64-pc-windows-msvc" ) , & options)
1620+ . unwrap( )
1621+ . ends_with( "x86_64-pc-windows-msvc/release" ) ) ;
1622+
1623+ #[ cfg( windows) ]
1624+ {
1625+ std:: env:: set_var ( "CARGO_TARGET_DIR" , "D:\\ path\\ to\\ env\\ dir" ) ;
1626+ assert_eq ! (
1627+ get_target_dir( None , & options) . unwrap( ) ,
1628+ PathBuf :: from( "D:\\ path\\ to\\ env\\ dir\\ release" )
1629+ ) ;
1630+ assert_eq ! (
1631+ get_target_dir( Some ( "x86_64-pc-windows-msvc" ) , & options) . unwrap( ) ,
1632+ PathBuf :: from( "D:\\ path\\ to\\ env\\ dir\\ x86_64-pc-windows-msvc\\ release" )
1633+ ) ;
1634+ }
1635+
1636+ #[ cfg( not( windows) ) ]
1637+ {
1638+ std:: env:: set_var ( "CARGO_TARGET_DIR" , "/path/to/env/dir" ) ;
1639+ assert_eq ! (
1640+ get_target_dir( None , & options) . unwrap( ) ,
1641+ PathBuf :: from( "/path/to/env/dir/release" )
1642+ ) ;
1643+ assert_eq ! (
1644+ get_target_dir( Some ( "x86_64-pc-windows-msvc" ) , & options) . unwrap( ) ,
1645+ PathBuf :: from( "/path/to/env/dir/x86_64-pc-windows-msvc/release" )
1646+ ) ;
1647+ }
1648+ }
15421649}
0 commit comments