Skip to content

Commit 541c908

Browse files
committed
extra-link-arg-etc: support all link types (credit @davidhewitt)
1 parent aee9262 commit 541c908

File tree

4 files changed

+152
-20
lines changed

4 files changed

+152
-20
lines changed

src/cargo/core/compiler/custom_build.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,22 @@ impl BuildOutput {
579579
script_out_dir.to_str().unwrap(),
580580
);
581581

582+
macro_rules! check_and_add_target {
583+
($target_kind: expr, $is_target_kind: expr, $link_type: expr) => {
584+
if !targets.iter().any(|target| $is_target_kind(target)) {
585+
bail!(
586+
"invalid instruction `cargo:{}` from {}\n\
587+
The package {} does not have a {} target.",
588+
key,
589+
whence,
590+
pkg_descr,
591+
$target_kind
592+
);
593+
}
594+
linker_args.push(($link_type, value));
595+
};
596+
}
597+
582598
// Keep in sync with TargetConfig::parse_links_overrides.
583599
match key {
584600
"rustc-flags" => {
@@ -604,16 +620,7 @@ impl BuildOutput {
604620
linker_args.push((LinkType::Cdylib, value))
605621
}
606622
"rustc-link-arg-bins" => {
607-
if !targets.iter().any(|target| target.is_bin()) {
608-
bail!(
609-
"invalid instruction `cargo:{}` from {}\n\
610-
The package {} does not have a bin target.",
611-
key,
612-
whence,
613-
pkg_descr
614-
);
615-
}
616-
linker_args.push((LinkType::Bin, value));
623+
check_and_add_target!("bin", Target::is_bin, LinkType::Bin);
617624
}
618625
"rustc-link-arg-bin" => {
619626
let mut parts = value.splitn(2, '=');
@@ -643,6 +650,15 @@ impl BuildOutput {
643650
}
644651
linker_args.push((LinkType::SingleBin(bin_name), arg.to_string()));
645652
}
653+
"rustc-link-arg-tests" => {
654+
check_and_add_target!("test", Target::is_test, LinkType::Test);
655+
}
656+
"rustc-link-arg-benches" => {
657+
check_and_add_target!("benchmark", Target::is_bench, LinkType::Bench);
658+
}
659+
"rustc-link-arg-examples" => {
660+
check_and_add_target!("example", Target::is_example, LinkType::Example);
661+
}
646662
"rustc-link-arg" => {
647663
linker_args.push((LinkType::All, value));
648664
}

src/cargo/util/config/target.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,18 +172,27 @@ fn parse_links_overrides(
172172
.extend(list.iter().map(|v| PathBuf::from(&v.0)));
173173
}
174174
"rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => {
175-
let args = value.list(key)?;
176-
let args = args.iter().map(|v| (LinkType::Cdylib, v.0.clone()));
175+
let args = extra_link_args(LinkType::Cdylib, key, value)?;
177176
output.linker_args.extend(args);
178177
}
179178
"rustc-link-arg-bins" => {
180-
let args = value.list(key)?;
181-
let args = args.iter().map(|v| (LinkType::Bin, v.0.clone()));
179+
let args = extra_link_args(LinkType::Bin, key, value)?;
182180
output.linker_args.extend(args);
183181
}
184182
"rustc-link-arg" => {
185-
let args = value.list(key)?;
186-
let args = args.iter().map(|v| (LinkType::All, v.0.clone()));
183+
let args = extra_link_args(LinkType::All, key, value)?;
184+
output.linker_args.extend(args);
185+
}
186+
"rustc-link-arg-tests" => {
187+
let args = extra_link_args(LinkType::Test, key, value)?;
188+
output.linker_args.extend(args);
189+
}
190+
"rustc-link-arg-benches" => {
191+
let args = extra_link_args(LinkType::Bench, key, value)?;
192+
output.linker_args.extend(args);
193+
}
194+
"rustc-link-arg-examples" => {
195+
let args = extra_link_args(LinkType::Example, key, value)?;
187196
output.linker_args.extend(args);
188197
}
189198
"rustc-cfg" => {
@@ -209,3 +218,12 @@ fn parse_links_overrides(
209218
}
210219
Ok(links_overrides)
211220
}
221+
222+
fn extra_link_args<'a>(
223+
link_type: LinkType,
224+
key: &str,
225+
value: &'a CV,
226+
) -> CargoResult<impl Iterator<Item = (LinkType, String)> + 'a> {
227+
let args = value.list(key)?;
228+
Ok(args.iter().map(move |v| (link_type.clone(), v.0.clone())))
229+
}

