Skip to content

Commit e295d7f

Browse files
npmccallumreitermarkus
authored andcommitted
Add rustc-bin-link-arg and rustc-link-arg custom build options
Both are similar to rustc-cdylib-link-arg. The rustc-bin-link-arg option adds -C link-arg=... on binary targets. The rustc-link-arg option adds -C link-arg=... on all supported targets (currently only binaries and cdylib libraries).
1 parent d5556ae commit e295d7f

File tree

4 files changed

+73
-10
lines changed

4 files changed

+73
-10
lines changed

src/cargo/core/compiler/custom_build.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::job::{Freshness, Job, Work};
2-
use super::{fingerprint, Context, Unit};
2+
use super::{fingerprint, Context, LinkType, Unit};
33
use crate::core::compiler::context::Metadata;
44
use crate::core::compiler::job_queue::JobState;
55
use crate::core::{profiles::ProfileRoot, PackageId};
@@ -23,7 +23,7 @@ pub struct BuildOutput {
2323
/// Names and link kinds of libraries, suitable for the `-l` flag.
2424
pub library_links: Vec<String>,
2525
/// Linker arguments suitable to be passed to `-C link-arg=<args>`
26-
pub linker_args: Vec<String>,
26+
pub linker_args: Vec<(Option<LinkType>, String)>,
2727
/// Various `--cfg` flags to pass to the compiler.
2828
pub cfgs: Vec<String>,
2929
/// Additional environment variables to run the compiler with.
@@ -535,7 +535,9 @@ impl BuildOutput {
535535
}
536536
"rustc-link-lib" => library_links.push(value.to_string()),
537537
"rustc-link-search" => library_paths.push(PathBuf::from(value)),
538-
"rustc-cdylib-link-arg" => linker_args.push(value.to_string()),
538+
"rustc-cdylib-link-arg" => linker_args.push((Some(LinkType::Cdylib), value)),
539+
"rustc-bin-link-arg" => linker_args.push((Some(LinkType::Bin), value)),
540+
"rustc-link-arg" => linker_args.push((None, value)),
539541
"rustc-cfg" => cfgs.push(value.to_string()),
540542
"rustc-env" => env.push(BuildOutput::parse_rustc_env(&value, &whence)?),
541543
"warning" => warnings.push(value.to_string()),

src/cargo/core/compiler/mod.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,24 @@ use crate::util::{internal, join_paths, paths, profile};
5959

6060
const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version";
6161

62+
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq)]
63+
pub enum LinkType {
64+
Cdylib,
65+
Bin,
66+
}
67+
68+
impl From<&super::Target> for Option<LinkType> {
69+
fn from(value: &super::Target) -> Self {
70+
if value.is_cdylib() {
71+
Some(LinkType::Cdylib)
72+
} else if value.is_bin() {
73+
Some(LinkType::Bin)
74+
} else {
75+
None
76+
}
77+
}
78+
}
79+
6280
/// A glorified callback for executing calls to rustc. Rather than calling rustc
6381
/// directly, we'll use an `Executor`, giving clients an opportunity to intercept
6482
/// the build calls.
@@ -196,7 +214,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc<dyn Executor>) -> Car
196214
// If we are a binary and the package also contains a library, then we
197215
// don't pass the `-l` flags.
198216
let pass_l_flag = unit.target.is_lib() || !unit.pkg.targets().iter().any(|t| t.is_lib());
199-
let pass_cdylib_link_args = unit.target.is_cdylib();
217+
let link_type = unit.target.into();
200218

