@@ -5,7 +5,6 @@ use std::io::{self, BufRead, BufReader, BufWriter, Write};
55use std:: ops:: Not ;
66use std:: path:: { Path , PathBuf } ;
77use std:: process:: Command ;
8- use std:: collections:: HashMap ;
98
109use serde:: { Deserialize , Serialize } ;
1110
@@ -50,7 +49,16 @@ struct CrateRunInfo {
5049 /// The command-line arguments.
5150 args : Vec < OsString > ,
5251 /// The environment.
53- env : HashMap < OsString , OsString > ,
52+ env : Vec < ( OsString , OsString ) > ,
53+ }
54+
55+ impl CrateRunInfo {
56+ /// Gather all the information we need.
57+ fn collect ( args : env:: ArgsOs ) -> Self {
58+ let args = args. collect ( ) ;
59+ let env = env:: vars_os ( ) . collect ( ) ;
60+ CrateRunInfo { args, env }
61+ }
5462}
5563
5664fn show_help ( ) {
@@ -128,6 +136,11 @@ fn xargo_check() -> Command {
128136 Command :: new ( env:: var_os ( "XARGO_CHECK" ) . unwrap_or_else ( || OsString :: from ( "xargo-check" ) ) )
129137}
130138
139+ fn exec ( mut cmd : Command ) -> ! {
140+ let exit_status = cmd. status ( ) . expect ( "failed to run command" ) ;
141+ std:: process:: exit ( exit_status. code ( ) . unwrap_or ( -1 ) )
142+ }
143+
131144fn xargo_version ( ) -> Option < ( u32 , u32 , u32 ) > {
132145 let out = xargo_check ( ) . arg ( "--version" ) . output ( ) . ok ( ) ?;
133146 if !out. status . success ( ) {
@@ -346,17 +359,16 @@ path = "lib.rs"
346359 }
347360}
348361
349- fn phase_cargo_miri ( mut args : env:: Args ) {
362+ fn phase_cargo_miri ( mut args : env:: ArgsOs ) {
350363 // Require a subcommand before any flags.
351364 // We cannot know which of those flags take arguments and which do not,
352365 // so we cannot detect subcommands later.
353- let subcommand = match args. next ( ) . as_deref ( ) {
366+ let subcommand = match args. next ( ) . as_deref ( ) . and_then ( |s| s . to_str ( ) ) {
354367 Some ( "test" ) => MiriCommand :: Test ,
355368 Some ( "run" ) => MiriCommand :: Run ,
356369 Some ( "setup" ) => MiriCommand :: Setup ,
357370 // Invalid command.
358- None => show_error ( format ! ( "`cargo miri` must be immediately followed by `test`, `run`, or `setup`." ) ) ,
359- Some ( s) => show_error ( format ! ( "unknown command `{}`" , s) ) ,
371+ _ => show_error ( format ! ( "`cargo miri` must be immediately followed by `test`, `run`, or `setup`." ) ) ,
360372 } ;
361373 let verbose = has_arg_flag ( "-v" ) ;
362374
@@ -410,13 +422,10 @@ fn phase_cargo_miri(mut args: env::Args) {
410422 cmd. env ( "MIRI_VERBOSE" , "" ) ; // this makes `inside_cargo_rustc` verbose.
411423 eprintln ! ( "+ {:?}" , cmd) ;
412424 }
413- let exit_status =
414- cmd. spawn ( ) . expect ( "could not run cargo" ) . wait ( ) . expect ( "failed to wait for cargo?" ) ;
415-
416- std:: process:: exit ( exit_status. code ( ) . unwrap_or ( -1 ) )
425+ exec ( cmd)
417426}
418427
419- fn phase_cargo_rustc ( mut args : env:: Args ) {
428+ fn phase_cargo_rustc ( args : env:: ArgsOs ) {
420429 /// Determines if we are being invoked (as rustc) to build a crate for
421430 /// the "target" architecture, in contrast to the "host" architecture.
422431 /// Host crates are for build scripts and proc macros and still need to
@@ -451,7 +460,7 @@ fn phase_cargo_rustc(mut args: env::Args) {
451460 // like we want them.
452461 // Instead of compiling, we write JSON into the output file with all the relevant command-line flags
453462 // and environment variables; this is sued alter when cargo calls us again in the CARGO_TARGET_RUNNER phase.
454- let info = CrateRunInfo { args : Vec :: new ( ) , env : HashMap :: new ( ) } ;
463+ let info = CrateRunInfo :: collect ( args ) ;
455464
456465 let mut path = PathBuf :: from ( get_arg_flag_value ( "--out-dir" ) . unwrap ( ) ) ;
457466 path. push ( format ! (
@@ -461,14 +470,12 @@ fn phase_cargo_rustc(mut args: env::Args) {
461470 // (and cargo passes this before the filename so it should be unique)
462471 get_arg_flag_value( "extra-filename" ) . unwrap_or( String :: new( ) ) ,
463472 ) ) ;
464- eprintln ! ( "Miri is supposed to run {}" , path. display( ) ) ;
465473
466474 let file = File :: create ( & path)
467475 . unwrap_or_else ( |_| show_error ( format ! ( "Cannot create {}" , path. display( ) ) ) ) ;
468476 let file = BufWriter :: new ( file) ;
469477 serde_json:: ser:: to_writer ( file, & info)
470478 . unwrap_or_else ( |_| show_error ( format ! ( "Cannot write to {}" , path. display( ) ) ) ) ;
471-
472479 return ;
473480 }
474481
@@ -495,24 +502,36 @@ fn phase_cargo_rustc(mut args: env::Args) {
495502 if verbose {
496503 eprintln ! ( "+ {:?}" , cmd) ;
497504 }
498- match cmd. status ( ) {
499- Ok ( exit) =>
500- if !exit. success ( ) {
501- std:: process:: exit ( exit. code ( ) . unwrap_or ( 42 ) ) ;
502- } ,
503- Err ( e) => panic ! ( "error running {:?}:\n {:?}" , cmd, e) ,
504- }
505+ exec ( cmd)
505506}
506507
507- fn phase_cargo_runner ( binary : & str , args : env:: Args ) {
508- eprintln ! ( "Asked to execute {}, args: {:?}" , binary , args . collect :: < Vec <_>> ( ) ) ;
508+ fn phase_cargo_runner ( binary : & str , args : env:: ArgsOs ) {
509+ let verbose = std :: env :: var_os ( "MIRI_VERBOSE" ) . is_some ( ) ;
509510
510511 let file = File :: open ( binary)
511512 . unwrap_or_else ( |_| show_error ( format ! ( "File {:?} not found, or cargo-miri invoked incorrectly" , binary) ) ) ;
512513 let file = BufReader :: new ( file) ;
513514 let info: CrateRunInfo = serde_json:: from_reader ( file)
514515 . unwrap_or_else ( |_| show_error ( format ! ( "File {:?} does not contain valid JSON" , binary) ) ) ;
515516 // FIXME: remove the file.
517+
518+ let mut cmd = miri ( ) ;
519+ // Forward rustc arguments,with our sysroot.
520+ cmd. args ( info. args ) ;
521+ let sysroot =
522+ env:: var_os ( "MIRI_SYSROOT" ) . expect ( "The wrapper should have set MIRI_SYSROOT" ) ;
523+ cmd. arg ( "--sysroot" ) ;
524+ cmd. arg ( sysroot) ;
525+
526+ // Then pass binary arguments.
527+ cmd. arg ( "--" ) ;
528+ cmd. args ( args) ;
529+
530+ // Run it.
531+ if verbose {
532+ eprintln ! ( "+ {:?}" , cmd) ;
533+ }
534+ exec ( cmd)
516535}
517536
518537fn main ( ) {
@@ -526,7 +545,7 @@ fn main() {
526545 return ;
527546 }
528547
529- let mut args = std:: env:: args ( ) ;
548+ let mut args = std:: env:: args_os ( ) ;
530549 // Skip binary name.
531550 args. next ( ) . unwrap ( ) ;
532551
@@ -537,7 +556,8 @@ fn main() {
537556 // binary crates for later interpretation.
538557 // - When we are executed due to CARGO_TARGET_RUNNER, we start interpretation based on the
539558 // flags that were stored earlier.
540- match & * args. next ( ) . unwrap ( ) {
559+ // FIXME: report errors for these unwraps.
560+ match & * args. next ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) {
541561 "miri" => phase_cargo_miri ( args) ,
542562 "rustc" => phase_cargo_rustc ( args) ,
543563 binary => phase_cargo_runner ( binary, args) ,
0 commit comments