From 0895469aecba6d32b9df35bd38935db081340d78 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 12 May 2021 00:21:35 +0200 Subject: [PATCH 1/4] Allow LinkType to access the Target for checking if it applies. --- src/cargo/core/compiler/custom_build.rs | 8 +++--- src/cargo/core/compiler/mod.rs | 37 ++++++++++--------------- src/cargo/util/config/target.rs | 6 ++-- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 1587f100eae..e4c56bfc2de 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -25,7 +25,7 @@ pub struct BuildOutput { /// Names and link kinds of libraries, suitable for the `-l` flag. pub library_links: Vec, /// Linker arguments suitable to be passed to `-C link-arg=` - pub linker_args: Vec<(Option, String)>, + pub linker_args: Vec<(LinkType, String)>, /// Various `--cfg` flags to pass to the compiler. pub cfgs: Vec, /// Additional environment variables to run the compiler with. @@ -562,18 +562,18 @@ impl BuildOutput { "rustc-link-lib" => library_links.push(value.to_string()), "rustc-link-search" => library_paths.push(PathBuf::from(value)), "rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => { - linker_args.push((Some(LinkType::Cdylib), value)) + linker_args.push((LinkType::Cdylib, value)) } "rustc-link-arg-bins" => { if extra_link_arg { - linker_args.push((Some(LinkType::Bin), value)); + linker_args.push((LinkType::Bin, value)); } else { warnings.push(format!("cargo:{} requires -Zextra-link-arg flag", key)); } } "rustc-link-arg" => { if extra_link_arg { - linker_args.push((None, value)); + linker_args.push((LinkType::All, value)); } else { warnings.push(format!("cargo:{} requires -Zextra-link-arg flag", key)); } diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 969e5996180..d9fc315de39 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -64,6 +64,7 @@ const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version"; #[derive(Copy, Clone, Hash, Debug, PartialEq, Eq)] pub enum LinkType { + All, Cdylib, Bin, Test, @@ -71,20 +72,15 @@ pub enum LinkType { Example, } -impl From<&super::Target> for Option { - fn from(value: &super::Target) -> Self { - if value.is_cdylib() { - Some(LinkType::Cdylib) - } else if value.is_bin() { - Some(LinkType::Bin) - } else if value.is_test() { - Some(LinkType::Test) - } else if value.is_bench() { - Some(LinkType::Bench) - } else if value.is_exe_example() { - Some(LinkType::Example) - } else { - None +impl LinkType { + pub fn applies_to(&self, target: &Target) -> bool { + match self { + LinkType::All => true, + LinkType::Cdylib => target.is_cdylib(), + LinkType::Bin => target.is_bin(), + LinkType::Test => target.is_test(), + LinkType::Bench => target.is_bench(), + LinkType::Example => target.is_exe_example(), } } } @@ -227,7 +223,6 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car // 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 link_type = (&unit.target).into(); let dep_info_name = if cx.files().use_extra_filename(unit) { format!( @@ -280,7 +275,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car &script_outputs, &build_scripts, pass_l_flag, - link_type, + &target, current_id, )?; add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?; @@ -371,7 +366,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car build_script_outputs: &BuildScriptOutputs, build_scripts: &BuildScripts, pass_l_flag: bool, - link_type: Option, + target: &Target, current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { @@ -396,11 +391,9 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car } } - if link_type.is_some() { - for (lt, arg) in &output.linker_args { - if lt.is_none() || *lt == link_type { - rustc.arg("-C").arg(format!("link-arg={}", arg)); - } + for (lt, arg) in &output.linker_args { + if lt.applies_to(&target) { + rustc.arg("-C").arg(format!("link-arg={}", arg)); } } } diff --git a/src/cargo/util/config/target.rs b/src/cargo/util/config/target.rs index e22cab92ee5..304679854ff 100644 --- a/src/cargo/util/config/target.rs +++ b/src/cargo/util/config/target.rs @@ -134,13 +134,13 @@ fn parse_links_overrides( } "rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => { let args = value.list(key)?; - let args = args.iter().map(|v| (Some(LinkType::Cdylib), v.0.clone())); + let args = args.iter().map(|v| (LinkType::Cdylib, v.0.clone())); output.linker_args.extend(args); } "rustc-link-arg-bins" => { if extra_link_arg { let args = value.list(key)?; - let args = args.iter().map(|v| (Some(LinkType::Bin), v.0.clone())); + let args = args.iter().map(|v| (LinkType::Bin, v.0.clone())); output.linker_args.extend(args); } else { config.shell().warn(format!( @@ -152,7 +152,7 @@ fn parse_links_overrides( "rustc-link-arg" => { if extra_link_arg { let args = value.list(key)?; - let args = args.iter().map(|v| (None, v.0.clone())); + let args = args.iter().map(|v| (LinkType::All, v.0.clone())); output.linker_args.extend(args); } else { config.shell().warn(format!( From 5382aa650aecffb73f19eaa5ec73345ad1a1b9d2 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 14 May 2021 22:13:57 +0200 Subject: [PATCH 2/4] Add rustc-link-arg-bin key to specify per-bin link args. --- src/cargo/core/compiler/custom_build.rs | 18 ++++++++++++++++++ src/cargo/core/compiler/mod.rs | 4 +++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index e4c56bfc2de..0360c088888 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -571,6 +571,24 @@ impl BuildOutput { warnings.push(format!("cargo:{} requires -Zextra-link-arg flag", key)); } } + "rustc-link-arg-bin" => { + if extra_link_arg { + let parts = value.splitn(2, "=").collect::>(); + if parts.len() == 2 { + linker_args.push(( + LinkType::SingleBin(parts[0].to_string()), + parts[1].to_string(), + )); + } else { + warnings.push(format!( + "cargo:{} has invalid syntax: expected `cargo:{}=BIN=ARG`", + key, key + )); + } + } else { + warnings.push(format!("cargo:{} requires -Zextra-link-arg flag", key)); + } + } "rustc-link-arg" => { if extra_link_arg { linker_args.push((LinkType::All, value)); diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index d9fc315de39..5079046e767 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -62,11 +62,12 @@ use cargo_util::{paths, ProcessBuilder, ProcessError}; const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version"; -#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq)] +#[derive(Clone, Hash, Debug, PartialEq, Eq)] pub enum LinkType { All, Cdylib, Bin, + SingleBin(String), Test, Bench, Example, @@ -78,6 +79,7 @@ impl LinkType { LinkType::All => true, LinkType::Cdylib => target.is_cdylib(), LinkType::Bin => target.is_bin(), + LinkType::SingleBin(name) => target.is_bin() && target.name() == name, LinkType::Test => target.is_test(), LinkType::Bench => target.is_bench(), LinkType::Example => target.is_exe_example(), From 160756368fefa8dc6034c15962f1f34e151e4873 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 20 May 2021 21:41:17 +0200 Subject: [PATCH 3/4] Add test for `cargo:rustc-link-arg-bin=foo=--bar` --- .../testsuite/build_script_extra_link_arg.rs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs index e655414924e..afd8e085aef 100644 --- a/tests/testsuite/build_script_extra_link_arg.rs +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -26,6 +26,49 @@ fn build_script_extra_link_arg_bin() { .run(); } +#[cargo_test] +fn build_script_extra_link_arg_bin_single() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foobar" + version = "0.5.0" + authors = ["wycats@example.com"] + + [[bin]] + name = "foo" + [[bin]] + name = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:rustc-link-arg-bins=--bogus-flag-all"); + println!("cargo:rustc-link-arg-bin=foo=--bogus-flag-foo"); + println!("cargo:rustc-link-arg-bin=bar=--bogus-flag-bar"); + } + "#, + ) + .build(); + + p.cargo("build -Zextra-link-arg -v") + .masquerade_as_nightly_cargo() + .without_status() + .with_stderr_contains( + "[RUNNING] `rustc --crate-name foo [..]-C link-arg=--bogus-flag-all -C link-arg=--bogus-flag-foo[..]", + ) + .with_stderr_contains( + "[RUNNING] `rustc --crate-name bar [..]-C link-arg=--bogus-flag-all -C link-arg=--bogus-flag-bar[..]", + ) + .run(); +} + #[cargo_test] fn build_script_extra_link_arg() { let p = project() From daffd0a42bb1513cd72b2db6cc5443f6344f47af Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 20 May 2021 21:50:50 +0200 Subject: [PATCH 4/4] Add unstable docs for `cargo:rustc-link-arg-bin=foo=--bar` --- src/doc/src/reference/unstable.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 348936aba86..e4befbccd69 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -137,11 +137,13 @@ Cargo _or_ Rust features can be used. * Tracking Issue: [#9426](https://github.com/rust-lang/cargo/issues/9426) * Original Pull Request: [#7811](https://github.com/rust-lang/cargo/pull/7811) -The `-Z extra-link-arg` flag makes the following two instructions available +The `-Z extra-link-arg` flag makes the following instructions available in build scripts: * [`cargo:rustc-link-arg-bins=FLAG`](#rustc-link-arg-bins) – Passes custom flags to a linker for binaries. +* [`cargo:rustc-link-arg-bin=BIN=FLAG`](#rustc-link-arg-bin) – Passes custom + flags to a linker for the binary `BIN`. * [`cargo:rustc-link-arg=FLAG`](#rustc-link-arg) – Passes custom flags to a linker for benchmarks, binaries, `cdylib` crates, examples, and tests. @@ -155,6 +157,16 @@ to set a linker script or other linker options. [link-arg]: ../../rustc/codegen-options/index.md#link-arg + +#### `cargo:rustc-link-arg-bin=BIN=FLAG` + +The `rustc-link-arg-bin` instruction tells Cargo to pass the [`-C +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 + #### `cargo:rustc-link-arg=FLAG`