@@ -236,22 +236,36 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
236236 is_bin || is_test
237237 }
238238
239- fn out_filename ( prefix : & str , suffix : & str ) -> PathBuf {
240- if let Some ( out_dir) = get_arg_flag_value ( "--out-dir" ) {
241- let mut path = PathBuf :: from ( out_dir) ;
242- path. push ( format ! (
243- "{}{}{}{}" ,
244- prefix,
245- get_arg_flag_value( "--crate-name" ) . unwrap( ) ,
246- // This is technically a `-C` flag but the prefix seems unique enough...
247- // (and cargo passes this before the filename so it should be unique)
248- get_arg_flag_value( "extra-filename" ) . unwrap_or_default( ) ,
249- suffix,
250- ) ) ;
251- path
239+ fn out_filenames ( ) -> Vec < PathBuf > {
240+ if let Some ( out_file) = get_arg_flag_value ( "-o" ) {
241+ // `-o` has precedence over `--out-dir`.
242+ vec ! [ PathBuf :: from( out_file) ]
252243 } else {
253- let out_file = get_arg_flag_value ( "-o" ) . unwrap ( ) ;
254- PathBuf :: from ( out_file)
244+ let out_dir = get_arg_flag_value ( "--out-dir" ) . unwrap_or_default ( ) ;
245+ let path = PathBuf :: from ( out_dir) ;
246+ // Ask rustc for the filename (since that is target-dependent).
247+ let mut rustc = miri_for_host ( ) ; // sysroot doesn't matter for this so we just use the host
248+ rustc. arg ( "--print" ) . arg ( "file-names" ) ;
249+ for flag in [ "--crate-name" , "--crate-type" , "--target" ] {
250+ for val in get_arg_flag_values ( flag) {
251+ rustc. arg ( flag) . arg ( val) ;
252+ }
253+ }
254+ // This is technically passed as `-C extra-filename=...`, but the prefix seems unique
255+ // enough... (and cargo passes this before the filename so it should be unique)
256+ if let Some ( extra) = get_arg_flag_value ( "extra-filename" ) {
257+ rustc. arg ( "-C" ) . arg ( format ! ( "extra-filename={extra}" ) ) ;
258+ }
259+ rustc. arg ( "-" ) ;
260+
261+ let output = rustc. output ( ) . expect ( "cannot run rustc to determine file name" ) ;
262+ assert ! (
263+ output. status. success( ) ,
264+ "rustc failed when determining file name:\n {output:?}"
265+ ) ;
266+ let output =
267+ String :: from_utf8 ( output. stdout ) . expect ( "rustc returned non-UTF-8 filename" ) ;
268+ output. lines ( ) . filter ( |l| !l. is_empty ( ) ) . map ( |l| path. join ( l) ) . collect ( )
255269 }
256270 }
257271
@@ -267,24 +281,28 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
267281 let info_query = get_arg_flag_value ( "--print" ) . is_some ( ) || has_arg_flag ( "-vV" ) ;
268282
269283 let store_json = |info : CrateRunInfo | {
270- // Create a stub .d file to stop Cargo from "rebuilding" the crate:
271- // https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693
272- // As we store a JSON file instead of building the crate here, an empty file is fine.
273- let dep_info_name = out_filename ( "" , ".d" ) ;
274- if verbose > 0 {
275- eprintln ! ( "[cargo-miri rustc] writing stub dep-info to `{}`" , dep_info_name. display( ) ) ;
284+ if get_arg_flag_value ( "--emit" ) . unwrap_or_default ( ) . split ( ',' ) . any ( |e| e == "dep-info" ) {
285+ // Create a stub .d file to stop Cargo from "rebuilding" the crate:
286+ // https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693
287+ // As we store a JSON file instead of building the crate here, an empty file is fine.
288+ let dep_info_name = format ! (
289+ "{}/{}{}.d" ,
290+ get_arg_flag_value( "--out-dir" ) . unwrap( ) ,
291+ get_arg_flag_value( "--crate-name" ) . unwrap( ) ,
292+ get_arg_flag_value( "extra-filename" ) . unwrap_or_default( ) ,
293+ ) ;
294+ if verbose > 0 {
295+ eprintln ! ( "[cargo-miri rustc] writing stub dep-info to `{dep_info_name}`" ) ;
296+ }
297+ File :: create ( dep_info_name) . expect ( "failed to create fake .d file" ) ;
276298 }
277- File :: create ( dep_info_name) . expect ( "failed to create fake .d file" ) ;
278299
279- let filename = out_filename ( "" , "" ) ;
280- if verbose > 0 {
281- eprintln ! ( "[cargo-miri rustc] writing run info to `{}`" , filename. display( ) ) ;
300+ for filename in out_filenames ( ) {
301+ if verbose > 0 {
302+ eprintln ! ( "[cargo-miri rustc] writing run info to `{}`" , filename. display( ) ) ;
303+ }
304+ info. store ( & filename) ;
282305 }
283- info. store ( & filename) ;
284- // For Windows and WASM, do the same thing again with `.exe`/`.wasm` appended to the filename.
285- // (Need to do this here as cargo moves that "binary" to a different place before running it.)
286- info. store ( & out_filename ( "" , ".exe" ) ) ;
287- info. store ( & out_filename ( "" , ".wasm" ) ) ;
288306 } ;
289307
290308 let runnable_crate = !info_query && is_runnable_crate ( ) ;
@@ -323,11 +341,14 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
323341
324342 // Alter the `-o` parameter so that it does not overwrite the JSON file we stored above.
325343 let mut args = env. args ;
344+ let mut out_filename = None ;
326345 for i in 0 ..args. len ( ) {
327346 if args[ i] == "-o" {
347+ out_filename = Some ( args[ i + 1 ] . clone ( ) ) ;
328348 args[ i + 1 ] . push_str ( ".miri" ) ;
329349 }
330350 }
351+ let out_filename = out_filename. expect ( "rustdoc must pass `-o`" ) ;
331352
332353 cmd. args ( & args) ;
333354 cmd. env ( "MIRI_BE_RUSTC" , "target" ) ;
@@ -340,7 +361,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
340361 eprintln ! ( "[cargo-miri rustc inside rustdoc] going to run:\n {cmd:?}" ) ;
341362 }
342363
343- exec_with_pipe ( cmd, & env. stdin , format ! ( "{}.stdin" , out_filename ( "" , "" ) . display ( ) ) ) ;
364+ exec_with_pipe ( cmd, & env. stdin , format ! ( "{out_filename }.stdin" ) ) ;
344365 }
345366
346367 return ;
@@ -422,15 +443,12 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
422443 // Create a stub .rlib file if "link" was requested by cargo.
423444 // This is necessary to prevent cargo from doing rebuilds all the time.
424445 if emit_link_hack {
425- // Some platforms prepend "lib", some do not... let's just create both files.
426- File :: create ( out_filename ( "lib" , ".rlib" ) ) . expect ( "failed to create fake .rlib file" ) ;
427- File :: create ( out_filename ( "" , ".rlib" ) ) . expect ( "failed to create fake .rlib file" ) ;
428- // Just in case this is a cdylib or staticlib, also create those fake files.
429- File :: create ( out_filename ( "lib" , ".so" ) ) . expect ( "failed to create fake .so file" ) ;
430- File :: create ( out_filename ( "lib" , ".a" ) ) . expect ( "failed to create fake .a file" ) ;
431- File :: create ( out_filename ( "lib" , ".dylib" ) ) . expect ( "failed to create fake .dylib file" ) ;
432- File :: create ( out_filename ( "" , ".dll" ) ) . expect ( "failed to create fake .dll file" ) ;
433- File :: create ( out_filename ( "" , ".lib" ) ) . expect ( "failed to create fake .lib file" ) ;
446+ for filename in out_filenames ( ) {
447+ if verbose > 0 {
448+ eprintln ! ( "[cargo-miri rustc] creating fake lib file at `{}`" , filename. display( ) ) ;
449+ }
450+ File :: create ( filename) . expect ( "failed to create fake lib file" ) ;
451+ }
434452 }
435453
436454 debug_cmd ( "[cargo-miri rustc]" , verbose, & cmd) ;
0 commit comments