From e295d7f364d8fc18b632355b4c64807f90693f1b Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Fri, 17 Jan 2020 10:50:37 -0500 Subject: [PATCH 01/14] 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). --- src/cargo/core/compiler/custom_build.rs | 8 +++--- src/cargo/core/compiler/mod.rs | 34 +++++++++++++++++++++---- src/cargo/util/config/target.rs | 15 +++++++++-- src/doc/src/reference/build-scripts.md | 26 +++++++++++++++++++ 4 files changed, 73 insertions(+), 10 deletions(-) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 7e02008c8a1..2061bd373e4 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -1,5 +1,5 @@ use super::job::{Freshness, Job, Work}; -use super::{fingerprint, Context, Unit}; +use super::{fingerprint, Context, LinkType, Unit}; use crate::core::compiler::context::Metadata; use crate::core::compiler::job_queue::JobState; use crate::core::{profiles::ProfileRoot, PackageId}; @@ -23,7 +23,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, + pub linker_args: Vec<(Option, String)>, /// Various `--cfg` flags to pass to the compiler. pub cfgs: Vec, /// Additional environment variables to run the compiler with. @@ -535,7 +535,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()), diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 53849e300e1..1c3d8137a82 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -59,6 +59,24 @@ use crate::util::{internal, join_paths, paths, profile}; const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version"; +#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq)] +pub enum LinkType { + Cdylib, + Bin, +} + +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 { + 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. @@ -196,7 +214,7 @@ 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 pass_cdylib_link_args = unit.target.is_cdylib(); + let link_type = unit.target.into(); let dep_info_name = match cx.files().metadata(unit) { Some(metadata) => format!("{}-{}.d", unit.target.crate_name(), metadata), @@ -244,7 +262,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car &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)?; @@ -326,7 +344,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car build_script_outputs: &BuildScriptOutputs, build_scripts: &BuildScripts, pass_l_flag: bool, - pass_cdylib_link_args: bool, + link_type: Option, current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { @@ -348,8 +366,14 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car 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); } diff --git a/src/cargo/util/config/target.rs b/src/cargo/util/config/target.rs index 7ae029f02f4..2d24d11d7be 100644 --- a/src/cargo/util/config/target.rs +++ b/src/cargo/util/config/target.rs @@ -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}; @@ -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)?; diff --git a/src/doc/src/reference/build-scripts.md b/src/doc/src/reference/build-scripts.md index 3bdbb6254f2..36ba3424d45 100644 --- a/src/doc/src/reference/build-scripts.md +++ b/src/doc/src/reference/build-scripts.md @@ -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` @@ -205,6 +209,26 @@ to set the shared library version or the runtime-path. [link-arg]: ../../rustc/codegen-options/index.md#link-arg + +#### `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 + + +#### `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 + #### `cargo:warning=MESSAGE` @@ -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" ``` From 92db0bd16afeb5c367e16c9d584f3ecf9355674d Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Fri, 24 Jan 2020 17:53:51 -0500 Subject: [PATCH 02/14] Add -Z extra-link-arg This hides the new rustc-bin-link-arg and rustc-link-arg build script configuration items behind an unstable flag. --- src/cargo/core/compiler/mod.rs | 15 ++++++++------- src/cargo/core/features.rs | 2 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 1c3d8137a82..b3bdd97641e 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -215,6 +215,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car // 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 extra_link_arg = cx.bcx.config.cli_unstable().extra_link_arg; let dep_info_name = match cx.files().metadata(unit) { Some(metadata) => format!("{}-{}.d", unit.target.crate_name(), metadata), @@ -263,6 +264,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car &build_scripts, pass_l_flag, link_type, + extra_link_arg, current_id, )?; add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?; @@ -345,6 +347,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car build_scripts: &BuildScripts, pass_l_flag: bool, link_type: Option, + extra_link_arg: bool, current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { @@ -366,17 +369,15 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car rustc.arg("-l").arg(name); } } - if link_type.is_some() { - for arg in output + 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); - } + .filter(|x| x.0 == Some(LinkType::Cdylib) || extra_link_arg) + .for_each(|x| { + rustc.arg("-C").arg(format!("link-arg={}", x.1)); + }); } } } diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index f2e5d957728..ec179eb6bd2 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -359,6 +359,7 @@ pub struct CliUnstable { pub terminal_width: Option>, pub namespaced_features: bool, pub weak_dep_features: bool, + pub extra_link_arg: bool, } fn deserialize_build_std<'de, D>(deserializer: D) -> Result>, D::Error> @@ -466,6 +467,7 @@ impl CliUnstable { "terminal-width" => self.terminal_width = Some(parse_usize_opt(v)?), "namespaced-features" => self.namespaced_features = parse_empty(k, v)?, "weak-dep-features" => self.weak_dep_features = parse_empty(k, v)?, + "extra-link-arg" => self.extra_link_arg = parse_empty(k, v)?, _ => bail!("unknown `-Z` flag specified: {}", k), } From 13b262491dca82b521ad58446d73cff16e6fe63e Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 2 Jul 2020 10:17:06 +0200 Subject: [PATCH 03/14] Fix compilation error. --- src/cargo/core/compiler/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index b3bdd97641e..ec22c4ea3bd 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -214,7 +214,7 @@ 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 link_type = (&unit.target).into(); let extra_link_arg = cx.bcx.config.cli_unstable().extra_link_arg; let dep_info_name = match cx.files().metadata(unit) { From d3454cb14b4e5c7b4ba04c28b56c3593001b0e78 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 2 Jul 2020 11:45:41 +0200 Subject: [PATCH 04/14] Add tests and warnings for `-Zextra-link-arg`. --- src/cargo/core/compiler/custom_build.rs | 34 +++++++-- src/cargo/core/compiler/mod.rs | 16 ++--- .../testsuite/build_script_extra_link_arg.rs | 72 +++++++++++++++++++ tests/testsuite/main.rs | 1 + 4 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 tests/testsuite/build_script_extra_link_arg.rs diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 2061bd373e4..815fdf7aa83 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -289,6 +289,8 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult { paths::create_dir_all(&script_dir)?; paths::create_dir_all(&script_out_dir)?; + let extra_link_arg = cx.bcx.config.cli_unstable().extra_link_arg; + // Prepare the unit of "dirty work" which will actually run the custom build // command. // @@ -392,8 +394,13 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult { paths::set_file_time_no_err(output_file, timestamp); paths::write(&err_file, &output.stderr)?; paths::write(&root_output_file, util::path2bytes(&script_out_dir)?)?; - let parsed_output = - BuildOutput::parse(&output.stdout, &pkg_name, &script_out_dir, &script_out_dir)?; + let parsed_output = BuildOutput::parse( + &output.stdout, + &pkg_name, + &script_out_dir, + &script_out_dir, + extra_link_arg, + )?; if json_messages { emit_build_output(state, &parsed_output, script_out_dir.as_path(), id); @@ -417,6 +424,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult { &pkg_name, &prev_script_out_dir, &script_out_dir, + extra_link_arg, )?, }; @@ -466,6 +474,7 @@ impl BuildOutput { pkg_name: &str, script_out_dir_when_generated: &Path, script_out_dir: &Path, + extra_link_arg: bool, ) -> CargoResult { let contents = paths::read_bytes(path)?; BuildOutput::parse( @@ -473,6 +482,7 @@ impl BuildOutput { pkg_name, script_out_dir_when_generated, script_out_dir, + extra_link_arg, ) } @@ -483,6 +493,7 @@ impl BuildOutput { pkg_name: &str, script_out_dir_when_generated: &Path, script_out_dir: &Path, + extra_link_arg: bool, ) -> CargoResult { let mut library_paths = Vec::new(); let mut library_links = Vec::new(); @@ -536,8 +547,20 @@ 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((Some(LinkType::Cdylib), value)), - "rustc-bin-link-arg" => linker_args.push((Some(LinkType::Bin), value)), - "rustc-link-arg" => linker_args.push((None, value)), + "rustc-bin-link-arg" => { + if extra_link_arg { + linker_args.push((Some(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)); + } else { + warnings.push(format!("cargo:{} requires -Zextra-link-arg flag", key)); + } + } "rustc-cfg" => cfgs.push(value.to_string()), "rustc-env" => env.push(BuildOutput::parse_rustc_env(&value, &whence)?), "warning" => warnings.push(value.to_string()), @@ -786,12 +809,15 @@ fn prev_build_output(cx: &mut Context<'_, '_>, unit: &Unit) -> (Option, unit: &Unit, exec: &Arc) -> Car // 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 extra_link_arg = cx.bcx.config.cli_unstable().extra_link_arg; let dep_info_name = match cx.files().metadata(unit) { Some(metadata) => format!("{}-{}.d", unit.target.crate_name(), metadata), @@ -264,7 +263,6 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car &build_scripts, pass_l_flag, link_type, - extra_link_arg, current_id, )?; add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?; @@ -347,7 +345,6 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car build_scripts: &BuildScripts, pass_l_flag: bool, link_type: Option, - extra_link_arg: bool, current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { @@ -370,14 +367,11 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car } } if link_type.is_some() { - output - .linker_args - .iter() - .filter(|x| x.0.is_none() || x.0 == link_type) - .filter(|x| x.0 == Some(LinkType::Cdylib) || extra_link_arg) - .for_each(|x| { - rustc.arg("-C").arg(format!("link-arg={}", x.1)); - }); + for (lt, arg) in &output.linker_args { + if lt.is_none() || *lt == link_type { + rustc.arg("-C").arg(format!("link-arg={}", arg)); + } + } } } } diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs new file mode 100644 index 00000000000..09a7488dc3a --- /dev/null +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -0,0 +1,72 @@ +//! Tests for -Zextra-link-arg. + +use cargo_test_support::{basic_bin_manifest, project}; + +#[cargo_test] +fn build_script_extra_bin_link_args() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:rustc-bin-link-arg=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("build -Zextra-link-arg -v") + .masquerade_as_nightly_cargo() + .with_status(101) + .with_stderr_contains( + "[RUNNING] `rustc --crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..]", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_args() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:rustc-link-arg=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("build -Zextra-link-arg -v") + .masquerade_as_nightly_cargo() + .with_status(101) + .with_stderr_contains( + "[RUNNING] `rustc --crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..]", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_args_warn_on_stable() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:rustc-link-arg=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("build -vv") + .with_status(0) + .with_stderr_contains("warning: cargo:rustc-link-arg requires -Zextra-link-arg flag") + .run(); +} diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs index 3fc5e492b3c..80d3d860c2d 100644 --- a/tests/testsuite/main.rs +++ b/tests/testsuite/main.rs @@ -20,6 +20,7 @@ mod build; mod build_plan; mod build_script; mod build_script_env; +mod build_script_extra_link_arg; mod cache_messages; mod cargo_alias_config; mod cargo_command; From 8726da21efe20d8bcb57e2b961bfc4a25f4db695 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 2 Jul 2020 11:55:44 +0200 Subject: [PATCH 05/14] Move `-Zextra-link-arg` documentation into `unstable.md`. --- src/doc/src/reference/build-scripts.md | 26 --------------------- src/doc/src/reference/unstable.md | 31 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/doc/src/reference/build-scripts.md b/src/doc/src/reference/build-scripts.md index 36ba3424d45..3bdbb6254f2 100644 --- a/src/doc/src/reference/build-scripts.md +++ b/src/doc/src/reference/build-scripts.md @@ -105,10 +105,6 @@ 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` @@ -209,26 +205,6 @@ to set the shared library version or the runtime-path. [link-arg]: ../../rustc/codegen-options/index.md#link-arg - -#### `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 - - -#### `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 - #### `cargo:warning=MESSAGE` @@ -396,8 +372,6 @@ 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" ``` diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 70989637edc..71c4a1ab0be 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -20,6 +20,37 @@ timings = 'yes' Some unstable features will require you to specify the `cargo-features` key in `Cargo.toml`. +### extra-link-arg +* Original Pull Request: [#7811](https://github.com/rust-lang/cargo/pull/7811) + +The `-Z extra-link-arg` flag makes the following two instructions available +in build scripts: + +* [`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: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 + + +#### `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 + ### no-index-update * Original Issue: [#3479](https://github.com/rust-lang/cargo/issues/3479) * Tracking Issue: [#7404](https://github.com/rust-lang/cargo/issues/7404) From 51f00f9d1c08f87f08a3f46004841027b918b42a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 2 Jul 2020 12:51:01 +0200 Subject: [PATCH 06/14] Add config warning for `-Zextra-link-arg`. --- src/cargo/util/config/target.rs | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/cargo/util/config/target.rs b/src/cargo/util/config/target.rs index 2d24d11d7be..acb7e9ae70d 100644 --- a/src/cargo/util/config/target.rs +++ b/src/cargo/util/config/target.rs @@ -77,7 +77,7 @@ pub(super) fn load_target_triple(config: &Config, triple: &str) -> CargoResult parse_links_overrides(&target_key, links.val)?, + Some(links) => parse_links_overrides(&target_key, links.val, &config)?, None => BTreeMap::new(), }; Ok(TargetConfig { @@ -91,7 +91,10 @@ pub(super) fn load_target_triple(config: &Config, triple: &str) -> CargoResult, + config: &Config, ) -> CargoResult> { + let extra_link_arg = config.cli_unstable().extra_link_arg; + let mut links_overrides = BTreeMap::new(); for (lib_name, value) in links { // Skip these keys, it shares the namespace with `TargetConfig`. @@ -135,14 +138,28 @@ fn parse_links_overrides( 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); + if extra_link_arg { + let args = value.list(key)?; + let args = args.iter().map(|v| (Some(LinkType::Bin), v.0.clone())); + output.linker_args.extend(args); + } else { + config.shell().warn(format!( + "target config `{}.{}` requires -Zextra-link-arg flag", + target_key, key + ))?; + } } "rustc-link-arg" => { - let args = value.list(key)?; - let args = args.iter().map(|v| (None, v.0.clone())); - output.linker_args.extend(args); + if extra_link_arg { + let args = value.list(key)?; + let args = args.iter().map(|v| (None, v.0.clone())); + output.linker_args.extend(args); + } else { + config.shell().warn(format!( + "target config `{}.{}` requires -Zextra-link-arg flag", + target_key, key + ))?; + } } "rustc-cfg" => { let list = value.list(key)?; From b4243dc0cca42b56375d9054e87bf7b1da6351e9 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 2 Jul 2020 12:58:10 +0200 Subject: [PATCH 07/14] Rename tests for `-Zextra-link-arg`. --- tests/testsuite/build_script_extra_link_arg.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs index 09a7488dc3a..a0a71f5ba14 100644 --- a/tests/testsuite/build_script_extra_link_arg.rs +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -3,7 +3,7 @@ use cargo_test_support::{basic_bin_manifest, project}; #[cargo_test] -fn build_script_extra_bin_link_args() { +fn build_script_extra_link_arg_bin() { let p = project() .file("Cargo.toml", &basic_bin_manifest("foo")) .file("src/main.rs", "fn main() {}") @@ -27,7 +27,7 @@ fn build_script_extra_bin_link_args() { } #[cargo_test] -fn build_script_extra_link_args() { +fn build_script_extra_link_arg() { let p = project() .file("Cargo.toml", &basic_bin_manifest("foo")) .file("src/main.rs", "fn main() {}") @@ -51,7 +51,7 @@ fn build_script_extra_link_args() { } #[cargo_test] -fn build_script_extra_link_args_warn_on_stable() { +fn build_script_extra_link_arg_warn_without_flag() { let p = project() .file("Cargo.toml", &basic_bin_manifest("foo")) .file("src/main.rs", "fn main() {}") From a8ee4778e8d24e9ea305038c5e661b8b3b40d614 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 2 Jul 2020 13:21:57 +0200 Subject: [PATCH 08/14] Remove unneeded verbose flag. --- tests/testsuite/build_script_extra_link_arg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs index a0a71f5ba14..45d140d642a 100644 --- a/tests/testsuite/build_script_extra_link_arg.rs +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -65,7 +65,7 @@ fn build_script_extra_link_arg_warn_without_flag() { ) .build(); - p.cargo("build -vv") + p.cargo("build -v") .with_status(0) .with_stderr_contains("warning: cargo:rustc-link-arg requires -Zextra-link-arg flag") .run(); From 5976d53add4061a4c4aef1b02389390e6e08dcb6 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 2 Jul 2020 13:48:30 +0200 Subject: [PATCH 09/14] Fix test on Windows. --- tests/testsuite/build_script_extra_link_arg.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs index 45d140d642a..e7286960806 100644 --- a/tests/testsuite/build_script_extra_link_arg.rs +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -19,7 +19,7 @@ fn build_script_extra_link_arg_bin() { p.cargo("build -Zextra-link-arg -v") .masquerade_as_nightly_cargo() - .with_status(101) + .without_status() .with_stderr_contains( "[RUNNING] `rustc --crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..]", ) @@ -43,7 +43,7 @@ fn build_script_extra_link_arg() { p.cargo("build -Zextra-link-arg -v") .masquerade_as_nightly_cargo() - .with_status(101) + .without_status() .with_stderr_contains( "[RUNNING] `rustc --crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..]", ) From 9fca62483f8d52bde07dc0b89813a8e809505c57 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 22 Jul 2020 02:02:37 +0200 Subject: [PATCH 10/14] Rename `rustc-bin-link-arg` to `rustc-link-arg-bins`. --- src/cargo/core/compiler/custom_build.rs | 2 +- src/cargo/util/config/target.rs | 2 +- src/doc/src/reference/unstable.md | 8 ++++---- tests/testsuite/build_script_extra_link_arg.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 815fdf7aa83..8e3ed263458 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -547,7 +547,7 @@ 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((Some(LinkType::Cdylib), value)), - "rustc-bin-link-arg" => { + "rustc-link-arg-bins" => { if extra_link_arg { linker_args.push((Some(LinkType::Bin), value)); } else { diff --git a/src/cargo/util/config/target.rs b/src/cargo/util/config/target.rs index acb7e9ae70d..d1ff8463eda 100644 --- a/src/cargo/util/config/target.rs +++ b/src/cargo/util/config/target.rs @@ -137,7 +137,7 @@ fn parse_links_overrides( let args = args.iter().map(|v| (Some(LinkType::Cdylib), v.0.clone())); output.linker_args.extend(args); } - "rustc-bin-link-arg" => { + "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())); diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 71c4a1ab0be..196d210a550 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -26,15 +26,15 @@ Some unstable features will require you to specify the `cargo-features` key in The `-Z extra-link-arg` flag makes the following two instructions available in build scripts: -* [`cargo:rustc-bin-link-arg=FLAG`](#rustc-bin-link-arg) — Passes custom +* [`cargo:rustc-link-arg-bins=FLAG`](#rustc-link-arg-bins) — 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:rustc-bin-link-arg=FLAG` + +#### `cargo:rustc-link-arg-bins=FLAG` -The `rustc-bin-link-arg` instruction tells Cargo to pass the [`-C +The `rustc-link-arg-bins` 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. diff --git a/tests/testsuite/build_script_extra_link_arg.rs b/tests/testsuite/build_script_extra_link_arg.rs index e7286960806..e655414924e 100644 --- a/tests/testsuite/build_script_extra_link_arg.rs +++ b/tests/testsuite/build_script_extra_link_arg.rs @@ -11,7 +11,7 @@ fn build_script_extra_link_arg_bin() { "build.rs", r#" fn main() { - println!("cargo:rustc-bin-link-arg=--this-is-a-bogus-flag"); + println!("cargo:rustc-link-arg-bins=--this-is-a-bogus-flag"); } "#, ) From 10ee101fabc94e0b1f17551b640f1034e86fece6 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 22 Jul 2020 02:02:59 +0200 Subject: [PATCH 11/14] Accept `rustc-link-arg-cdylib` in addition to `rustc-cdylib-link-arg`. --- src/cargo/core/compiler/custom_build.rs | 4 +++- src/cargo/util/config/target.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 8e3ed263458..0fcb7a6dfc8 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -546,7 +546,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((Some(LinkType::Cdylib), value)), + "rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => { + linker_args.push((Some(LinkType::Cdylib), value)) + } "rustc-link-arg-bins" => { if extra_link_arg { linker_args.push((Some(LinkType::Bin), value)); diff --git a/src/cargo/util/config/target.rs b/src/cargo/util/config/target.rs index d1ff8463eda..13b77e262d0 100644 --- a/src/cargo/util/config/target.rs +++ b/src/cargo/util/config/target.rs @@ -132,7 +132,7 @@ fn parse_links_overrides( .library_paths .extend(list.iter().map(|v| PathBuf::from(&v.0))); } - "rustc-cdylib-link-arg" => { + "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())); output.linker_args.extend(args); From 48913c3815c4383f59f13500a548bea31948cb50 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 24 Jul 2020 08:55:12 +0200 Subject: [PATCH 12/14] Pass link args to dependents. --- src/cargo/core/compiler/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index e0181a2cb39..4b1ed821748 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -357,6 +357,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car for path in output.library_paths.iter() { rustc.arg("-L").arg(path); } + if key.0 == current_id { for cfg in &output.cfgs { rustc.arg("--cfg").arg(cfg); @@ -366,11 +367,12 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car rustc.arg("-l").arg(name); } } - 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)); - } + } + + 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)); } } } From e433ceced642f2a274ada1ab4fbe695f773ae444 Mon Sep 17 00:00:00 2001 From: Nick Shipp Date: Fri, 16 Oct 2020 18:25:53 -0400 Subject: [PATCH 13/14] Pass extra link args to all linked targets --- src/cargo/core/compiler/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 4b1ed821748..30fa2650c97 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -63,6 +63,9 @@ const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version"; pub enum LinkType { Cdylib, Bin, + Test, + Bench, + Example, } impl From<&super::Target> for Option { @@ -71,6 +74,12 @@ impl From<&super::Target> for Option { 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 } From 51f7a44a9953825631d655948bee8e51e5f4bef8 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 3 Nov 2020 17:45:36 +0100 Subject: [PATCH 14/14] State all supported targets for `rustc-link-arg`. --- src/doc/src/reference/unstable.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 196d210a550..816df88cf07 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -26,10 +26,10 @@ Some unstable features will require you to specify the `cargo-features` key in The `-Z extra-link-arg` flag makes the following two instructions available in build scripts: -* [`cargo:rustc-link-arg-bins=FLAG`](#rustc-link-arg-bins) — 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:rustc-link-arg-bins=FLAG`](#rustc-link-arg-bins) – Passes custom + flags to a linker for binaries. +* [`cargo:rustc-link-arg=FLAG`](#rustc-link-arg) – Passes custom flags to a + linker for benchmarks, binaries, `cdylib` crates, examples, and tests. #### `cargo:rustc-link-arg-bins=FLAG` @@ -45,9 +45,10 @@ to set a linker script or other linker options. #### `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. +option][link-arg] to the compiler, but only when building supported targets +(benchmarks, binaries, `cdylib` crates, examples, and tests). 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