201219
let dep_info_name = match cx.files().metadata(unit) {
202220
Some(metadata) => format!("{}-{}.d", unit.target.crate_name(), metadata),
@@ -244,7 +262,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc<dyn Executor>) -> Car
244262
&script_outputs,
245263
&build_scripts,
246264
pass_l_flag,
247-
pass_cdylib_link_args,
265+
link_type,
248266
current_id,
249267
)?;
250268
add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?;
@@ -326,7 +344,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc<dyn Executor>) -> Car
326344
build_script_outputs: &BuildScriptOutputs,
327345
build_scripts: &BuildScripts,
328346
pass_l_flag: bool,
329-
pass_cdylib_link_args: bool,
347+
link_type: Option<LinkType>,
330348
current_id: PackageId,
331349
) -> CargoResult<()> {
332350
for key in build_scripts.to_link.iter() {
@@ -348,8 +366,14 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc<dyn Executor>) -> Car
348366
rustc.arg("-l").arg(name);
349367
}
350368
}
351-
if pass_cdylib_link_args {
352-
for arg in output.linker_args.iter() {
369+
370+
if link_type.is_some() {
371+
for arg in output
372+
.linker_args
373+
.iter()
374+
.filter(|x| x.0.is_none() || x.0 == link_type)
375+
.map(|x| &x.1)
376+
{
353377
let link_arg = format!("link-arg={}", arg);
354378
rustc.arg("-C").arg(link_arg);
355379
}

src/cargo/util/config/target.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{Config, ConfigKey, ConfigRelativePath, OptValue, PathAndArgs, StringList, CV};
2-
use crate::core::compiler::BuildOutput;
2+
use crate::core::compiler::{BuildOutput, LinkType};
33
use crate::util::CargoResult;
44
use serde::Deserialize;
55
use std::collections::{BTreeMap, HashMap};
@@ -131,7 +131,18 @@ fn parse_links_overrides(
131131
}
132132
"rustc-cdylib-link-arg" => {
133133
let args = value.list(key)?;
134-
output.linker_args.extend(args.iter().map(|v| v.0.clone()));
134+
let args = args.iter().map(|v| (Some(LinkType::Cdylib), v.0.clone()));
135+
output.linker_args.extend(args);
136+
}
137+
"rustc-bin-link-arg" => {
138+
let args = value.list(key)?;
139+
let args = args.iter().map(|v| (Some(LinkType::Bin), v.0.clone()));
140+
output.linker_args.extend(args);
141+
}
142+
"rustc-link-arg" => {
143+
let args = value.list(key)?;
144+
let args = args.iter().map(|v| (None, v.0.clone()));
145+
output.linker_args.extend(args);
135146
}
136147
"rustc-cfg" => {
137148
let list = value.list(key)?;

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ one detailed below.
105105
* [`cargo:rustc-env=VAR=VALUE`](#rustc-env) — Sets an environment variable.
106106
* [`cargo:rustc-cdylib-link-arg=FLAG`](#rustc-cdylib-link-arg) — Passes custom
107107
flags to a linker for cdylib crates.
108+
* [`cargo:rustc-bin-link-arg=FLAG`](#rustc-bin-link-arg) — Passes custom
109+
flags to a linker for bin crates.
110+
* [`cargo:rustc-link-arg=FLAG`](#rustc-link-arg) — Passes custom
111+
flags to a linker for all supported crates.
108112
* [`cargo:warning=MESSAGE`](#cargo-warning) — Displays a warning on the
109113
terminal.
110114
* [`cargo:KEY=VALUE`](#the-links-manifest-key) — Metadata, used by `links`
@@ -205,6 +209,26 @@ to set the shared library version or the runtime-path.
205209

206210
[link-arg]: ../../rustc/codegen-options/index.md#link-arg
207211

212+
<a id="rustc-bin-link-arg"></a>
213+
#### `cargo:rustc-bin-link-arg=FLAG`
214+
215+
The `rustc-bin-link-arg` instruction tells Cargo to pass the [`-C
216+
link-arg=FLAG` option][link-arg] to the compiler, but only when building a
217+
binary target. Its usage is highly platform specific. It is useful
218+
to set a linker script or other linker options.
219+
220+
[link-arg]: ../../rustc/codegen-options/index.md#link-arg
221+
222+
<a id="rustc-link-arg"></a>
223+
#### `cargo:rustc-link-arg=FLAG`
224+
225+
The `rustc-link-arg` instruction tells Cargo to pass the [`-C link-arg=FLAG`
226+
option][link-arg] to the compiler, but only when building a supported target
227+
(currently a binary or `cdylib` library). Its usage is highly platform
228+
specific. It is useful to set the shared library version or linker script.
229+
230+
[link-arg]: ../../rustc/codegen-options/index.md#link-arg
231+
208232
<a id="cargo-warning"></a>
209233
#### `cargo:warning=MESSAGE`
210234

@@ -372,6 +396,8 @@ rustc-flags = "-L /some/path"
372396
rustc-cfg = ['key="value"']
373397
rustc-env = {key = "value"}
374398
rustc-cdylib-link-arg = [""]
399+
rustc-bin-link-arg = [""]
400+
rustc-link-arg = [""]
375401
metadata_key1 = "value"
376402
metadata_key2 = "value"
377403
```

0 commit comments

Comments
 (0)