Fix the wrong removal of first linker arg in Windows. Linker argument file no longer include first program name argument. Small refactor of handling of linker response file. (#5010)
Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
This commit is contained in:
1 parent
5929c09cec
commit
da72b63b6f
3 files changed
+28
-12
No files matched your search
@@ -2194,7 +2194,7 @@ impl BuildRequest {
|
|||||||
// And then remove the rest of the rlibs
|
// And then remove the rest of the rlibs
|
||||||
//
|
//
|
||||||
// We also need to insert the -force_load flag to force the linker to load the archive
|
// We also need to insert the -force_load flag to force the linker to load the archive
|
||||||
let mut args: Vec<_> = rustc_args.link_args.iter().skip(1).cloned().collect();
|
let mut args: Vec<_> = rustc_args.link_args.clone();
|
||||||
if let Some(last_object) = args.iter().rposition(|arg| arg.ends_with(".o")) {
|
if let Some(last_object) = args.iter().rposition(|arg| arg.ends_with(".o")) {
|
||||||
if archive_has_contents {
|
if archive_has_contents {
|
||||||
match self.linker_flavor() {
|
match self.linker_flavor() {
|
||||||
|
|||||||
@@ -127,12 +127,12 @@ impl LinkAction {
|
|||||||
/// The file will be given by the dx-magic-link-arg env var itself, so we use
|
/// The file will be given by the dx-magic-link-arg env var itself, so we use
|
||||||
/// it both for determining if we should act as a linker and the for the file name itself.
|
/// it both for determining if we should act as a linker and the for the file name itself.
|
||||||
fn run_link_inner(self) -> Result<()> {
|
fn run_link_inner(self) -> Result<()> {
|
||||||
let mut args: Vec<_> = std::env::args().collect();
|
let args: Vec<_> = std::env::args().collect();
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_linker_command_file(&mut args);
|
let mut args = get_actual_linker_args_excluding_program_name(args);
|
||||||
|
|
||||||
if self.triple.environment == target_lexicon::Environment::Android {
|
if self.triple.environment == target_lexicon::Environment::Android {
|
||||||
args.retain(|arg| !arg.ends_with(".lib"));
|
args.retain(|arg| !arg.ends_with(".lib"));
|
||||||
@@ -149,7 +149,7 @@ impl LinkAction {
|
|||||||
let mut cmd = std::process::Command::new(linker);
|
let mut cmd = std::process::Command::new(linker);
|
||||||
match cfg!(target_os = "windows") {
|
match cfg!(target_os = "windows") {
|
||||||
true => cmd.arg(format!("@{}", &self.link_args_file.display())),
|
true => cmd.arg(format!("@{}", &self.link_args_file.display())),
|
||||||
false => cmd.args(args.iter().skip(1)),
|
false => cmd.args(args),
|
||||||
};
|
};
|
||||||
let res = cmd.output().expect("Failed to run linker");
|
let res = cmd.output().expect("Failed to run linker");
|
||||||
|
|
||||||
@@ -240,14 +240,22 @@ impl LinkAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_linker_command_file(args: &mut Vec<String>) {
|
pub fn get_actual_linker_args_excluding_program_name(args: Vec<String>) -> Vec<String> {
|
||||||
// Handle command files, usually a windows thing.
|
args.into_iter()
|
||||||
if let Some(command) = args.iter().find(|arg| arg.starts_with('@')).cloned() {
|
.skip(1) // the first arg is program name
|
||||||
let path = command.trim().trim_start_matches('@');
|
.flat_map(|arg| handle_linker_arg_response_file(arg).into_iter())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle Windows linker response file. It's designed to workaround Windows command length limit.
|
||||||
|
// https://learn.microsoft.com/en-us/cpp/build/reference/at-specify-a-linker-response-file?view=msvc-170
|
||||||
|
pub fn handle_linker_arg_response_file(arg: String) -> Vec<String> {
|
||||||
|
if arg.starts_with('@') {
|
||||||
|
let path = arg.trim().trim_start_matches('@');
|
||||||
let file_binary = std::fs::read(path).unwrap();
|
let file_binary = std::fs::read(path).unwrap();
|
||||||
|
|
||||||
// This may be a utf-16le file. Let's try utf-8 first.
|
// This may be a utf-16le file. Let's try utf-8 first.
|
||||||
let content = String::from_utf8(file_binary.clone()).unwrap_or_else(|_| {
|
let mut content = String::from_utf8(file_binary.clone()).unwrap_or_else(|_| {
|
||||||
// Convert Vec<u8> to Vec<u16> to convert into a String
|
// Convert Vec<u8> to Vec<u16> to convert into a String
|
||||||
let binary_u16le: Vec<u16> = file_binary
|
let binary_u16le: Vec<u16> = file_binary
|
||||||
.chunks_exact(2)
|
.chunks_exact(2)
|
||||||
@@ -257,8 +265,13 @@ pub fn handle_linker_command_file(args: &mut Vec<String>) {
|
|||||||
String::from_utf16_lossy(&binary_u16le)
|
String::from_utf16_lossy(&binary_u16le)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Remove byte order mark in the beginning
|
||||||
|
if content.starts_with('\u{FEFF}') {
|
||||||
|
content.remove(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Gather linker args, and reset the args to be just the linker args
|
// Gather linker args, and reset the args to be just the linker args
|
||||||
*args = content
|
content
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
let line_parsed = line.trim().to_string();
|
let line_parsed = line.trim().to_string();
|
||||||
@@ -266,6 +279,8 @@ pub fn handle_linker_command_file(args: &mut Vec<String>) {
|
|||||||
let line_parsed = line_parsed.trim_start_matches('"').to_string();
|
let line_parsed = line_parsed.trim_start_matches('"').to_string();
|
||||||
line_parsed
|
line_parsed
|
||||||
})
|
})
|
||||||
.collect();
|
.collect()
|
||||||
|
} else {
|
||||||
|
vec![arg]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,8 @@ pub fn is_wrapping_rustc() -> bool {
|
|||||||
pub struct RustcArgs {
|
pub struct RustcArgs {
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
pub envs: Vec<(String, String)>,
|
pub envs: Vec<(String, String)>,
|
||||||
pub link_args: Vec<String>, // I don't believe this is used anymore
|
/// it doesn't include first program name argument
|
||||||
|
pub link_args: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the arguments indicate a linking step, including those in command files.
|
/// Check if the arguments indicate a linking step, including those in command files.
|
||||||
|
|||||||
Reference in new issue
Block a user