Skip to content

Commit 50344c0

Browse files
committed
Build: migrate to file lists for driver invocations
When invoking the driver use file lists rather than passing all the sources on the command line. This is particularly import for Windows where the command line limit is 32k. With deep dependency sets and large projects, it is possible to overrun this limit and fail to invoke the command. The driver itself will invoke the frontend using response files if the invocation will overflow the command line limit. The test expectations need to be altered as we will use the build directories to store the file list which is the temps path.
1 parent 0d43a5e commit 50344c0

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,8 @@ public final class SwiftTargetBuildDescription {
546546
}
547547

548548
result.append("-c")
549-
result.append(contentsOf: self.sources.map(\.pathString))
549+
// FIXME: Eliminate side effect.
550+
try result.append("@\(self.writeFileList(includeDerivedSources: true).pathString)")
550551

551552
result.append("-I")
552553
result.append(self.buildParameters.buildPath.pathString)
@@ -578,9 +579,8 @@ public final class SwiftTargetBuildDescription {
578579

579580
// FIXME: Handle WMO
580581

581-
for source in self.target.sources.paths {
582-
result.append(source.pathString)
583-
}
582+
// FIXME: Eliminate side effect.
583+
try result.append("@\(self.writeFileList().pathString)")
584584

585585
result.append("-I")
586586
result.append(self.buildParameters.buildPath.pathString)
@@ -631,9 +631,8 @@ public final class SwiftTargetBuildDescription {
631631
// FIXME: Handle WMO
632632

633633
result.append("-c")
634-
for source in self.target.sources.paths {
635-
result.append(source.pathString)
636-
}
634+
// FIXME: Eliminate side effect.
635+
try result.append("@\(self.writeFileList().pathString)")
637636

638637
result.append("-I")
639638
result.append(self.buildParameters.buildPath.pathString)
@@ -677,6 +676,13 @@ public final class SwiftTargetBuildDescription {
677676
self.buildParameters.triple.isDarwin() && self.target.type == .library
678677
}
679678

679+
private func writeFileList(includeDerivedSources: Bool = false) throws -> AbsolutePath {
680+
let path = self.tempsPath.appending(component: "\(self.target.name)-\(includeDerivedSources ? "all-" : "")sources.filelist")
681+
let contents = (includeDerivedSources ? self.sources : self.target.sources.paths).map { $0.pathString.spm_shellEscaped() }.joined(separator: "\n")
682+
try self.fileSystem.writeFileContents(path, string: contents)
683+
return path
684+
}
685+
680686
private func writeOutputFileMap() throws -> AbsolutePath {
681687
let path = self.tempsPath.appending("output-file-map.json")
682688
let masterDepsPath = self.tempsPath.appending("master.swiftdeps")

Tests/CommandsTests/BuildToolTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ final class BuildToolTests: CommandsTestCase {
150150
do {
151151
let result = try build(["--product", "exec1"], packagePath: fullPath)
152152
XCTAssertMatch(result.binContents, ["exec1"])
153-
XCTAssertNoMatch(result.binContents, ["exec2.build"])
153+
XCTAssertMatch(result.binContents, ["exec2.build"])
154154
}
155155

156156
do {
@@ -219,9 +219,9 @@ final class BuildToolTests: CommandsTestCase {
219219
do {
220220
let result = try build([], packagePath: aPath)
221221
XCTAssertNoMatch(result.binContents, ["bexec"])
222-
XCTAssertNoMatch(result.binContents, ["BTarget2.build"])
222+
XCTAssertMatch(result.binContents, ["BTarget2.build"])
223223
XCTAssertNoMatch(result.binContents, ["cexec"])
224-
XCTAssertNoMatch(result.binContents, ["CTarget.build"])
224+
XCTAssertMatch(result.binContents, ["CTarget.build"])
225225
}
226226

227227
// Dependency contains a dependent product
@@ -231,15 +231,15 @@ final class BuildToolTests: CommandsTestCase {
231231
XCTAssertMatch(result.binContents, ["BTarget2.build"])
232232
XCTAssertMatch(result.binContents, ["bexec"])
233233
XCTAssertNoMatch(result.binContents, ["aexec"])
234-
XCTAssertNoMatch(result.binContents, ["ATarget.build"])
234+
XCTAssertMatch(result.binContents, ["ATarget.build"])
235235
XCTAssertNoMatch(result.binContents, ["BLibrary.a"])
236236

237237
// FIXME: We create the modulemap during build planning, hence this uglyness.
238238
let bTargetBuildDir = ((try? localFileSystem.getDirectoryContents(result.binPath.appending("BTarget1.build"))) ?? []).filter{ $0 != moduleMapFilename }
239239
XCTAssertTrue(bTargetBuildDir.isEmpty, "bTargetBuildDir should be empty")
240240

241241
XCTAssertNoMatch(result.binContents, ["cexec"])
242-
XCTAssertNoMatch(result.binContents, ["CTarget.build"])
242+
XCTAssertMatch(result.binContents, ["CTarget.build"])
243243

244244
// Also make sure we didn't emit parseable module interfaces
245245
// (do this here to avoid doing a second build in

0 commit comments

Comments
 (0)