Skip to content

Commit

Permalink
Add rustc-bin-link-arg and rustc-link-arg custom build options
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
npmccallum committed Jan 24, 2020
1 parent b68b097 commit ab0f482
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 10 deletions.
8 changes: 5 additions & 3 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::job::{Freshness, Job, Work};
use super::{fingerprint, CompileKind, Context, Unit};
use super::{fingerprint, CompileKind, Context, LinkType, Unit};
use crate::core::compiler::job_queue::JobState;
use crate::core::{profiles::ProfileRoot, PackageId};
use crate::util::errors::{CargoResult, CargoResultExt};
Expand All @@ -20,7 +20,7 @@ pub struct BuildOutput {
/// Names and link kinds of libraries, suitable for the `-l` flag.
pub library_links: Vec<String>,
/// Linker arguments suitable to be passed to `-C link-arg=<args>`
pub linker_args: Vec<String>,
pub linker_args: Vec<(Option<LinkType>, String)>,
/// Various `--cfg` flags to pass to the compiler.
pub cfgs: Vec<String>,
/// Additional environment variables to run the compiler with.
Expand Down Expand Up @@ -478,7 +478,9 @@ impl BuildOutput {
}
"rustc-link-lib" => library_links.push(value.to_string()),
"rustc-link-search" => library_paths.push(PathBuf::from(value)),
"rustc-cdylib-link-arg" => linker_args.push(value.to_string()),
"rustc-cdylib-link-arg" => linker_args.push((Some(LinkType::Cdylib), value)),
"rustc-bin-link-arg" => linker_args.push((Some(LinkType::Bin), value)),
"rustc-link-arg" => linker_args.push((None, value)),
"rustc-cfg" => cfgs.push(value.to_string()),
"rustc-env" => env.push(BuildOutput::parse_rustc_env(&value, &whence)?),
"warning" => warnings.push(value.to_string()),
Expand Down
34 changes: 29 additions & 5 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,24 @@ use crate::util::machine_message::Message;
use crate::util::{self, machine_message, ProcessBuilder};
use crate::util::{internal, join_paths, paths, profile};

#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq)]
pub enum LinkType {
Cdylib,
Bin,
}

impl From<&super::Target> for Option<LinkType> {
fn from(value: &super::Target) -> Self {
if value.is_cdylib() {
Some(LinkType::Cdylib)
} else if value.is_bin() {
Some(LinkType::Bin)
} else {
None
}
}
}

/// A glorified callback for executing calls to rustc. Rather than calling rustc
/// directly, we'll use an `Executor`, giving clients an opportunity to intercept
/// the build calls.
Expand Down Expand Up @@ -191,7 +209,7 @@ fn rustc<'a, 'cfg>(
// If we are a binary and the package also contains a library, then we
// don't pass the `-l` flags.
let pass_l_flag = unit.target.is_lib() || !unit.pkg.targets().iter().any(|t| t.is_lib());
let pass_cdylib_link_args = unit.target.is_cdylib();
let link_type = unit.target.into();
let do_rename = unit.target.allows_underscores() && !unit.mode.is_any_test();
let real_name = unit.target.name().to_string();
let crate_name = unit.target.crate_name();
Expand Down Expand Up @@ -242,7 +260,7 @@ fn rustc<'a, 'cfg>(
&script_outputs,
&build_scripts,
pass_l_flag,
pass_cdylib_link_args,
link_type,
current_id,
)?;
add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?;
Expand Down Expand Up @@ -336,7 +354,7 @@ fn rustc<'a, 'cfg>(
build_script_outputs: &BuildScriptOutputs,
build_scripts: &BuildScripts,
pass_l_flag: bool,
pass_cdylib_link_args: bool,
link_type: Option<LinkType>,
current_id: PackageId,
) -> CargoResult<()> {
for key in build_scripts.to_link.iter() {
Expand All @@ -358,8 +376,14 @@ fn rustc<'a, 'cfg>(
rustc.arg("-l").arg(name);
}
}
if pass_cdylib_link_args {
for arg in output.linker_args.iter() {

if link_type.is_some() {
for arg in output
.linker_args
.iter()
.filter(|x| x.0.is_none() || x.0 == link_type)
.map(|x| &x.1)
{
let link_arg = format!("link-arg={}", arg);
rustc.arg("-C").arg(link_arg);
}
Expand Down
15 changes: 13 additions & 2 deletions src/cargo/util/config/target.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{Config, ConfigKey, ConfigRelativePath, OptValue, PathAndArgs, StringList, CV};
use crate::core::compiler::BuildOutput;
use crate::core::compiler::{BuildOutput, LinkType};
use crate::util::CargoResult;
use serde::Deserialize;
use std::collections::{BTreeMap, HashMap};
Expand Down Expand Up @@ -131,7 +131,18 @@ fn parse_links_overrides(
}
"rustc-cdylib-link-arg" => {
let args = value.list(key)?;
output.linker_args.extend(args.iter().map(|v| v.0.clone()));
let args = args.iter().map(|v| (Some(LinkType::Cdylib), v.0.clone()));
output.linker_args.extend(args);
}
"rustc-bin-link-arg" => {
let args = value.list(key)?;
let args = args.iter().map(|v| (Some(LinkType::Bin), v.0.clone()));
output.linker_args.extend(args);
}
"rustc-link-arg" => {
let args = value.list(key)?;
let args = args.iter().map(|v| (None, v.0.clone()));
output.linker_args.extend(args);
}
"rustc-cfg" => {
let list = value.list(key)?;
Expand Down
26 changes: 26 additions & 0 deletions src/doc/src/reference/build-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ one detailed below.
* [`cargo:rustc-env=VAR=VALUE`](#rustc-env) — Sets an environment variable.
* [`cargo:rustc-cdylib-link-arg=FLAG`](#rustc-cdylib-link-arg) — Passes custom
flags to a linker for cdylib crates.
* [`cargo:rustc-bin-link-arg=FLAG`](#rustc-bin-link-arg) — Passes custom
flags to a linker for bin crates.
* [`cargo:rustc-link-arg=FLAG`](#rustc-link-arg) — Passes custom
flags to a linker for all supported crates.
* [`cargo:warning=MESSAGE`](#cargo-warning) — Displays a warning on the
terminal.
* [`cargo:KEY=VALUE`](#the-links-manifest-key) — Metadata, used by `links`
Expand Down Expand Up @@ -205,6 +209,26 @@ to set the shared library version or the runtime-path.

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

<a id="rustc-bin-link-arg"></a>
#### `cargo:rustc-bin-link-arg=FLAG`

The `rustc-bin-link-arg` instruction tells Cargo to pass the [`-C
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-arg"></a>
#### `cargo:rustc-link-arg=FLAG`

The `rustc-link-arg` instruction tells Cargo to pass the [`-C link-arg=FLAG`
option][link-arg] to the compiler, but only when building a supported target
(currently a binary or `cdylib` library). Its usage is highly platform
specific. It is useful to set the shared library version or linker script.

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

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

Expand Down Expand Up @@ -372,6 +396,8 @@ rustc-flags = "-L /some/path"
rustc-cfg = ['key="value"']
rustc-env = {key = "value"}
rustc-cdylib-link-arg = [""]
rustc-bin-link-arg = [""]
rustc-link-arg = [""]
metadata_key1 = "value"
metadata_key2 = "value"
```
Expand Down

0 comments on commit ab0f482

Please sign in to comment.