Skip to content

Commit aafbe07

Browse files
authored
Rollup merge of #70665 - petrochenkov:linkargs, r=nagisa
Do not lose or reorder user-provided linker arguments Linker arguments are potentially order-dependent, so the order in which `-C link-arg` and `-C link-args` options are passed to `rustc` should be preserved when they are passed further to the linker. Also, multiple `-C link-args` options are now appended to each other rather than overwrite each other. In other words, `-C link-arg=a -C link-args="b c" -C link-args="d e" -C link-arg=f` is now passed as `"a" "b" "c" "d" "e" "f"` and not as `"d" "e" "a" "f"`. Addresses #70505 (comment).
2 parents be93b1c + 13bd25e commit aafbe07

File tree

5 files changed

+38
-22
lines changed

5 files changed

+38
-22
lines changed

src/librustc_codegen_ssa/back/link.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -505,10 +505,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
505505
cmd.args(args);
506506
}
507507
}
508-
if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
509-
cmd.args(args);
510-
}
511-
cmd.args(&sess.opts.debugging_opts.pre_link_arg);
508+
cmd.args(&sess.opts.debugging_opts.pre_link_args);
512509

513510
if sess.target.target.options.is_like_fuchsia {
514511
let prefix = match sess.opts.debugging_opts.sanitizer {
@@ -1302,18 +1299,17 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
13021299
cmd.gc_sections(keep_metadata);
13031300
}
13041301

1305-
let used_link_args = &codegen_results.crate_info.link_args;
1302+
let attr_link_args = codegen_results.crate_info.link_args.iter();
1303+
let user_link_args: Vec<_> =
1304+
sess.opts.cg.link_args.iter().chain(attr_link_args).cloned().collect();
13061305

13071306
if crate_type == config::CrateType::Executable {
13081307
let mut position_independent_executable = false;
13091308

13101309
if t.options.position_independent_executables {
1311-
let empty_vec = Vec::new();
1312-
let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
1313-
let more_args = &sess.opts.cg.link_arg;
1314-
let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
1315-
1316-
if is_pic(sess) && !sess.crt_static(Some(crate_type)) && !args.any(|x| *x == "-static")
1310+
if is_pic(sess)
1311+
&& !sess.crt_static(Some(crate_type))
1312+
&& !user_link_args.iter().any(|x| x == "-static")
13171313
{
13181314
position_independent_executable = true;
13191315
}
@@ -1444,11 +1440,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
14441440

14451441
// Finally add all the linker arguments provided on the command line along
14461442
// with any #[link_args] attributes found inside the crate
1447-
if let Some(ref args) = sess.opts.cg.link_args {
1448-
cmd.args(args);
1449-
}
1450-
cmd.args(&sess.opts.cg.link_arg);
1451-
cmd.args(&used_link_args);
1443+
cmd.args(&user_link_args);
14521444
}
14531445

14541446
// # Native library linking

src/librustc_interface/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ fn test_codegen_options_tracking_hash() {
382382
opts.cg.linker = Some(PathBuf::from("linker"));
383383
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
384384

385-
opts.cg.link_args = Some(vec![String::from("abc"), String::from("def")]);
385+
opts.cg.link_args = vec![String::from("abc"), String::from("def")];
386386
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
387387

388388
opts.cg.link_dead_code = true;

src/librustc_session/options.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,17 @@ macro_rules! options {
296296
use std::path::PathBuf;
297297
use std::str::FromStr;
298298

299+
// Sometimes different options need to build a common structure.
300+
// That structure can kept in one of the options' fields, the others become dummy.
301+
macro_rules! redirect_field {
302+
($cg:ident.link_arg) => { $cg.link_args };
303+
($cg:ident.pre_link_arg) => { $cg.pre_link_args };
304+
($cg:ident.$field:ident) => { $cg.$field };
305+
}
306+
299307
$(
300308
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
301-
$parse(&mut cg.$opt, v)
309+
$parse(&mut redirect_field!(cg.$opt), v)
302310
}
303311
)*
304312

@@ -643,9 +651,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
643651
"this option is deprecated and does nothing"),
644652
linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
645653
"system linker to link outputs with"),
646-
link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
654+
link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED],
647655
"a single extra argument to append to the linker invocation (can be used several times)"),
648-
link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
656+
link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
649657
"extra arguments to append to the linker invocation (space separated)"),
650658
link_dead_code: bool = (false, parse_bool, [UNTRACKED],
651659
"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,
876884
"make rustc print the total optimization fuel used by a crate"),
877885
force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
878886
"force all crates to be `rustc_private` unstable"),
879-
pre_link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
887+
pre_link_arg: (/* redirected to pre_link_args */) = ((), parse_string_push, [UNTRACKED],
880888
"a single extra argument to prepend the linker invocation (can be used several times)"),
881-
pre_link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
889+
pre_link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
882890
"extra arguments to prepend to the linker invocation (space separated)"),
883891
profile: bool = (false, parse_bool, [TRACKED],
884892
"insert profiling code"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# ignore-msvc
2+
3+
-include ../tools.mk
4+
5+
RUSTC_FLAGS = -C linker-flavor=ld -C link-arg=a -C link-args="b c" -C link-args="d e" -C link-arg=f
6+
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
7+
8+
all:
9+
$(RUSTC) $(RUSTC_FLAGS) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f" "g"'
10+
$(RUSTC) $(RUSTC_FLAGS_PRE) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f"'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(link_args)]
2+
3+
#[link_args = "g"]
4+
extern "C" {}
5+
6+
fn main() {}

0 commit comments

Comments
 (0)