1
1
use std:: ffi:: { OsStr , OsString } ;
2
+ use std:: io:: BufRead ;
2
3
use std:: ops:: Range ;
3
4
use std:: path:: { Path , PathBuf } ;
4
5
use std:: sync:: atomic:: { AtomicBool , AtomicU32 , Ordering } ;
5
- use std:: thread;
6
+ use std:: { env , iter , thread} ;
6
7
7
- use anyhow:: { anyhow, Context , Result } ;
8
+ use anyhow:: { anyhow, bail , Context , Result } ;
8
9
use dunce:: canonicalize;
9
10
use path_macro:: path;
10
11
use xshell:: { cmd, Cmd , Shell } ;
@@ -73,8 +74,11 @@ impl MiriEnv {
73
74
let rustflags = {
74
75
let mut flags = OsString :: new ( ) ;
75
76
// We set the rpath so that Miri finds the private rustc libraries it needs.
76
- flags. push ( "-C link-args=-Wl,-rpath," ) ;
77
- flags. push ( libdir) ;
77
+ // (This only makes sense on Unix.)
78
+ if cfg ! ( unix) {
79
+ flags. push ( "-C link-args=-Wl,-rpath," ) ;
80
+ flags. push ( & libdir) ;
81
+ }
78
82
// Enable rustc-specific lints (ignored without `-Zunstable-options`).
79
83
flags. push (
80
84
" -Zunstable-options -Wrustc::internal -Wrust_2018_idioms -Wunused_lifetimes" ,
@@ -88,6 +92,14 @@ impl MiriEnv {
88
92
} ;
89
93
sh. set_var ( "RUSTFLAGS" , rustflags) ;
90
94
95
+ // On Windows, the `-Wl,-rpath,` above does not help. Instead we add the libdir to the PATH,
96
+ // so that Windows can find the DLLs.
97
+ if cfg ! ( windows) {
98
+ let old_path = sh. var ( "PATH" ) ?;
99
+ let new_path = env:: join_paths ( iter:: once ( libdir) . chain ( env:: split_paths ( & old_path) ) ) ?;
100
+ sh. set_var ( "PATH" , new_path) ;
101
+ }
102
+
91
103
// Get extra flags for cargo.
92
104
let cargo_extra_flags = std:: env:: var ( "CARGO_EXTRA_FLAGS" ) . unwrap_or_default ( ) ;
93
105
let cargo_extra_flags = flagsplit ( & cargo_extra_flags) ;
@@ -126,21 +138,40 @@ impl MiriEnv {
126
138
127
139
pub fn build ( & self , crate_dir : impl AsRef < OsStr > , args : & [ String ] , quiet : bool ) -> Result < ( ) > {
128
140
let quiet_flag = if quiet { Some ( "--quiet" ) } else { None } ;
129
- // We build the tests as well, (a) to avoid having rebuilds when building the tests later
130
- // and (b) to have more parallelism during the build of Miri and its tests.
131
- // This means `./miri run` without `--dep` will build Miri twice (for the sysroot with
132
- // dev-dependencies, and then for running without dev-dependencies), but the way more common
133
- // `./miri test` will avoid building Miri twice.
134
- let mut cmd = self
135
- . cargo_cmd ( crate_dir, "build" )
136
- . args ( & [ "--bins" , "--tests" ] )
137
- . args ( quiet_flag)
138
- . args ( args) ;
141
+ // We build all targets, since building *just* the bin target doesnot include
142
+ // `dev-dependencies` and that changes feature resolution. This also gets us more
143
+ // parallelism in `./miri test` as we build Miri and its tests together.
144
+ let mut cmd =
145
+ self . cargo_cmd ( crate_dir, "build" ) . args ( & [ "--all-targets" ] ) . args ( quiet_flag) . args ( args) ;
139
146
cmd. set_quiet ( quiet) ;
140
147
cmd. run ( ) ?;
141
148
Ok ( ( ) )
142
149
}
143
150
151
+ /// Returns the path to the main crate binary. Assumes that `build` has been called before.
152
+ pub fn build_get_binary ( & self , crate_dir : impl AsRef < OsStr > ) -> Result < PathBuf > {
153
+ let cmd =
154
+ self . cargo_cmd ( crate_dir, "build" ) . args ( & [ "--all-targets" , "--message-format=json" ] ) ;
155
+ let output = cmd. output ( ) ?;
156
+ let mut bin = None ;
157
+ for line in output. stdout . lines ( ) {
158
+ let line = line?;
159
+ if line. starts_with ( "{" ) {
160
+ let json: serde_json:: Value = serde_json:: from_str ( & line) ?;
161
+ if json[ "reason" ] == "compiler-artifact"
162
+ && !json[ "profile" ] [ "test" ] . as_bool ( ) . unwrap ( )
163
+ && !json[ "executable" ] . is_null ( )
164
+ {
165
+ if bin. is_some ( ) {
166
+ bail ! ( "found two binaries in cargo output" ) ;
167
+ }
168
+ bin = Some ( PathBuf :: from ( json[ "executable" ] . as_str ( ) . unwrap ( ) ) )
169
+ }
170
+ }
171
+ }
172
+ bin. ok_or_else ( || anyhow ! ( "found no binary in cargo output" ) )
173
+ }
174
+
144
175
pub fn check ( & self , crate_dir : impl AsRef < OsStr > , args : & [ String ] ) -> Result < ( ) > {
145
176
self . cargo_cmd ( crate_dir, "check" ) . arg ( "--all-targets" ) . args ( args) . run ( ) ?;
146
177
Ok ( ( ) )
0 commit comments