From 13bd25e4722a02f7b38797c7d116bfb9d1667e72 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 1 Apr 2020 19:17:08 +0300 Subject: [PATCH] Do not lose or reorder user-provided linker arguments --- src/librustc_codegen_ssa/back/link.rs | 24 +++++++------------ src/librustc_interface/tests.rs | 2 +- src/librustc_session/options.rs | 18 ++++++++++---- .../link-args-order/Makefile | 10 ++++++++ .../link-args-order/empty.rs | 6 +++++ 5 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 src/test/run-make-fulldeps/link-args-order/Makefile create mode 100644 src/test/run-make-fulldeps/link-args-order/empty.rs diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 1e780c5f86771..49786bc3b068d 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -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 diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index f58c5cc8eeb8a..b452ccfe33a52 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -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; diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 3962e30335db2..8cd6ca86f4689 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -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 = (None, parse_opt_pathbuf, [UNTRACKED], "system linker to link outputs with"), - link_arg: Vec = (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> = (None, parse_opt_list, [UNTRACKED], + link_args: Vec = (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 = (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> = (None, parse_opt_list, [UNTRACKED], + pre_link_args: Vec = (Vec::new(), parse_list, [UNTRACKED], "extra arguments to prepend to the linker invocation (space separated)"), profile: bool = (false, parse_bool, [TRACKED], "insert profiling code"), diff --git a/src/test/run-make-fulldeps/link-args-order/Makefile b/src/test/run-make-fulldeps/link-args-order/Makefile new file mode 100644 index 0000000000000..98c1e0eac3b0e --- /dev/null +++ b/src/test/run-make-fulldeps/link-args-order/Makefile @@ -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"' diff --git a/src/test/run-make-fulldeps/link-args-order/empty.rs b/src/test/run-make-fulldeps/link-args-order/empty.rs new file mode 100644 index 0000000000000..2439171004b5f --- /dev/null +++ b/src/test/run-make-fulldeps/link-args-order/empty.rs @@ -0,0 +1,6 @@ +#![feature(link_args)] + +#[link_args = "g"] +extern "C" {} + +fn main() {}