diff --git a/Sources/SwiftDriver/Execution/ArgsResolver.swift b/Sources/SwiftDriver/Execution/ArgsResolver.swift index 00a846657..420a749f8 100644 --- a/Sources/SwiftDriver/Execution/ArgsResolver.swift +++ b/Sources/SwiftDriver/Execution/ArgsResolver.swift @@ -196,9 +196,6 @@ public final class ArgsResolver { } private func createResponseFileIfNeeded(for job: Job, resolvedArguments: inout [String], useResponseFiles: ResponseFileHandling) throws -> Bool { - func quote(_ string: String) -> String { - return "\"\(String(string.flatMap { ["\\", "\""].contains($0) ? "\\\($0)" : "\($0)" }))\"" - } guard useResponseFiles != .disabled else { return false } @@ -214,11 +211,8 @@ public final class ArgsResolver { // FIXME: Need a way to support this for distributed build systems... if let absPath = responseFilePath.absolutePath { - // Adopt the same technique as clang - - // Wrap all arguments in double quotes to ensure that both Unix and - // Windows tools understand the response file. try fileSystem.writeFileContents(absPath) { - $0.send(resolvedArguments[2...].map { quote($0) }.joined(separator: "\n")) + $0.send(resolvedArguments[2...].map { $0.spm_shellEscaped() }.joined(separator: "\n")) } resolvedArguments = [resolvedArguments[0], resolvedArguments[1], "@\(absPath.pathString)"] } diff --git a/Sources/SwiftDriver/Jobs/LinkJob.swift b/Sources/SwiftDriver/Jobs/LinkJob.swift index fa7d40eb5..76668127e 100644 --- a/Sources/SwiftDriver/Jobs/LinkJob.swift +++ b/Sources/SwiftDriver/Jobs/LinkJob.swift @@ -49,6 +49,15 @@ extension Driver { mutating func linkJob(inputs: [TypedVirtualPath]) throws -> Job { var commandLine: [Job.ArgTemplate] = [] + #if os(Windows) + // We invoke clang as `clang.exe`, which expects a POSIX-style response file by default (`clang-cl.exe` expects + // Windows-style response files). + // The driver is outputting Windows-style response files because swift-frontend expects Windows-style response + // files. + // Force `clang.exe` into parsing Windows-style response files. + commandLine.appendFlag("--rsp-quoting=windows") + #endif + // Compute the final output file let outputFile: VirtualPath if let output = parsedOptions.getLastArgument(.o) { diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index 2c6149df1..9c9c275da 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -1695,9 +1695,9 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(resolvedArgs[2].first, "@") let responseFilePath = try AbsolutePath(validating: String(resolvedArgs[2].dropFirst())) let contents = try localFileSystem.readFileContents(responseFilePath).description - XCTAssertTrue(contents.hasPrefix("\"-interpret\"\n\"/foo.swift\"")) - XCTAssertTrue(contents.contains("\"-D\"\n\"TEST_20000\"")) - XCTAssertTrue(contents.contains("\"-D\"\n\"TEST_1\"")) + XCTAssertTrue(contents.hasPrefix("-interpret\n/foo.swift")) + XCTAssertTrue(contents.contains("-D\nTEST_20000")) + XCTAssertTrue(contents.contains("-D\nTEST_1")) } // Needs response file + disable override @@ -1724,7 +1724,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(resolvedArgs[2].first, "@") let responseFilePath = try AbsolutePath(validating: String(resolvedArgs[2].dropFirst())) let contents = try localFileSystem.readFileContents(responseFilePath).description - XCTAssertTrue(contents.hasPrefix("\"-interpret\"\n\"/foo.swift\"")) + XCTAssertTrue(contents.hasPrefix("-interpret\n/foo.swift")) } // No response file