@@ -157,8 +157,8 @@ public struct Driver {
157
157
) throws {
158
158
// FIXME: Determine if we should run as subcommand.
159
159
160
- let args = try Self . expandResponseFiles ( args)
161
160
self . diagnosticEngine = DiagnosticsEngine ( handlers: [ diagnosticsHandler] )
161
+ let args = try Self . expandResponseFiles ( args, diagnosticsEngine: self . diagnosticEngine)
162
162
self . driverKind = try Self . determineDriverKind ( args: args)
163
163
self . optionTable = OptionTable ( )
164
164
self . parsedOptions = try optionTable. parse ( Array ( args. dropFirst ( ) ) )
@@ -252,18 +252,39 @@ public struct Driver {
252
252
self . swiftInterfacePath = try Self . computeSupplementaryOutputPath ( & parsedOptions, type: . swiftInterface, isOutput: . emit_module_interface, outputPath: . emit_module_interface_path, compilerOutputType: compilerOutputType, moduleName: moduleName)
253
253
self . optimizationRecordPath = try Self . computeSupplementaryOutputPath ( & parsedOptions, type: . optimizationRecord, isOutput: . save_optimization_record, outputPath: . save_optimization_record_path, compilerOutputType: compilerOutputType, moduleName: moduleName)
254
254
}
255
+ }
255
256
256
- /// Expand response files in the input arguments and return a new argument list.
257
- public static func expandResponseFiles( _ args: [ String ] ) throws -> [ String ] {
257
+ // Response files.
258
+ extension Driver {
259
+ /// Tokenize a single line in a response file
260
+ private static func tokenizeResponseFileLine( _ line: String ) -> String {
261
+ // FIXME: This is wrong. We need to do proper shell escaping.
262
+ return line. replacingOccurrences ( of: " \\ " , with: " " )
263
+ }
264
+
265
+ private static func expandResponseFiles(
266
+ _ args: [ String ] ,
267
+ diagnosticsEngine: DiagnosticsEngine ,
268
+ visitedResponseFiles: inout Set < AbsolutePath >
269
+ ) throws -> [ String ] {
258
270
// FIXME: This is very very prelimary. Need to look at how Swift compiler expands response file.
259
271
260
272
var result : [ String ] = [ ]
261
273
262
274
// Go through each arg and add arguments from response files.
263
275
for arg in args {
264
276
if arg. first == " @ " , let responseFile = try ? AbsolutePath ( validating: String ( arg. dropFirst ( ) ) ) {
277
+ guard visitedResponseFiles. insert ( responseFile) . inserted else {
278
+ diagnosticsEngine. emit ( . warn_recursive_response_file( responseFile) )
279
+ continue
280
+ }
281
+ defer {
282
+ visitedResponseFiles. remove ( responseFile)
283
+ }
284
+
265
285
let contents = try localFileSystem. readFileContents ( responseFile) . cString
266
- result += contents. split ( separator: " \n " , omittingEmptySubsequences: true ) . map ( String . init)
286
+ let lines = contents. split ( separator: " \n " , omittingEmptySubsequences: true ) . map { tokenizeResponseFileLine ( String ( $0) ) }
287
+ result. append ( contentsOf: try expandResponseFiles ( lines, diagnosticsEngine: diagnosticsEngine, visitedResponseFiles: & visitedResponseFiles) )
267
288
} else {
268
289
result. append ( arg)
269
290
}
@@ -272,6 +293,17 @@ public struct Driver {
272
293
return result
273
294
}
274
295
296
+ /// Expand response files in the input arguments and return a new argument list.
297
+ public static func expandResponseFiles(
298
+ _ args: [ String ] ,
299
+ diagnosticsEngine: DiagnosticsEngine
300
+ ) throws -> [ String ] {
301
+ var visitedResponseFiles = Set < AbsolutePath > ( )
302
+ return try expandResponseFiles ( args, diagnosticsEngine: diagnosticsEngine, visitedResponseFiles: & visitedResponseFiles)
303
+ }
304
+ }
305
+
306
+ extension Driver {
275
307
/// Determine the driver kind based on the command-line arguments.
276
308
public static func determineDriverKind(
277
309
args: [ String ] ,
@@ -364,6 +396,10 @@ public struct Driver {
364
396
}
365
397
366
398
extension Diagnostic . Message {
399
+ static func warn_recursive_response_file( _ path: AbsolutePath ) -> Diagnostic . Message {
400
+ . warning( " response file ' \( path) ' is recursively expanded " )
401
+ }
402
+
367
403
static var error_no_swift_frontend : Diagnostic . Message {
368
404
. error( " -driver-use-frontend-path requires a Swift compiler executable argument " )
369
405
}
0 commit comments