Skip to content

Commit

Permalink
extra-link-arg-etc: support all link types (credit @davidhewitt)
Browse files Browse the repository at this point in the history
  • Loading branch information
aviramha committed Jan 27, 2022
1 parent aee9262 commit 541c908
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 @@ -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" => {
Expand All @@ -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<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 541c908

Please sign in to comment.