Skip to content

Commit 717d313

Browse files
committed
cargo-miri: use rustc to determine the output filename
1 parent 4f051a6 commit 717d313

File tree

1 file changed

+66
-40
lines changed

1 file changed

+66
-40
lines changed

cargo-miri/src/phases.rs

+66-40
Original file line numberDiff line numberDiff line change
@@ -236,22 +236,44 @@ 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
269+
.lines()
270+
.filter(|l| !l.is_empty())
271+
.map(|l| {
272+
let mut p = path.clone();
273+
p.push(l);
274+
p
275+
})
276+
.collect()
255277
}
256278
}
257279

@@ -267,24 +289,28 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
267289
let info_query = get_arg_flag_value("--print").is_some() || has_arg_flag("-vV");
268290

269291
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());
292+
if get_arg_flag_value("--emit").unwrap_or_default().split(',').any(|e| e == "dep-info") {
293+
// Create a stub .d file to stop Cargo from "rebuilding" the crate:
294+
// https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693
295+
// As we store a JSON file instead of building the crate here, an empty file is fine.
296+
let dep_info_name = format!(
297+
"{}/{}{}.d",
298+
get_arg_flag_value("--out-dir").unwrap(),
299+
get_arg_flag_value("--crate-name").unwrap(),
300+
get_arg_flag_value("extra-filename").unwrap_or_default(),
301+
);
302+
if verbose > 0 {
303+
eprintln!("[cargo-miri rustc] writing stub dep-info to `{dep_info_name}`");
304+
}
305+
File::create(dep_info_name).expect("failed to create fake .d file");
276306
}
277-
File::create(dep_info_name).expect("failed to create fake .d file");
278307

279-
let filename = out_filename("", "");
280-
if verbose > 0 {
281-
eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display());
308+
for filename in out_filenames() {
309+
if verbose > 0 {
310+
eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display());
311+
}
312+
info.store(&filename);
282313
}
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"));
288314
};
289315

290316
let runnable_crate = !info_query && is_runnable_crate();
@@ -323,11 +349,14 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
323349

324350
// Alter the `-o` parameter so that it does not overwrite the JSON file we stored above.
325351
let mut args = env.args;
352+
let mut out_filename = None;
326353
for i in 0..args.len() {
327354
if args[i] == "-o" {
355+
out_filename = Some(args[i + 1].clone());
328356
args[i + 1].push_str(".miri");
329357
}
330358
}
359+
let out_filename = out_filename.expect("rustdoc must pass `-o`");
331360

332361
cmd.args(&args);
333362
cmd.env("MIRI_BE_RUSTC", "target");
@@ -340,7 +369,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
340369
eprintln!("[cargo-miri rustc inside rustdoc] going to run:\n{cmd:?}");
341370
}
342371

343-
exec_with_pipe(cmd, &env.stdin, format!("{}.stdin", out_filename("", "").display()));
372+
exec_with_pipe(cmd, &env.stdin, format!("{out_filename}.stdin"));
344373
}
345374

346375
return;
@@ -422,15 +451,12 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
422451
// Create a stub .rlib file if "link" was requested by cargo.
423452
// This is necessary to prevent cargo from doing rebuilds all the time.
424453
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");
454+
for filename in out_filenames() {
455+
if verbose > 0 {
456+
eprintln!("[cargo-miri rustc] creating fake lib file at `{}`", filename.display());
457+
}
458+
File::create(filename).expect("failed to create fake lib file");
459+
}
434460
}
435461

436462
debug_cmd("[cargo-miri rustc]", verbose, &cmd);

0 commit comments

Comments
 (0)