@@ -138,9 +138,13 @@ fn xargo_check() -> Command {
138
138
Command :: new ( env:: var_os ( "XARGO_CHECK" ) . unwrap_or_else ( || OsString :: from ( "xargo-check" ) ) )
139
139
}
140
140
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 ) {
142
144
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
+ }
144
148
}
145
149
146
150
fn xargo_version ( ) -> Option < ( u32 , u32 , u32 ) > {
@@ -453,6 +457,20 @@ fn phase_cargo_rustc(args: env::ArgsOs) {
453
457
( is_bin || is_test) && !print
454
458
}
455
459
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
+
456
474
let verbose = std:: env:: var_os ( "MIRI_VERBOSE" ) . is_some ( ) ;
457
475
let target_crate = is_target_crate ( ) ;
458
476
@@ -463,60 +481,58 @@ fn phase_cargo_rustc(args: env::ArgsOs) {
463
481
// Instead of compiling, we write JSON into the output file with all the relevant command-line flags
464
482
// and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase.
465
483
let info = CrateRunInfo :: collect ( args) ;
484
+ // FIXME: Windows might need a ".exe" suffix.
485
+ let filename = out_filename ( "" , "" ) ;
466
486
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
- ) ) ;
475
487
if verbose {
476
- eprintln ! ( "[cargo-miri rustc] writing run info to {:?}" , path . display( ) ) ;
488
+ eprintln ! ( "[cargo-miri rustc] writing run info to {:?}" , filename . display( ) ) ;
477
489
}
478
490
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( ) ) ) ) ;
481
493
let file = BufWriter :: new ( file) ;
482
494
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( ) ) ) ) ;
484
496
return ;
485
497
}
486
498
487
499
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
+ }
503
521
}
522
+ cmd. arg ( format ! ( "{}={}" , emit_flag, val. join( "," ) ) ) ;
523
+ } else {
524
+ cmd. arg ( arg) ;
504
525
}
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) ;
509
526
}
510
- }
511
527
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.
516
529
let sysroot =
517
530
env:: var_os ( "MIRI_SYSROOT" ) . expect ( "The wrapper should have set MIRI_SYSROOT" ) ;
518
531
cmd. arg ( "--sysroot" ) ;
519
532
cmd. arg ( sysroot) ;
533
+ } else {
534
+ // For host crates, just forward everything.
535
+ cmd. args ( args) ;
520
536
}
521
537
522
538
// 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) {
527
543
if verbose {
528
544
eprintln ! ( "[cargo-miri rustc] {:?}" , cmd) ;
529
545
}
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
+ }
531
554
}
532
555
533
556
fn phase_cargo_runner ( binary : & OsStr , binary_args : env:: ArgsOs ) {
0 commit comments