@@ -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}
0 commit comments