Do not lose or reorder user-provided linker arguments

This commit is contained in:
Vadim Petrochenkov 2020-04-01 19:17:08 +03:00
parent cff07db629
commit 13bd25e472
5 changed files with 38 additions and 22 deletions

View File

@ -505,10 +505,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
cmd.args(args);
}
}
if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
cmd.args(args);
}
cmd.args(&sess.opts.debugging_opts.pre_link_arg);
cmd.args(&sess.opts.debugging_opts.pre_link_args);
if sess.target.target.options.is_like_fuchsia {
let prefix = match sess.opts.debugging_opts.sanitizer {
@ -1302,18 +1299,17 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
cmd.gc_sections(keep_metadata);
}
let used_link_args = &codegen_results.crate_info.link_args;
let attr_link_args = codegen_results.crate_info.link_args.iter();
let user_link_args: Vec<_> =
sess.opts.cg.link_args.iter().chain(attr_link_args).cloned().collect();
if crate_type == config::CrateType::Executable {
let mut position_independent_executable = false;
if t.options.position_independent_executables {
let empty_vec = Vec::new();
let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
let more_args = &sess.opts.cg.link_arg;
let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
if is_pic(sess) && !sess.crt_static(Some(crate_type)) && !args.any(|x| *x == "-static")
if is_pic(sess)
&& !sess.crt_static(Some(crate_type))
&& !user_link_args.iter().any(|x| x == "-static")
{
position_independent_executable = true;
}
@ -1444,11 +1440,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
// Finally add all the linker arguments provided on the command line along
// with any #[link_args] attributes found inside the crate
if let Some(ref args) = sess.opts.cg.link_args {
cmd.args(args);
}
cmd.args(&sess.opts.cg.link_arg);
cmd.args(&used_link_args);
cmd.args(&user_link_args);
}
// # Native library linking

View File

@ -382,7 +382,7 @@ fn test_codegen_options_tracking_hash() {
opts.cg.linker = Some(PathBuf::from("linker"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.link_args = Some(vec![String::from("abc"), String::from("def")]);
opts.cg.link_args = vec![String::from("abc"), String::from("def")];
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.link_dead_code = true;

View File

@ -296,9 +296,17 @@ macro_rules! options {
use std::path::PathBuf;
use std::str::FromStr;
// Sometimes different options need to build a common structure.
// That structure can kept in one of the options' fields, the others become dummy.
macro_rules! redirect_field {
($cg:ident.link_arg) => { $cg.link_args };
($cg:ident.pre_link_arg) => { $cg.pre_link_args };
($cg:ident.$field:ident) => { $cg.$field };
}
$(
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
$parse(&mut cg.$opt, v)
$parse(&mut redirect_field!(cg.$opt), v)
}
)*
@ -643,9 +651,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
"this option is deprecated and does nothing"),
linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"system linker to link outputs with"),
link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED],
"a single extra argument to append to the linker invocation (can be used several times)"),
link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
"extra arguments to append to the linker invocation (space separated)"),
link_dead_code: bool = (false, parse_bool, [UNTRACKED],
"don't let linker strip dead code (turning it on can be used for code coverage)"),
@ -876,9 +884,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"make rustc print the total optimization fuel used by a crate"),
force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
"force all crates to be `rustc_private` unstable"),
pre_link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
pre_link_arg: (/* redirected to pre_link_args */) = ((), parse_string_push, [UNTRACKED],
"a single extra argument to prepend the linker invocation (can be used several times)"),
pre_link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
pre_link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
"extra arguments to prepend to the linker invocation (space separated)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code"),

View File

@ -0,0 +1,10 @@
# ignore-msvc
-include ../tools.mk
RUSTC_FLAGS = -C linker-flavor=ld -C link-arg=a -C link-args="b c" -C link-args="d e" -C link-arg=f
RUSTC_FLAGS_PRE = -C linker-flavor=ld -Z pre-link-arg=a -Z pre-link-args="b c" -Z pre-link-args="d e" -Z pre-link-arg=f
all:
$(RUSTC) $(RUSTC_FLAGS) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f" "g"'
$(RUSTC) $(RUSTC_FLAGS_PRE) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f"'

View File

@ -0,0 +1,6 @@
#![feature(link_args)]
#[link_args = "g"]
extern "C" {}
fn main() {}