Skip to content

Commit 2581af8

Browse files
committed
Response files should be named using the hash of the command line arguments only
1 parent 5e9abc0 commit 2581af8

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

Sources/SwiftDriver/Execution/ArgsResolver.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import class Foundation.NSLock
1515
import func TSCBasic.withTemporaryDirectory
1616
import protocol TSCBasic.FileSystem
1717
import struct TSCBasic.AbsolutePath
18+
import struct TSCBasic.SHA256
1819

1920
@_implementationOnly import Yams
2021

@@ -208,7 +209,8 @@ public final class ArgsResolver {
208209
assert(!forceResponseFiles || job.supportsResponseFiles,
209210
"Platform does not support response files for job: \(job)")
210211
// Match the integrated driver's behavior, which uses response file names of the form "arguments-[0-9a-zA-Z].resp".
211-
let responseFilePath = temporaryDirectory.appending(component: "arguments-\(abs(job.hashValue)).resp")
212+
let hash = SHA256().hash(resolvedArguments.joined(separator: " ")).hexadecimalRepresentation
213+
let responseFilePath = temporaryDirectory.appending(component: "arguments-\(hash).resp")
212214

213215
// FIXME: Need a way to support this for distributed build systems...
214216
if let absPath = responseFilePath.absolutePath {

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,26 @@ final class SwiftDriverTests: XCTestCase {
17121712
XCTAssertFalse(resolvedArgs.contains { $0.hasPrefix("@") })
17131713
}
17141714
}
1715+
1716+
func testResponseFileDeterministicNaming() throws {
1717+
#if !os(macOS)
1718+
throw XCTSkip("Test assumes macOS response file quoting behavior")
1719+
#endif
1720+
do {
1721+
let manyArgs = (1...20000).map { "-DTEST_\($0)" }
1722+
var driver = try Driver(args: ["swift"] + manyArgs + ["/foo.swift"])
1723+
let jobs = try driver.planBuild()
1724+
XCTAssertTrue(jobs.count == 1 && jobs[0].kind == .interpret)
1725+
let interpretJob = jobs[0]
1726+
let resolver = try ArgsResolver(fileSystem: localFileSystem)
1727+
let resolvedArgs: [String] = try resolver.resolveArgumentList(for: interpretJob)
1728+
XCTAssertTrue(resolvedArgs.count == 3)
1729+
XCTAssertEqual(resolvedArgs[1], "-frontend")
1730+
XCTAssertEqual(resolvedArgs[2].first, "@")
1731+
let responseFilePath = try AbsolutePath(validating: String(resolvedArgs[2].dropFirst()))
1732+
XCTAssertEqual(responseFilePath.basename, "arguments-b8821417b0e2b7903ed3121610ab6a9721637b459c6703ef1af18297c2a4998f.resp")
1733+
}
1734+
}
17151735

17161736
func testSpecificJobsResponseFiles() throws {
17171737
// The jobs below often take large command lines (e.g., when passing a large number of Clang

0 commit comments

Comments
 (0)