diff --git a/src/cargo/core/compiler/build_runner/mod.rs b/src/cargo/core/compiler/build_runner/mod.rs index 16476693784..ec8d6bd1ebc 100644 --- a/src/cargo/core/compiler/build_runner/mod.rs +++ b/src/cargo/core/compiler/build_runner/mod.rs @@ -262,7 +262,7 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> { } for (lt, arg) in &output.linker_args { - if lt.applies_to(&unit.target) { + if lt.applies_to(&unit.target, unit.mode) { args.push("-C".into()); args.push(format!("link-arg={}", arg).into()); } diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 8928c93be10..5483eabc84f 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -37,6 +37,7 @@ use crate::core::compiler::build_runner::UnitHash; use crate::core::compiler::fingerprint::DirtyReason; use crate::core::compiler::job_queue::JobState; use crate::core::{profiles::ProfileRoot, PackageId, Target}; +use crate::util::command_prelude::CompileMode; use crate::util::errors::CargoResult; use crate::util::internal; use crate::util::machine_message::{self, Message}; @@ -196,10 +197,11 @@ pub enum LinkArgTarget { impl LinkArgTarget { /// Checks if this link type applies to a given [`Target`]. - pub fn applies_to(&self, target: &Target) -> bool { + pub fn applies_to(&self, target: &Target, mode: CompileMode) -> bool { + let is_test = mode.is_any_test(); match self { LinkArgTarget::All => true, - LinkArgTarget::Cdylib => target.is_cdylib(), + LinkArgTarget::Cdylib => !is_test && target.is_cdylib(), LinkArgTarget::Bin => target.is_bin(), LinkArgTarget::SingleBin(name) => target.is_bin() && target.name() == name, LinkArgTarget::Test => target.is_test(), diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index a0a42e84532..3ec3b74ba93 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -360,6 +360,7 @@ fn rustc( pass_l_flag, &target, current_id, + mode, )?; add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?; } @@ -494,6 +495,7 @@ fn rustc( pass_l_flag: bool, target: &Target, current_id: PackageId, + mode: CompileMode, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { let output = build_script_outputs.get(key.1).ok_or_else(|| { @@ -520,7 +522,9 @@ fn rustc( // clause should have been kept in the `if` block above. For // now, continue allowing it for cdylib only. // See https://github.com/rust-lang/cargo/issues/9562 - if lt.applies_to(target) && (key.0 == current_id || *lt == LinkArgTarget::Cdylib) { + if lt.applies_to(target, mode) + && (key.0 == current_id || *lt == LinkArgTarget::Cdylib) + { rustc.arg("-C").arg(format!("link-arg={}", arg)); } } diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs index ee58e309fe9..fc1e03f987e 100644 --- a/tests/testsuite/build_script_extra_link_arg.rs +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -443,3 +443,40 @@ fn cdylib_both_forms() { "#]]) .run(); } + +// https://github.com/rust-lang/cargo/issues/12663 +#[cargo_test] +fn cdylib_extra_link_args_should_not_apply_to_unit_tests() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [lib] + crate-type = ["lib", "cdylib"] + "#, + ) + .file( + "src/lib.rs", + r#" + #[test] + fn noop() {} + "#, + ) + .file( + "build.rs", + r#" + fn main() { + // This would fail if cargo passed `-lhack` to building the test because `hack` doesn't exist. + println!("cargo::rustc-link-arg-cdylib=-lhack"); + } + "#, + ) + .build(); + + p.cargo("test --lib").run(); +}