@@ -53,25 +53,41 @@ fn show_error(msg: String) -> ! {
5353 std:: process:: exit ( 1 )
5454}
5555
56- fn list_targets ( mut args : impl Iterator < Item =String > ) -> impl Iterator < Item =cargo_metadata:: Target > {
56+ fn get_arg_flag_value ( name : & str ) -> Option < String > {
57+ // stop searching at `--`
58+ let mut args = std:: env:: args ( ) . skip_while ( |val| !( val. starts_with ( name) || val == "--" ) ) ;
59+
60+ match args. next ( ) {
61+ Some ( ref p) if p == "--" => None ,
62+ Some ( ref p) if p == name => args. next ( ) ,
63+ Some ( p) => {
64+ // Make sure this really starts with `$name=`, we didn't test for the `=` yet.
65+ let v = & p[ name. len ( ) ..] ; // strip leading `$name`
66+ if v. starts_with ( '=' ) {
67+ Some ( v[ 1 ..] . to_owned ( ) ) // strip leading `=`
68+ } else {
69+ None
70+ }
71+ } ,
72+ None => None ,
73+ }
74+ }
75+
76+ fn list_targets ( ) -> impl Iterator < Item =cargo_metadata:: Target > {
5777 // We need to get the manifest, and then the metadata, to enumerate targets.
58- let manifest_path_arg = args . find ( |val| {
59- val . starts_with ( "--manifest-path=" )
60- } ) ;
78+ let manifest_path = get_arg_flag_value ( "--manifest-path" ) . map ( |m|
79+ Path :: new ( & m ) . canonicalize ( ) . unwrap ( )
80+ ) ;
6181
6282 let mut metadata = if let Ok ( metadata) = cargo_metadata:: metadata (
63- manifest_path_arg . as_ref ( ) . map ( AsRef :: as_ref) ,
83+ manifest_path . as_ref ( ) . map ( AsRef :: as_ref) ,
6484 )
6585 {
6686 metadata
6787 } else {
6888 show_error ( format ! ( "error: Could not obtain cargo metadata." ) ) ;
6989 } ;
7090
71- let manifest_path = manifest_path_arg. map ( |arg| {
72- PathBuf :: from ( Path :: new ( & arg[ "--manifest-path=" . len ( ) ..] ) )
73- } ) ;
74-
7591 let current_dir = std:: env:: current_dir ( ) ;
7692
7793 let package_index = metadata
@@ -176,17 +192,28 @@ path = "lib.rs"
176192 "# ) . unwrap ( ) ;
177193 File :: create ( dir. join ( "lib.rs" ) ) . unwrap ( ) ;
178194 // Run xargo
179- if !Command :: new ( "xargo" ) . arg ( "build" ) . arg ( "-q" )
195+ let target = get_arg_flag_value ( "--target" ) ;
196+ let mut command = Command :: new ( "xargo" ) ;
197+ command. arg ( "build" ) . arg ( "-q" )
180198 . current_dir ( & dir)
181199 . env ( "RUSTFLAGS" , miri:: miri_default_args ( ) . join ( " " ) )
182- . env ( "XARGO_HOME" , dir. to_str ( ) . unwrap ( ) )
183- . status ( ) . unwrap ( ) . success ( )
200+ . env ( "XARGO_HOME" , dir. to_str ( ) . unwrap ( ) ) ;
201+ if let Some ( ref target) = target {
202+ command. arg ( "--target" ) . arg ( & target) ;
203+ }
204+ if !command. status ( ) . unwrap ( ) . success ( )
184205 {
185206 show_error ( format ! ( "Failed to run xargo" ) ) ;
186207 }
187208
188- // That should be it!
189- let sysroot = dir. join ( "HOST" ) ;
209+ // That should be it! But we need to figure out where xargo built stuff.
210+ // Unfortunately, it puts things into a different directory when the
211+ // architecture matches the host.
212+ let is_host = match target {
213+ None => true ,
214+ Some ( target) => target == rustc_version:: version_meta ( ) . unwrap ( ) . host ,
215+ } ;
216+ let sysroot = if is_host { dir. join ( "HOST" ) } else { PathBuf :: from ( dir) } ;
190217 std:: env:: set_var ( "MIRI_SYSROOT" , & sysroot) ;
191218 if !ask_user {
192219 println ! ( "A libstd for miri is now available in `{}`" , sysroot. display( ) ) ;
@@ -232,7 +259,7 @@ fn main() {
232259 }
233260
234261 // Now run the command.
235- for target in list_targets ( std :: env :: args ( ) . skip ( skip ) ) {
262+ for target in list_targets ( ) {
236263 let args = std:: env:: args ( ) . skip ( skip) ;
237264 let kind = target. kind . get ( 0 ) . expect (
238265 "badly formatted cargo metadata: target::kind is an empty array" ,
@@ -315,22 +342,21 @@ fn main() {
315342 . collect ( )
316343 } ;
317344 args. splice ( 0 ..0 , miri:: miri_default_args ( ) . iter ( ) . map ( ToString :: to_string) ) ;
345+ args. extend_from_slice ( & [ "--cfg" . to_owned ( ) , r#"feature="cargo-miri""# . to_owned ( ) ] ) ;
318346
319347 // this check ensures that dependencies are built but not interpreted and the final crate is
320348 // interpreted but not built
321349 let miri_enabled = std:: env:: args ( ) . any ( |s| s == "--emit=dep-info,metadata" ) ;
322-
323350 let mut command = if miri_enabled {
324351 let mut path = std:: env:: current_exe ( ) . expect ( "current executable path invalid" ) ;
325352 path. set_file_name ( "miri" ) ;
326353 Command :: new ( path)
327354 } else {
328355 Command :: new ( "rustc" )
329356 } ;
357+ command. args ( & args) ;
330358
331- args. extend_from_slice ( & [ "--cfg" . to_owned ( ) , r#"feature="cargo-miri""# . to_owned ( ) ] ) ;
332-
333- match command. args ( & args) . status ( ) {
359+ match command. status ( ) {
334360 Ok ( exit) => {
335361 if !exit. success ( ) {
336362 std:: process:: exit ( exit. code ( ) . unwrap_or ( 42 ) ) ;
@@ -361,7 +387,7 @@ where
361387 args. push ( r#"feature="cargo-miri""# . to_owned ( ) ) ;
362388
363389 let path = std:: env:: current_exe ( ) . expect ( "current executable path invalid" ) ;
364- let exit_status = std :: process :: Command :: new ( "cargo" )
390+ let exit_status = Command :: new ( "cargo" )
365391 . args ( & args)
366392 . env ( "RUSTC" , path)
367393 . spawn ( )
0 commit comments