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