src/doc/src/reference/build-scripts.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ one detailed below.
100100
flags to a linker for the binary `BIN`.
101101
* [`cargo:rustc-link-arg-bins=FLAG`](#rustc-link-arg-bins) – Passes custom
102102
flags to a linker for binaries.
103+
* [`cargo:rustc-link-arg-tests=FLAG`](#rustc-link-arg-tests) – Passes custom
104+
flags to a linker for tests.
105+
* [`cargo:rustc-link-arg-examples=FLAG`](#rustc-link-arg-examples) – Passes custom
106+
flags to a linker for examples.
107+
* [`cargo:rustc-link-arg-benches=FLAG`](#rustc-link-arg-benches) – Passes custom
108+
flags to a linker for benchmarks.
103109
* [`cargo:rustc-link-lib=[KIND=]NAME`](#rustc-link-lib) — Adds a library to
104110
link.
105111
* [`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
136142
the binary target with name `BIN`. Its usage is highly platform specific. It is useful
137143
to set a linker script or other linker options.
138144

139-
[link-arg]: ../../rustc/codegen-options/index.md#link-arg
140145

141146
<a id="rustc-link-arg-bins"></a>
142147
#### `cargo:rustc-link-arg-bins=FLAG`
@@ -146,7 +151,6 @@ link-arg=FLAG` option][link-arg] to the compiler, but only when building a
146151
binary target. Its usage is highly platform specific. It is useful
147152
to set a linker script or other linker options.
148153

149-
[link-arg]: ../../rustc/codegen-options/index.md#link-arg
150154

151155
<a id="rustc-link-lib"></a>
152156
#### `cargo:rustc-link-lib=[KIND=]NAME`
@@ -169,6 +173,29 @@ The optional `KIND` may be one of `dylib`, `static`, or `framework`. See the
169173
[option-link]: ../../rustc/command-line-arguments.md#option-l-link-lib
170174
[FFI]: ../../nomicon/ffi.md
171175

176+
177+
<a id="rustc-link-arg-tests"></a>
178+
#### `cargo:rustc-link-arg-tests=FLAG`
179+
180+
The `rustc-link-arg-tests` instruction tells Cargo to pass the [`-C
181+
link-arg=FLAG` option][link-arg] to the compiler, but only when building a
182+
tests target.
183+
184+
185+
<a id="rustc-link-arg-examples"></a>
186+
#### `cargo:rustc-link-arg-examples=FLAG`
187+
188+
The `rustc-link-arg-examples` instruction tells Cargo to pass the [`-C
189+
link-arg=FLAG` option][link-arg] to the compiler, but only when building an examples
190+
target.
191+
192+
<a id="rustc-link-arg-benches"></a>
193+
#### `cargo:rustc-link-arg-benches=FLAG`
194+
195+
The `rustc-link-arg-benches` instruction tells Cargo to pass the [`-C
196+
link-arg=FLAG` option][link-arg] to the compiler, but only when building an benchmark
197+
target.
198+
172199
<a id="rustc-link-search"></a>
173200
#### `cargo:rustc-link-search=[KIND=]PATH`
174201

@@ -247,7 +274,6 @@ link-arg=FLAG` option][link-arg] to the compiler, but only when building a
247274
`cdylib` library target. Its usage is highly platform specific. It is useful
248275
to set the shared library version or the runtime-path.
249276

250-
[link-arg]: ../../rustc/codegen-options/index.md#link-arg
251277

252278
<a id="cargo-warning"></a>
253279
#### `cargo:warning=MESSAGE`

tests/testsuite/build_script_extra_link_arg.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// and other linkers will return an error.
66

77
use cargo_test_support::registry::Package;
8-
use cargo_test_support::{basic_bin_manifest, basic_manifest, project};
8+
use cargo_test_support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, project};
99

1010
#[cargo_test]
1111
fn build_script_extra_link_arg_bin() {
@@ -310,3 +310,75 @@ fn link_arg_with_doctest() {
310310
)
311311
.run();
312312
}
313+
314+
#[cargo_test]
315+
fn build_script_extra_link_arg_tests() {
316+
let p = project()
317+
.file("Cargo.toml", &basic_lib_manifest("foo"))
318+
.file("src/lib.rs", "")
319+
.file("tests/test_foo.rs", "")
320+
.file(
321+
"build.rs",
322+
r#"
323+
fn main() {
324+
println!("cargo:rustc-link-arg-tests=--this-is-a-bogus-flag");
325+
}
326+
"#,
327+
)
328+
.build();
329+
330+
p.cargo("test -v")
331+
.without_status()
332+
.with_stderr_contains(
333+
"[RUNNING] `rustc --crate-name test_foo [..]-C link-arg=--this-is-a-bogus-flag[..]",
334+
)
335+
.run();
336+
}
337+
338+
#[cargo_test]
339+
fn build_script_extra_link_arg_benches() {
340+
let p = project()
341+
.file("Cargo.toml", &basic_lib_manifest("foo"))
342+
.file("src/lib.rs", "")
343+
.file("benches/bench_foo.rs", "")
344+
.file(
345+
"build.rs",
346+
r#"
347+
fn main() {
348+
println!("cargo:rustc-link-arg-benches=--this-is-a-bogus-flag");
349+
}
350+
"#,
351+
)
352+
.build();
353+
354+
p.cargo("bench -v")
355+
.without_status()
356+
.with_stderr_contains(
357+
"[RUNNING] `rustc --crate-name bench_foo [..]-C link-arg=--this-is-a-bogus-flag[..]",
358+
)
359+
.run();
360+
}
361+
362+
#[cargo_test]
363+
fn build_script_extra_link_arg_examples() {
364+
let p = project()
365+
.file("Cargo.toml", &basic_lib_manifest("foo"))
366+
.file("src/lib.rs", "")
367+
.file("examples/example_foo.rs", "fn main() {}")
368+
.file(
369+
"build.rs",
370+
r#"
371+
fn main() {
372+
println!("cargo:rustc-link-arg-examples=--this-is-a-bogus-flag");
373+
}
374+
"#,
375+
)
376+
.build();
377+
378+
p.cargo("build -v --examples")
379+
.without_status()
380+
.with_stderr_contains(
381+
"[RUNNING] `rustc --crate-name example_foo [..]-C link-arg=--this-is-a-bogus-flag[..]",
382+
)
383+
.run();
384+
}

0 commit comments

Comments
 (0)