diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index ae627c926f6..6062cab9d23 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -579,6 +579,22 @@ impl BuildOutput { script_out_dir.to_str().unwrap(), ); + macro_rules! check_and_add_target { + ($target_kind: expr, $is_target_kind: expr, $link_type: expr) => { + if !targets.iter().any(|target| $is_target_kind(target)) { + bail!( + "invalid instruction `cargo:{}` from {}\n\ + The package {} does not have a {} target.", + key, + whence, + pkg_descr, + $target_kind + ); + } + linker_args.push(($link_type, value)); + }; + } + // Keep in sync with TargetConfig::parse_links_overrides. match key { "rustc-flags" => { @@ -604,16 +620,7 @@ impl BuildOutput { linker_args.push((LinkType::Cdylib, value)) } "rustc-link-arg-bins" => { - if !targets.iter().any(|target| target.is_bin()) { - bail!( - "invalid instruction `cargo:{}` from {}\n\ - The package {} does not have a bin target.", - key, - whence, - pkg_descr - ); - } - linker_args.push((LinkType::Bin, value)); + check_and_add_target!("bin", Target::is_bin, LinkType::Bin); } "rustc-link-arg-bin" => { let mut parts = value.splitn(2, '='); @@ -643,6 +650,15 @@ impl BuildOutput { } linker_args.push((LinkType::SingleBin(bin_name), arg.to_string())); } + "rustc-link-arg-tests" => { + check_and_add_target!("test", Target::is_test, LinkType::Test); + } + "rustc-link-arg-benches" => { + check_and_add_target!("benchmark", Target::is_bench, LinkType::Bench); + } + "rustc-link-arg-examples" => { + check_and_add_target!("example", Target::is_example, LinkType::Example); + } "rustc-link-arg" => { linker_args.push((LinkType::All, value)); } diff --git a/src/cargo/util/config/target.rs b/src/cargo/util/config/target.rs index d259b970633..6b7b6911473 100644 --- a/src/cargo/util/config/target.rs +++ b/src/cargo/util/config/target.rs @@ -172,18 +172,27 @@ fn parse_links_overrides( .extend(list.iter().map(|v| PathBuf::from(&v.0))); } "rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => { - let args = value.list(key)?; - let args = args.iter().map(|v| (LinkType::Cdylib, v.0.clone())); + let args = extra_link_args(LinkType::Cdylib, key, value)?; output.linker_args.extend(args); } "rustc-link-arg-bins" => { - let args = value.list(key)?; - let args = args.iter().map(|v| (LinkType::Bin, v.0.clone())); + let args = extra_link_args(LinkType::Bin, key, value)?; output.linker_args.extend(args); } "rustc-link-arg" => { - let args = value.list(key)?; - let args = args.iter().map(|v| (LinkType::All, v.0.clone())); + let args = extra_link_args(LinkType::All, key, value)?; + output.linker_args.extend(args); + } + "rustc-link-arg-tests" => { + let args = extra_link_args(LinkType::Test, key, value)?; + output.linker_args.extend(args); + } + "rustc-link-arg-benches" => { + let args = extra_link_args(LinkType::Bench, key, value)?; + output.linker_args.extend(args); + } + "rustc-link-arg-examples" => { + let args = extra_link_args(LinkType::Example, key, value)?; output.linker_args.extend(args); } "rustc-cfg" => { @@ -209,3 +218,12 @@ fn parse_links_overrides( } Ok(links_overrides) } + +fn extra_link_args<'a>( + link_type: LinkType, + key: &str, + value: &'a CV, +) -> CargoResult + 'a> { + let args = value.list(key)?; + Ok(args.iter().map(move |v| (link_type.clone(), v.0.clone()))) +} diff --git a/src/doc/src/reference/build-scripts.md b/src/doc/src/reference/build-scripts.md index 2c17cb2eec9..bba7bcf2d67 100644 --- a/src/doc/src/reference/build-scripts.md +++ b/src/doc/src/reference/build-scripts.md @@ -100,6 +100,12 @@ one detailed below. flags to a linker for the binary `BIN`. * [`cargo:rustc-link-arg-bins=FLAG`](#rustc-link-arg-bins) – Passes custom flags to a linker for binaries. +* [`cargo:rustc-link-arg-tests=FLAG`](#rustc-link-arg-tests) – Passes custom + flags to a linker for tests. +* [`cargo:rustc-link-arg-examples=FLAG`](#rustc-link-arg-examples) – Passes custom + flags to a linker for examples. +* [`cargo:rustc-link-arg-benches=FLAG`](#rustc-link-arg-benches) – Passes custom + flags to a linker for benchmarks. * [`cargo:rustc-link-lib=[KIND=]NAME`](#rustc-link-lib) — Adds a library to link. * [`cargo:rustc-link-search=[KIND=]PATH`](#rustc-link-search) — Adds to the @@ -136,7 +142,6 @@ link-arg=FLAG` option][link-arg] to the compiler, but only when building the binary target with name `BIN`. Its usage is highly platform specific. It is useful to set a linker script or other linker options. -[link-arg]: ../../rustc/codegen-options/index.md#link-arg #### `cargo:rustc-link-arg-bins=FLAG` @@ -146,7 +151,6 @@ link-arg=FLAG` option][link-arg] to the compiler, but only when building a binary target. Its usage is highly platform specific. It is useful to set a linker script or other linker options. -[link-arg]: ../../rustc/codegen-options/index.md#link-arg #### `cargo:rustc-link-lib=[KIND=]NAME` @@ -169,6 +173,29 @@ The optional `KIND` may be one of `dylib`, `static`, or `framework`. See the [option-link]: ../../rustc/command-line-arguments.md#option-l-link-lib [FFI]: ../../nomicon/ffi.md + + +#### `cargo:rustc-link-arg-tests=FLAG` + +The `rustc-link-arg-tests` instruction tells Cargo to pass the [`-C +link-arg=FLAG` option][link-arg] to the compiler, but only when building a +tests target. + + + +#### `cargo:rustc-link-arg-examples=FLAG` + +The `rustc-link-arg-examples` instruction tells Cargo to pass the [`-C +link-arg=FLAG` option][link-arg] to the compiler, but only when building an examples +target. + + +#### `cargo:rustc-link-arg-benches=FLAG` + +The `rustc-link-arg-benches` instruction tells Cargo to pass the [`-C +link-arg=FLAG` option][link-arg] to the compiler, but only when building an benchmark +target. + #### `cargo:rustc-link-search=[KIND=]PATH` @@ -247,7 +274,6 @@ link-arg=FLAG` option][link-arg] to the compiler, but only when building a `cdylib` library target. Its usage is highly platform specific. It is useful to set the shared library version or the runtime-path. -[link-arg]: ../../rustc/codegen-options/index.md#link-arg #### `cargo:warning=MESSAGE` diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs index 116b094d770..123f0c34b68 100644 --- a/tests/testsuite/build_script_extra_link_arg.rs +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -5,7 +5,7 @@ // and other linkers will return an error. use cargo_test_support::registry::Package; -use cargo_test_support::{basic_bin_manifest, basic_manifest, project}; +use cargo_test_support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, project}; #[cargo_test] fn build_script_extra_link_arg_bin() { @@ -310,3 +310,75 @@ fn link_arg_with_doctest() { ) .run(); } + +#[cargo_test] +fn build_script_extra_link_arg_tests() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file("tests/test_foo.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:rustc-link-arg-tests=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("test -v") + .without_status() + .with_stderr_contains( + "[RUNNING] `rustc --crate-name test_foo [..]-C link-arg=--this-is-a-bogus-flag[..]", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_arg_benches() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file("benches/bench_foo.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:rustc-link-arg-benches=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("bench -v") + .without_status() + .with_stderr_contains( + "[RUNNING] `rustc --crate-name bench_foo [..]-C link-arg=--this-is-a-bogus-flag[..]", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_arg_examples() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file("examples/example_foo.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:rustc-link-arg-examples=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("build -v --examples") + .without_status() + .with_stderr_contains( + "[RUNNING] `rustc --crate-name example_foo [..]-C link-arg=--this-is-a-bogus-flag[..]", + ) + .run(); +}