Skip to content

Commit 27ad378

Browse files
committed
Fix the wrong removal of first linker arg in Windows. Small refactor of handling of linker response file.
1 parent 84efc00 commit 27ad378

File tree

3 files changed

+23
-11
lines changed

3 files changed

+23
-11
lines changed

packages/cli/src/build/request.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2201,7 +2201,7 @@ impl BuildRequest {
22012201
// And then remove the rest of the rlibs
22022202
//
22032203
// We also need to insert the -force_load flag to force the linker to load the archive
2204-
let mut args: Vec<_> = rustc_args.link_args.iter().skip(1).cloned().collect();
2204+
let mut args: Vec<_> = rustc_args.link_args.clone();
22052205
if let Some(last_object) = args.iter().rposition(|arg| arg.ends_with(".o")) {
22062206
if archive_has_contents {
22072207
match self.linker_flavor() {

packages/cli/src/cli/link.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@ impl LinkAction {
127127
/// The file will be given by the dx-magic-link-arg env var itself, so we use
128128
/// it both for determining if we should act as a linker and the for the file name itself.
129129
fn run_link_inner(self) -> Result<()> {
130-
let mut args: Vec<_> = std::env::args().collect();
130+
let args: Vec<_> = std::env::args().collect();
131131
if args.is_empty() {
132132
return Ok(());
133133
}
134134

135-
handle_linker_command_file(&mut args);
135+
let mut args = get_actual_linker_args_excluding_program_name(args);
136136

137137
if self.triple.environment == target_lexicon::Environment::Android {
138138
args.retain(|arg| !arg.ends_with(".lib"));
@@ -149,7 +149,7 @@ impl LinkAction {
149149
let mut cmd = std::process::Command::new(linker);
150150
match cfg!(target_os = "windows") {
151151
true => cmd.arg(format!("@{}", &self.link_args_file.display())),
152-
false => cmd.args(args.iter().skip(1)),
152+
false => cmd.args(args),
153153
};
154154
let res = cmd.output().expect("Failed to run linker");
155155

@@ -240,10 +240,19 @@ impl LinkAction {
240240
}
241241
}
242242

243-
pub fn handle_linker_command_file(args: &mut Vec<String>) {
244-
// Handle command files, usually a windows thing.
245-
if let Some(command) = args.iter().find(|arg| arg.starts_with('@')).cloned() {
246-
let path = command.trim().trim_start_matches('@');
243+
pub fn get_actual_linker_args_excluding_program_name(args: Vec<String>) -> Vec<String> {
244+
args
245+
.iter()
246+
.skip(1) // the first arg is program name
247+
.flat_map(|arg| handle_linker_arg_response_file(arg).into_iter())
248+
.collect()
249+
}
250+
251+
// handle Windows linker response file. It's designed to workaround Windows command length limit.
252+
// https://learn.microsoft.com/en-us/cpp/build/reference/at-specify-a-linker-response-file?view=msvc-170
253+
pub fn handle_linker_arg_response_file(arg: &String) -> Vec<String> {
254+
if arg.starts_with('@') {
255+
let path = arg.trim().trim_start_matches('@');
247256
let file_binary = std::fs::read(path).unwrap();
248257

249258
// This may be a utf-16le file. Let's try utf-8 first.
@@ -258,14 +267,16 @@ pub fn handle_linker_command_file(args: &mut Vec<String>) {
258267
});
259268

260269
// Gather linker args, and reset the args to be just the linker args
261-
*args = content
270+
content
262271
.lines()
263272
.map(|line| {
264273
let line_parsed = line.trim().to_string();
265274
let line_parsed = line_parsed.trim_end_matches('"').to_string();
266275
let line_parsed = line_parsed.trim_start_matches('"').to_string();
267276
line_parsed
268277
})
269-
.collect();
278+
.collect()
279+
} else {
280+
vec![arg.clone()]
270281
}
271282
}

packages/cli/src/rustcwrapper.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ pub fn is_wrapping_rustc() -> bool {
2626
pub struct RustcArgs {
2727
pub args: Vec<String>,
2828
pub envs: Vec<(String, String)>,
29-
pub link_args: Vec<String>, // I don't believe this is used anymore
29+
/// it doesn't include first program name argument
30+
pub link_args: Vec<String>,
3031
}
3132

3233
/// Check if the arguments indicate a linking step, including those in command files.

0 commit comments

Comments
 (0)