diff --git a/cargo-miri/bin.rs b/cargo-miri/bin.rs index f38e79732b..cb003c0f3e 100644 --- a/cargo-miri/bin.rs +++ b/cargo-miri/bin.rs @@ -143,6 +143,18 @@ fn get_arg_flag_value(name: &str) -> Option { ArgFlagValueIter::new(name).next() } +fn forward_patched_extern_arg(args: &mut impl Iterator, cmd: &mut Command) { + cmd.arg("--extern"); // always forward flag, but adjust filename: + let path = args.next().expect("`--extern` should be followed by a filename"); + if let Some(lib) = path.strip_suffix(".rlib") { + // If this is an rlib, make it an rmeta. + cmd.arg(format!("{}.rmeta", lib)); + } else { + // Some other extern file (e.g. a `.so`). Forward unchanged. + cmd.arg(path); + } +} + /// Returns the path to the `miri` binary fn find_miri() -> PathBuf { if let Some(path) = env::var_os("MIRI") { @@ -553,7 +565,7 @@ fn phase_cargo_miri(mut args: env::Args) { exec(cmd) } -fn phase_cargo_rustc(args: env::Args) { +fn phase_cargo_rustc(mut args: env::Args) { /// Determines if we are being invoked (as rustc) to build a crate for /// the "target" architecture, in contrast to the "host" architecture. /// Host crates are for build scripts and proc macros and still need to @@ -596,15 +608,6 @@ fn phase_cargo_rustc(args: env::Args) { let target_crate = is_target_crate(); let print = get_arg_flag_value("--print").is_some(); // whether this is cargo passing `--print` to get some infos - // cdylib is just skipped, we cannot interpret it and do not need it - // for the rest of the build either. - if get_arg_flag_value("--crate-type").as_deref() == Some("cdylib") { - if verbose { - eprint!("[cargo-miri rustc] (cdylib skipped)"); - } - return; - } - let store_json = |info: CrateRunInfo| { let filename = out_filename("", ""); if verbose { @@ -643,7 +646,7 @@ fn phase_cargo_rustc(args: env::Args) { if !print && target_crate { // Forward arguments, but remove "link" from "--emit" to make this a check-only build. let emit_flag = "--emit"; - for arg in args { + while let Some(arg) = args.next() { if arg.starts_with(emit_flag) { // Patch this argument. First, extract its value. let val = &arg[emit_flag.len()..]; @@ -659,6 +662,10 @@ fn phase_cargo_rustc(args: env::Args) { } } cmd.arg(format!("{}={}", emit_flag, val.join(","))); + } else if arg == "--extern" { + // Patch `--extern` filenames, since Cargo sometimes passes stub `.rlib` files: + // https://github.com/rust-lang/miri/issues/1705 + forward_patched_extern_arg(&mut args, &mut cmd); } else { cmd.arg(arg); } @@ -734,21 +741,11 @@ fn phase_cargo_runner(binary: &Path, binary_args: env::Args) { // but when we run here, cargo does not interpret the JSON any more. `--json` // then also nees to be dropped. let mut args = info.args.into_iter(); - let extern_flag = "--extern"; let error_format_flag = "--error-format"; let json_flag = "--json"; while let Some(arg) = args.next() { - if arg == extern_flag { - cmd.arg(extern_flag); // always forward flag, but adjust filename - // `--extern` is always passed as a separate argument by cargo. - let next_arg = args.next().expect("`--extern` should be followed by a filename"); - if let Some(next_lib) = next_arg.strip_suffix(".rlib") { - // If this is an rlib, make it an rmeta. - cmd.arg(format!("{}.rmeta", next_lib)); - } else { - // Some other extern file (e.g., a `.so`). Forward unchanged. - cmd.arg(next_arg); - } + if arg == "--extern" { + forward_patched_extern_arg(&mut args, &mut cmd); } else if arg.starts_with(error_format_flag) { let suffix = &arg[error_format_flag.len()..]; assert!(suffix.starts_with('=')); diff --git a/test-cargo-miri/Cargo.lock b/test-cargo-miri/Cargo.lock index a3a708c6b5..1f1541b92a 100644 --- a/test-cargo-miri/Cargo.lock +++ b/test-cargo-miri/Cargo.lock @@ -11,12 +11,21 @@ name = "cargo-miri-test" version = "0.1.0" dependencies = [ "byteorder", + "cdylib", "issue_1567", "issue_1691", + "issue_1705", "rand", "serde_derive", ] +[[package]] +name = "cdylib" +version = "0.1.0" +dependencies = [ + "byteorder", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -54,6 +63,13 @@ dependencies = [ name = "issue_1691" version = "0.1.0" +[[package]] +name = "issue_1705" +version = "0.1.0" +dependencies = [ + "byteorder", +] + [[package]] name = "libc" version = "0.2.81" diff --git a/test-cargo-miri/Cargo.toml b/test-cargo-miri/Cargo.toml index c42d6753e8..7ffe7d04ea 100644 --- a/test-cargo-miri/Cargo.toml +++ b/test-cargo-miri/Cargo.toml @@ -9,8 +9,10 @@ edition = "2018" [dependencies] byteorder = "1.0" +cdylib = { path = "cdylib" } issue_1567 = { path = "issue-1567" } issue_1691 = { path = "issue-1691" } +issue_1705 = { path = "issue-1705" } [dev-dependencies] rand = { version = "0.7", features = ["small_rng"] } diff --git a/test-cargo-miri/cdylib/Cargo.toml b/test-cargo-miri/cdylib/Cargo.toml new file mode 100644 index 0000000000..4e5b5601a5 --- /dev/null +++ b/test-cargo-miri/cdylib/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "cdylib" +version = "0.1.0" +authors = ["Miri Team"] +edition = "2018" + +[lib] +# cargo-miri used to handle `cdylib` crate-type specially (https://github.com/rust-lang/miri/pull/1577). +crate-type = ["cdylib"] + +[dependencies] +byteorder = "1.0" diff --git a/test-cargo-miri/cdylib/src/lib.rs b/test-cargo-miri/cdylib/src/lib.rs new file mode 100644 index 0000000000..dd89048284 --- /dev/null +++ b/test-cargo-miri/cdylib/src/lib.rs @@ -0,0 +1,6 @@ +use byteorder::{BigEndian, ByteOrder}; + +#[no_mangle] +extern "C" fn use_the_dependency() { + let _n = ::read_u64(&[1,2,3,4,5,6,7,8]); +} diff --git a/test-cargo-miri/issue-1705/Cargo.toml b/test-cargo-miri/issue-1705/Cargo.toml new file mode 100644 index 0000000000..ae63647a88 --- /dev/null +++ b/test-cargo-miri/issue-1705/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "issue_1705" +version = "0.1.0" +authors = ["Miri Team"] +edition = "2018" + +[lib] +crate-type = ["lib", "staticlib", "cdylib"] + +[dependencies] +byteorder = "1.0" diff --git a/test-cargo-miri/issue-1705/src/lib.rs b/test-cargo-miri/issue-1705/src/lib.rs new file mode 100644 index 0000000000..ef24d3f1a0 --- /dev/null +++ b/test-cargo-miri/issue-1705/src/lib.rs @@ -0,0 +1,5 @@ +use byteorder::{LittleEndian, ByteOrder}; + +pub fn use_the_dependency() { + let _n = ::read_u32(&[1,2,3,4]); +} diff --git a/test-cargo-miri/src/lib.rs b/test-cargo-miri/src/lib.rs index b50dfbe51e..33bbd8c966 100644 --- a/test-cargo-miri/src/lib.rs +++ b/test-cargo-miri/src/lib.rs @@ -3,5 +3,7 @@ /// assert!(cargo_miri_test::make_true()); /// ``` pub fn make_true() -> bool { + issue_1567::use_the_dependency(); + issue_1705::use_the_dependency(); issue_1691::use_me() }