@@ -138,9 +138,13 @@ fn xargo_check() -> Command {
138138 Command :: new ( env:: var_os ( "XARGO_CHECK" ) . unwrap_or_else ( || OsString :: from ( "xargo-check" ) ) )
139139}
140140
141- fn exec ( mut cmd : Command ) -> ! {
141+ /// Execute the command if it fails, fail this process with the same exit code.
142+ /// Otherwise, continue.
143+ fn exec ( mut cmd : Command ) {
142144 let exit_status = cmd. status ( ) . expect ( "failed to run command" ) ;
143- std:: process:: exit ( exit_status. code ( ) . unwrap_or ( -1 ) )
145+ if exit_status. success ( ) . not ( ) {
146+ std:: process:: exit ( exit_status. code ( ) . unwrap_or ( -1 ) )
147+ }
144148}
145149
146150fn xargo_version ( ) -> Option < ( u32 , u32 , u32 ) > {
@@ -453,6 +457,20 @@ fn phase_cargo_rustc(args: env::ArgsOs) {
453457 ( is_bin || is_test) && !print
454458 }
455459
460+ fn out_filename ( prefix : & str , suffix : & str ) -> PathBuf {
461+ let mut path = PathBuf :: from ( get_arg_flag_value ( "--out-dir" ) . unwrap ( ) ) ;
462+ path. push ( format ! (
463+ "{}{}{}{}" ,
464+ prefix,
465+ get_arg_flag_value( "--crate-name" ) . unwrap( ) ,
466+ // This is technically a `-C` flag but the prefix seems unique enough...
467+ // (and cargo passes this before the filename so it should be unique)
468+ get_arg_flag_value( "extra-filename" ) . unwrap_or( String :: new( ) ) ,
469+ suffix,
470+ ) ) ;
471+ path
472+ }
473+
456474 let verbose = std:: env:: var_os ( "MIRI_VERBOSE" ) . is_some ( ) ;
457475 let target_crate = is_target_crate ( ) ;
458476
@@ -463,60 +481,58 @@ fn phase_cargo_rustc(args: env::ArgsOs) {
463481 // Instead of compiling, we write JSON into the output file with all the relevant command-line flags
464482 // and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase.
465483 let info = CrateRunInfo :: collect ( args) ;
484+ // FIXME: Windows might need a ".exe" suffix.
485+ let filename = out_filename ( "" , "" ) ;
466486
467- let mut path = PathBuf :: from ( get_arg_flag_value ( "--out-dir" ) . unwrap ( ) ) ;
468- path. push ( format ! (
469- "{}{}" ,
470- get_arg_flag_value( "--crate-name" ) . unwrap( ) ,
471- // This is technically a `-C` flag but the prefix seems unique enough...
472- // (and cargo passes this before the filename so it should be unique)
473- get_arg_flag_value( "extra-filename" ) . unwrap_or( String :: new( ) ) ,
474- ) ) ;
475487 if verbose {
476- eprintln ! ( "[cargo-miri rustc] writing run info to {:?}" , path . display( ) ) ;
488+ eprintln ! ( "[cargo-miri rustc] writing run info to {:?}" , filename . display( ) ) ;
477489 }
478490
479- let file = File :: create ( & path )
480- . unwrap_or_else ( |_| show_error ( format ! ( "Cannot create {:?}" , path . display( ) ) ) ) ;
491+ let file = File :: create ( & filename )
492+ . unwrap_or_else ( |_| show_error ( format ! ( "Cannot create {:?}" , filename . display( ) ) ) ) ;
481493 let file = BufWriter :: new ( file) ;
482494 serde_json:: ser:: to_writer ( file, & info)
483- . unwrap_or_else ( |_| show_error ( format ! ( "Cannot write to {:?}" , path . display( ) ) ) ) ;
495+ . unwrap_or_else ( |_| show_error ( format ! ( "Cannot write to {:?}" , filename . display( ) ) ) ) ;
484496 return ;
485497 }
486498
487499 let mut cmd = miri ( ) ;
488- // Forward arguments, but (only for target crates!) remove "link" from "--emit" to make this a check-only build.
489- let emit_flag = "--emit" ;
490- for arg in args {
491- if target_crate && arg. to_string_lossy ( ) . starts_with ( emit_flag) {
492- // Patch this argument. First, extract its value.
493- let arg = arg. to_str ( ) . expect ( "`--emit` must be UTF-8" ) ;
494- let val = & arg[ emit_flag. len ( ) ..] ;
495- assert ! ( val. starts_with( "=" ) , "`cargo` should pass `--emit=X` as one argument" ) ;
496- let val = & val[ 1 ..] ;
497- let mut val: Vec < _ > = val. split ( ',' ) . collect ( ) ;
498- // Now make sure "link" is not in there, but "metadata" is.
499- if let Some ( i) = val. iter ( ) . position ( |& s| s == "link" ) {
500- val. remove ( i) ;
501- if !val. iter ( ) . any ( |& s| s == "metadata" ) {
502- val. push ( "metadata" ) ;
500+ let mut emit_link_hack = false ;
501+ // Arguments are treated very differently depending on whether this crate is
502+ // for interpretation by Miri, or for use by a build script / proc macro.
503+ if target_crate {
504+ // Forward arguments, butremove "link" from "--emit" to make this a check-only build.
505+ let emit_flag = "--emit" ;
506+ for arg in args {
507+ if arg. to_string_lossy ( ) . starts_with ( emit_flag) {
508+ // Patch this argument. First, extract its value.
509+ let arg = arg. to_str ( ) . expect ( "`--emit` must be UTF-8" ) ;
510+ let val = & arg[ emit_flag. len ( ) ..] ;
511+ assert ! ( val. starts_with( "=" ) , "`cargo` should pass `--emit=X` as one argument" ) ;
512+ let val = & val[ 1 ..] ;
513+ let mut val: Vec < _ > = val. split ( ',' ) . collect ( ) ;
514+ // Now make sure "link" is not in there, but "metadata" is.
515+ if let Some ( i) = val. iter ( ) . position ( |& s| s == "link" ) {
516+ emit_link_hack = true ;
517+ val. remove ( i) ;
518+ if !val. iter ( ) . any ( |& s| s == "metadata" ) {
519+ val. push ( "metadata" ) ;
520+ }
503521 }
522+ cmd. arg ( format ! ( "{}={}" , emit_flag, val. join( "," ) ) ) ;
523+ } else {
524+ cmd. arg ( arg) ;
504525 }
505- cmd. arg ( format ! ( "{}={}" , emit_flag, val. join( "," ) ) ) ;
506- // FIXME: due to this, the `.rlib` file does not get created and cargo re-triggers the build each time.
507- } else {
508- cmd. arg ( arg) ;
509526 }
510- }
511527
512- // We make sure to only specify our custom Xargo sysroot for target crates - that is,
513- // crates which are needed for interpretation by Miri. proc-macros and build scripts
514- // should use the default sysroot.
515- if target_crate {
528+ // Use our custom sysroot.
516529 let sysroot =
517530 env:: var_os ( "MIRI_SYSROOT" ) . expect ( "The wrapper should have set MIRI_SYSROOT" ) ;
518531 cmd. arg ( "--sysroot" ) ;
519532 cmd. arg ( sysroot) ;
533+ } else {
534+ // For host crates, just forward everything.
535+ cmd. args ( args) ;
520536 }
521537
522538 // We want to compile, not interpret. We still use Miri to make sure the compiler version etc
@@ -527,7 +543,14 @@ fn phase_cargo_rustc(args: env::ArgsOs) {
527543 if verbose {
528544 eprintln ! ( "[cargo-miri rustc] {:?}" , cmd) ;
529545 }
530- exec ( cmd)
546+ exec ( cmd) ;
547+
548+ // Create a stub .rlib file if "link" was requested by cargo.
549+ if emit_link_hack {
550+ // FIXME: is "lib" always right?
551+ let filename = out_filename ( "lib" , ".rlib" ) ;
552+ File :: create ( filename) . expect ( "Failed to create rlib file" ) ;
553+ }
531554}
532555
533556fn phase_cargo_runner ( binary : & OsStr , binary_args : env:: ArgsOs ) {
0 commit comments