Skip to content

Commit 868dcbb

Browse files
committed
even when not linking, create stub .rlib files to fool cargo
1 parent f0987a3 commit 868dcbb

File tree

1 file changed

+62
-39
lines changed

1 file changed

+62
-39
lines changed

cargo-miri/bin.rs

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,13 @@ fn xargo_check() -> Command {
138138
Command::new(env::var_os("XARGO_CHECK").unwrap_or_else(|| OsString::from("xargo-check")))
139139
}
140140

141-
fn exec(mut cmd: Command) -> ! {
141+
/// Execute the command if it fails, fail this process with the same exit code.
142+
/// Otherwise, continue.
143+
fn exec(mut cmd: Command) {
142144
let exit_status = cmd.status().expect("failed to run command");
143-
std::process::exit(exit_status.code().unwrap_or(-1))
145+
if exit_status.success().not() {
146+
std::process::exit(exit_status.code().unwrap_or(-1))
147+
}
144148
}
145149

146150
fn xargo_version() -> Option<(u32, u32, u32)> {
@@ -453,6 +457,20 @@ fn phase_cargo_rustc(args: env::ArgsOs) {
453457
(is_bin || is_test) && !print
454458
}
455459

460+
fn out_filename(prefix: &str, suffix: &str) -> PathBuf {
461+
let mut path = PathBuf::from(get_arg_flag_value("--out-dir").unwrap());
462+
path.push(format!(
463+
"{}{}{}{}",
464+
prefix,
465+
get_arg_flag_value("--crate-name").unwrap(),
466+
// This is technically a `-C` flag but the prefix seems unique enough...
467+
// (and cargo passes this before the filename so it should be unique)
468+
get_arg_flag_value("extra-filename").unwrap_or(String::new()),
469+
suffix,
470+
));
471+
path
472+
}
473+
456474
let verbose = std::env::var_os("MIRI_VERBOSE").is_some();
457475
let target_crate = is_target_crate();
458476

@@ -463,60 +481,58 @@ fn phase_cargo_rustc(args: env::ArgsOs) {
463481
// Instead of compiling, we write JSON into the output file with all the relevant command-line flags
464482
// and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase.
465483
let info = CrateRunInfo::collect(args);
484+
// FIXME: Windows might need a ".exe" suffix.
485+
let filename = out_filename("", "");
466486

467-
let mut path = PathBuf::from(get_arg_flag_value("--out-dir").unwrap());
468-
path.push(format!(
469-
"{}{}",
470-
get_arg_flag_value("--crate-name").unwrap(),
471-
// This is technically a `-C` flag but the prefix seems unique enough...
472-
// (and cargo passes this before the filename so it should be unique)
473-
get_arg_flag_value("extra-filename").unwrap_or(String::new()),
474-
));
475487
if verbose {
476-
eprintln!("[cargo-miri rustc] writing run info to {:?}", path.display());
488+
eprintln!("[cargo-miri rustc] writing run info to {:?}", filename.display());
477489
}
478490

479-
let file = File::create(&path)
480-
.unwrap_or_else(|_| show_error(format!("Cannot create {:?}", path.display())));
491+
let file = File::create(&filename)
492+
.unwrap_or_else(|_| show_error(format!("Cannot create {:?}", filename.display())));
481493
let file = BufWriter::new(file);
482494
serde_json::ser::to_writer(file, &info)
483-
.unwrap_or_else(|_| show_error(format!("Cannot write to {:?}", path.display())));
495+
.unwrap_or_else(|_| show_error(format!("Cannot write to {:?}", filename.display())));
484496
return;
485497
}
486498

487499
let mut cmd = miri();
488-
// Forward arguments, but (only for target crates!) remove "link" from "--emit" to make this a check-only build.
489-
let emit_flag = "--emit";
490-
for arg in args {
491-
if target_crate && arg.to_string_lossy().starts_with(emit_flag) {
492-
// Patch this argument. First, extract its value.
493-
let arg = arg.to_str().expect("`--emit` must be UTF-8");
494-
let val = &arg[emit_flag.len()..];
495-
assert!(val.starts_with("="), "`cargo` should pass `--emit=X` as one argument");
496-
let val = &val[1..];
497-
let mut val: Vec<_> = val.split(',').collect();
498-
// Now make sure "link" is not in there, but "metadata" is.
499-
if let Some(i) = val.iter().position(|&s| s == "link") {
500-
val.remove(i);
501-
if !val.iter().any(|&s| s == "metadata") {
502-
val.push("metadata");
500+
let mut emit_link_hack = false;
501+
// Arguments are treated very differently depending on whether this crate is
502+
// for interpretation by Miri, or for use by a build script / proc macro.
503+
if target_crate {
504+
// Forward arguments, butremove "link" from "--emit" to make this a check-only build.
505+
let emit_flag = "--emit";
506+
for arg in args {
507+
if arg.to_string_lossy().starts_with(emit_flag) {
508+
// Patch this argument. First, extract its value.
509+
let arg = arg.to_str().expect("`--emit` must be UTF-8");
510+
let val = &arg[emit_flag.len()..];
511+
assert!(val.starts_with("="), "`cargo` should pass `--emit=X` as one argument");
512+
let val = &val[1..];
513+
let mut val: Vec<_> = val.split(',').collect();
514+
// Now make sure "link" is not in there, but "metadata" is.
515+
if let Some(i) = val.iter().position(|&s| s == "link") {
516+
emit_link_hack = true;
517+
val.remove(i);
518+
if !val.iter().any(|&s| s == "metadata") {
519+
val.push("metadata");
520+
}
503521
}
522+
cmd.arg(format!("{}={}", emit_flag, val.join(",")));
523+
} else {
524+
cmd.arg(arg);
504525
}
505-
cmd.arg(format!("{}={}", emit_flag, val.join(",")));
506-
// FIXME: due to this, the `.rlib` file does not get created and cargo re-triggers the build each time.
507-
} else {
508-
cmd.arg(arg);
509526
}
510-
}
511527

512-
// We make sure to only specify our custom Xargo sysroot for target crates - that is,
513-
// crates which are needed for interpretation by Miri. proc-macros and build scripts
514-
// should use the default sysroot.
515-
if target_crate {
528+
// Use our custom sysroot.
516529
let sysroot =
517530
env::var_os("MIRI_SYSROOT").expect("The wrapper should have set MIRI_SYSROOT");
518531
cmd.arg("--sysroot");
519532
cmd.arg(sysroot);
533+
} else {
534+
// For host crates, just forward everything.
535+
cmd.args(args);
520536
}
521537

522538
// We want to compile, not interpret. We still use Miri to make sure the compiler version etc
@@ -527,7 +543,14 @@ fn phase_cargo_rustc(args: env::ArgsOs) {
527543
if verbose {
528544
eprintln!("[cargo-miri rustc] {:?}", cmd);
529545
}
530-
exec(cmd)
546+
exec(cmd);
547+
548+
// Create a stub .rlib file if "link" was requested by cargo.
549+
if emit_link_hack {
550+
// FIXME: is "lib" always right?
551+
let filename = out_filename("lib", ".rlib");
552+
File::create(filename).expect("Failed to create rlib file");
553+
}
531554
}
532555

533556
fn phase_cargo_runner(binary: &OsStr, binary_args: env::ArgsOs) {

0 commit comments

Comments
 (0)