Do not lose or reorder user-provided linker arguments
This commit is contained in:
parent
cff07db629
commit
13bd25e472
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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"),
|
||||
|
10
src/test/run-make-fulldeps/link-args-order/Makefile
Normal file
10
src/test/run-make-fulldeps/link-args-order/Makefile
Normal 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"'
|
6
src/test/run-make-fulldeps/link-args-order/empty.rs
Normal file
6
src/test/run-make-fulldeps/link-args-order/empty.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![feature(link_args)]
|
||||
|
||||
#[link_args = "g"]
|
||||
extern "C" {}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user