Skip to content

Commit

Permalink
Auto merge of #10274 - aviramha:extra-link-args, r=ehuss
Browse files Browse the repository at this point in the history
extra-link-arg-etc: support all link types (credit @davidhewitt)

This commit adds support for the remaining link types to `-Zextra-link-arg-etc`:
`
rustc-link-arg-tests
rustc-link-arg-benches
rustc-link-arg-examples
`
This would be useful in PyO3, where users writing Python extension modules (which do link against libpython) want to run cargo tests for extension module. As executables, these tests need to link against libpython.

This is a follow up of #9416 by `@davidhewitt`
  • Loading branch information
bors committed Jan 30, 2022
2 parents f639ea3 + 541c908 commit b2496f0
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 20 deletions.
36 changes: 26 additions & 10 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" => {
Expand All @@ -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, '=');
Expand Down Expand Up @@ -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));
}
Expand Down
30 changes: 24 additions & 6 deletions src/cargo/util/config/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,18 +173,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" => {
Expand All @@ -210,3 +219,12 @@ fn parse_links_overrides(
}
Ok(links_overrides)
}

fn extra_link_args<'a>(
link_type: LinkType,
key: &str,
value: &'a CV,
) -> CargoResult<impl Iterator<Item = (LinkType, String)> + 'a> {
let args = value.list(key)?;
Ok(args.iter().map(move |v| (link_type.clone(), v.0.clone())))
}
32 changes: 29 additions & 3 deletions src/doc/src/reference/build-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

<a id="rustc-link-arg-bins"></a>
#### `cargo:rustc-link-arg-bins=FLAG`
Expand All @@ -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

<a id="rustc-link-lib"></a>
#### `cargo:rustc-link-lib=[KIND=]NAME`
Expand All @@ -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


<a id="rustc-link-arg-tests"></a>
#### `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.


<a id="rustc-link-arg-examples"></a>
#### `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.

<a id="rustc-link-arg-benches"></a>
#### `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.

<a id="rustc-link-search"></a>
#### `cargo:rustc-link-search=[KIND=]PATH`

Expand Down Expand Up @@ -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

<a id="cargo-warning"></a>
#### `cargo:warning=MESSAGE`
Expand Down
74 changes: 73 additions & 1 deletion tests/testsuite/build_script_extra_link_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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();
}

0 comments on commit b2496f0

Please sign in to comment.