@@ -378,6 +378,74 @@ path = "lib.rs"
378
378
}
379
379
}
380
380
381
+ enum CargoTargets {
382
+ All ,
383
+ Filtered { lib : bool , bin : Vec < String > , test : Vec < String > } ,
384
+ }
385
+
386
+ impl CargoTargets {
387
+ fn matches ( & self , kind : & str , name : & str ) -> bool {
388
+ match self {
389
+ CargoTargets :: All => true ,
390
+ CargoTargets :: Filtered { lib, bin, test } => match kind {
391
+ "lib" => * lib,
392
+ "bin" => bin. iter ( ) . any ( |n| n == name) ,
393
+ "test" => test. iter ( ) . any ( |n| n == name) ,
394
+ _ => false ,
395
+ } ,
396
+ }
397
+ }
398
+ }
399
+
400
+ fn parse_cargo_miri_args (
401
+ mut args : impl Iterator < Item = String > ,
402
+ ) -> ( CargoTargets , Vec < String > , Vec < String > ) {
403
+ let mut lib_present = false ;
404
+ let mut bin_targets = Vec :: new ( ) ;
405
+ let mut test_targets = Vec :: new ( ) ;
406
+ let mut additional_args = Vec :: new ( ) ;
407
+ while let Some ( arg) = args. next ( ) {
408
+ match arg {
409
+ arg if arg == "--" => {
410
+ // Miri arguments begin after the first "--".
411
+ break ;
412
+ }
413
+ arg if arg == "--lib" => lib_present = true ,
414
+ arg if arg == "--bin" => {
415
+ if let Some ( binary) = args. next ( ) {
416
+ if binary == "--" {
417
+ show_error ( format ! ( "\" --bin\" takes one argument." ) ) ;
418
+ } else {
419
+ bin_targets. push ( binary)
420
+ }
421
+ } else {
422
+ show_error ( format ! ( "\" --bin\" takes one argument." ) ) ;
423
+ }
424
+ }
425
+ arg if arg. starts_with ( "--bin=" ) => bin_targets. push ( ( & arg[ "--bin=" . len ( ) ..] ) . to_string ( ) ) ,
426
+ arg if arg == "--test" => {
427
+ if let Some ( test) = args. next ( ) {
428
+ if test == "--" {
429
+ show_error ( format ! ( "\" --test\" takes one argument." ) ) ;
430
+ } else {
431
+ test_targets. push ( test)
432
+ }
433
+ } else {
434
+ show_error ( format ! ( "\" --test\" takes one argument." ) ) ;
435
+ }
436
+ }
437
+ arg if arg. starts_with ( "--test=" ) => test_targets. push ( ( & arg[ "--test=" . len ( ) ..] ) . to_string ( ) ) ,
438
+ other => additional_args. push ( other) ,
439
+ }
440
+ }
441
+ let targets = if !lib_present && bin_targets. len ( ) == 0 && test_targets. len ( ) == 0 {
442
+ CargoTargets :: All
443
+ } else {
444
+ CargoTargets :: Filtered { lib : lib_present, bin : bin_targets, test : test_targets }
445
+ } ;
446
+ ( targets, additional_args, args. collect ( ) )
447
+ }
448
+
381
449
fn in_cargo_miri ( ) {
382
450
let ( subcommand, skip) = match std:: env:: args ( ) . nth ( 2 ) . as_deref ( ) {
383
451
Some ( "test" ) => ( MiriCommand :: Test , 3 ) ,
@@ -398,22 +466,27 @@ fn in_cargo_miri() {
398
466
return ;
399
467
}
400
468
469
+ // FIXME: this accepts --test, --lib, and multiple --bin for `cargo miri run`.
470
+ let ( target_filters, cargo_args, miri_args) =
471
+ parse_cargo_miri_args ( std:: env:: args ( ) . skip ( skip) ) ;
472
+
401
473
// Now run the command.
402
474
for target in list_targets ( ) {
403
- let mut args = std:: env:: args ( ) . skip ( skip) ;
404
475
let kind = target
405
476
. kind
406
477
. get ( 0 )
407
478
. expect ( "badly formatted cargo metadata: target::kind is an empty array" ) ;
479
+ if !target_filters. matches ( kind, & target. name ) {
480
+ continue ;
481
+ }
408
482
// Now we run `cargo check $FLAGS $ARGS`, giving the user the
409
483
// change to add additional arguments. `FLAGS` is set to identify
410
484
// this target. The user gets to control what gets actually passed to Miri.
411
485
let mut cmd = cargo ( ) ;
412
486
cmd. arg ( "check" ) ;
413
487
match ( subcommand, kind. as_str ( ) ) {
414
488
( MiriCommand :: Run , "bin" ) => {
415
- // FIXME: we just run all the binaries here.
416
- // We should instead support `cargo miri --bin foo`.
489
+ // FIXME: we default to running all binaries here.
417
490
cmd. arg ( "--bin" ) . arg ( target. name ) ;
418
491
}
419
492
( MiriCommand :: Test , "test" ) => {
@@ -429,11 +502,8 @@ fn in_cargo_miri() {
429
502
// The remaining targets we do not even want to build.
430
503
_ => continue ,
431
504
}
432
- // Forward user-defined `cargo` args until first `--`.
433
- while let Some ( arg) = args. next ( ) {
434
- if arg == "--" {
435
- break ;
436
- }
505
+ // Forward further `cargo` args.
506
+ for arg in cargo_args. iter ( ) {
437
507
cmd. arg ( arg) ;
438
508
}
439
509
// We want to always run `cargo` with `--target`. This later helps us detect
@@ -450,8 +520,7 @@ fn in_cargo_miri() {
450
520
// our actual target crate (the binary or the test we are running).
451
521
// Since we're using "cargo check", we have no other way of passing
452
522
// these arguments.
453
- let args_vec: Vec < String > = args. collect ( ) ;
454
- cmd. env ( "MIRI_ARGS" , serde_json:: to_string ( & args_vec) . expect ( "failed to serialize args" ) ) ;
523
+ cmd. env ( "MIRI_ARGS" , serde_json:: to_string ( & miri_args) . expect ( "failed to serialize args" ) ) ;
455
524
456
525
// Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation,
457
526
// i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish
0 commit comments