1
+ #![ feature( inner_deref) ]
2
+
1
3
extern crate cargo_metadata;
2
4
3
5
use std:: path:: { PathBuf , Path } ;
@@ -25,6 +27,13 @@ it to configure the resource limits
25
27
available resource limits are `memory_size`, `step_limit`, `stack_limit`
26
28
"# ;
27
29
30
+ #[ derive( Copy , Clone , Debug ) ]
31
+ enum MiriCommand {
32
+ Run ,
33
+ Test ,
34
+ Setup ,
35
+ }
36
+
28
37
fn show_help ( ) {
29
38
println ! ( "{}" , CARGO_MIRI_HELP ) ;
30
39
}
@@ -34,6 +43,54 @@ fn show_version() {
34
43
env!( "CARGO_PKG_VERSION" ) , env!( "VERGEN_SHA_SHORT" ) , env!( "VERGEN_COMMIT_DATE" ) ) ;
35
44
}
36
45
46
+ fn list_targets ( mut args : impl Iterator < Item =String > ) -> impl Iterator < Item =cargo_metadata:: Target > {
47
+ // We need to get the manifest, and then the metadata, to enumerate targets.
48
+ let manifest_path_arg = args. find ( |val| {
49
+ val. starts_with ( "--manifest-path=" )
50
+ } ) ;
51
+
52
+ let mut metadata = if let Ok ( metadata) = cargo_metadata:: metadata (
53
+ manifest_path_arg. as_ref ( ) . map ( AsRef :: as_ref) ,
54
+ )
55
+ {
56
+ metadata
57
+ } else {
58
+ let _ = std:: io:: stderr ( ) . write_fmt ( format_args ! (
59
+ "error: Could not obtain cargo metadata."
60
+ ) ) ;
61
+ std:: process:: exit ( 101 ) ;
62
+ } ;
63
+
64
+ let manifest_path = manifest_path_arg. map ( |arg| {
65
+ PathBuf :: from ( Path :: new ( & arg[ "--manifest-path=" . len ( ) ..] ) )
66
+ } ) ;
67
+
68
+ let current_dir = std:: env:: current_dir ( ) ;
69
+
70
+ let package_index = metadata
71
+ . packages
72
+ . iter ( )
73
+ . position ( |package| {
74
+ let package_manifest_path = Path :: new ( & package. manifest_path ) ;
75
+ if let Some ( ref manifest_path) = manifest_path {
76
+ package_manifest_path == manifest_path
77
+ } else {
78
+ let current_dir = current_dir. as_ref ( ) . expect (
79
+ "could not read current directory" ,
80
+ ) ;
81
+ let package_manifest_directory = package_manifest_path. parent ( ) . expect (
82
+ "could not find parent directory of package manifest" ,
83
+ ) ;
84
+ package_manifest_directory == current_dir
85
+ }
86
+ } )
87
+ . expect ( "could not find matching package" ) ;
88
+ let package = metadata. packages . remove ( package_index) ;
89
+
90
+ // Finally we got the list of targets to build
91
+ package. targets . into_iter ( )
92
+ }
93
+
37
94
fn main ( ) {
38
95
// Check for version and help flags even when invoked as 'cargo-miri'
39
96
if std:: env:: args ( ) . any ( |a| a == "--help" || a == "-h" ) {
@@ -51,61 +108,27 @@ fn main() {
51
108
// binary so that we come back in the other branch, and dispatch
52
109
// the invocations to rustc and miri, respectively.
53
110
54
- let test = std:: env:: args ( ) . nth ( 2 ) . map_or ( false , |text| text == "test" ) ;
55
- let skip = if test { 3 } else { 2 } ;
56
-
57
- // We need to get the manifest, and then the metadata, to enumerate targets.
58
- let manifest_path_arg = std:: env:: args ( ) . skip ( skip) . find ( |val| {
59
- val. starts_with ( "--manifest-path=" )
60
- } ) ;
61
-
62
- let mut metadata = if let Ok ( metadata) = cargo_metadata:: metadata (
63
- manifest_path_arg. as_ref ( ) . map ( AsRef :: as_ref) ,
64
- )
65
- {
66
- metadata
67
- } else {
68
- let _ = std:: io:: stderr ( ) . write_fmt ( format_args ! (
69
- "error: Could not obtain cargo metadata."
70
- ) ) ;
71
- std:: process:: exit ( 101 ) ;
111
+ let ( subcommand, skip) = match std:: env:: args ( ) . nth ( 2 ) . deref ( ) {
112
+ Some ( "test" ) => ( MiriCommand :: Test , 3 ) ,
113
+ Some ( "run" ) => ( MiriCommand :: Run , 3 ) ,
114
+ Some ( "setup" ) => ( MiriCommand :: Setup , 3 ) ,
115
+ // Default command, if there is an option or nothing
116
+ Some ( s) if s. starts_with ( "-" ) => ( MiriCommand :: Run , 2 ) ,
117
+ None => ( MiriCommand :: Run , 2 ) ,
118
+ // Unvalid command
119
+ Some ( s) => {
120
+ eprintln ! ( "Unknown command `{}`" , s) ;
121
+ std:: process:: exit ( 1 )
122
+ }
72
123
} ;
73
124
74
- let manifest_path = manifest_path_arg. map ( |arg| {
75
- PathBuf :: from ( Path :: new ( & arg[ "--manifest-path=" . len ( ) ..] ) )
76
- } ) ;
77
-
78
- let current_dir = std:: env:: current_dir ( ) ;
79
-
80
- let package_index = metadata
81
- . packages
82
- . iter ( )
83
- . position ( |package| {
84
- let package_manifest_path = Path :: new ( & package. manifest_path ) ;
85
- if let Some ( ref manifest_path) = manifest_path {
86
- package_manifest_path == manifest_path
87
- } else {
88
- let current_dir = current_dir. as_ref ( ) . expect (
89
- "could not read current directory" ,
90
- ) ;
91
- let package_manifest_directory = package_manifest_path. parent ( ) . expect (
92
- "could not find parent directory of package manifest" ,
93
- ) ;
94
- package_manifest_directory == current_dir
95
- }
96
- } )
97
- . expect ( "could not find matching package" ) ;
98
- let package = metadata. packages . remove ( package_index) ;
99
-
100
- // Finally we got the metadata, iterate all targets and see for which ones
101
- // we do anything.
102
- for target in package. targets {
125
+ for target in list_targets ( std:: env:: args ( ) . skip ( skip) ) {
103
126
let args = std:: env:: args ( ) . skip ( skip) ;
104
127
let kind = target. kind . get ( 0 ) . expect (
105
128
"badly formatted cargo metadata: target::kind is an empty array" ,
106
129
) ;
107
- match ( test , & kind[ ..] ) {
108
- ( true , "test" ) => {
130
+ match ( subcommand , & kind[ ..] ) {
131
+ ( MiriCommand :: Test , "test" ) => {
109
132
// For test binaries we call `cargo rustc --test target -- <rustc args>`
110
133
if let Err ( code) = process (
111
134
vec ! [ "--test" . to_string( ) , target. name] . into_iter ( ) . chain (
@@ -116,7 +139,7 @@ fn main() {
116
139
std:: process:: exit ( code) ;
117
140
}
118
141
}
119
- ( true , "lib" ) => {
142
+ ( MiriCommand :: Test , "lib" ) => {
120
143
// For libraries we call `cargo rustc -- --test <rustc args>`
121
144
// Notice now that `--test` is a rustc arg rather than a cargo arg. This tells
122
145
// rustc to build a test harness which calls all #[test] functions. We don't
@@ -131,7 +154,7 @@ fn main() {
131
154
std:: process:: exit ( code) ;
132
155
}
133
156
}
134
- ( false , "bin" ) => {
157
+ ( MiriCommand :: Run , "bin" ) => {
135
158
// For ordinary binaries we call `cargo rustc --bin target -- <rustc args>`
136
159
if let Err ( code) = process (
137
160
vec ! [ "--bin" . to_string( ) , target. name] . into_iter ( ) . chain (
0 commit comments