Skip to content

Commit c6b9336

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. Fixes: #6402
1 parent ee7f064 commit c6b9336

File tree

5 files changed

+59
-12
lines changed

5 files changed

+59
-12
lines changed

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ public final class SwiftTargetBuildDescription {
7474
self.target.sources.paths + self.derivedSources.paths + self.pluginDerivedSources.paths
7575
}
7676

77+
public var sourcesFileListPath: AbsolutePath {
78+
self.tempsPath.appending(component: "sources")
79+
}
80+
7781
/// The list of all resource files in the target, including the derived ones.
7882
public var resources: [Resource] {
7983
self.target.underlyingTarget.resources + self.pluginDerivedResources

Sources/Build/LLBuildManifestBuilder.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,10 @@ extension LLBuildManifestBuilder {
614614
let isLibrary = target.target.type == .library || target.target.type == .test
615615
let cmdName = target.target.getCommandName(config: self.buildConfig)
616616

617+
self.manifest.addWriteSourcesFileListCommand(sources: target.sources, sourcesFileListPath: target.sourcesFileListPath)
617618
self.manifest.addSwiftCmd(
618619
name: cmdName,
619-
inputs: inputs,
620+
inputs: inputs + [Node.file(target.sourcesFileListPath)],
620621
outputs: cmdOutputs,
621622
executable: self.buildParameters.toolchain.swiftCompilerPath,
622623
moduleName: target.target.c99name,
@@ -627,6 +628,7 @@ extension LLBuildManifestBuilder {
627628
objects: try target.objects,
628629
otherArguments: try target.compileArguments(),
629630
sources: target.sources,
631+
fileList: target.sourcesFileListPath,
630632
isLibrary: isLibrary,
631633
wholeModuleOptimization: self.buildParameters.configuration == .release,
632634
outputFileMapPath: try target.writeOutputFileMap() // FIXME: Eliminate side effect.

Sources/LLBuildManifest/BuildManifest.swift

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public protocol AuxiliaryFileType {
1919
}
2020

2121
public enum WriteAuxiliary {
22-
public static let fileTypes: [AuxiliaryFileType.Type] = [LinkFileList.self]
22+
public static let fileTypes: [AuxiliaryFileType.Type] = [LinkFileList.self, SourcesFileList.self]
2323

2424
public struct LinkFileList: AuxiliaryFileType {
2525
public static let name = "link-file-list"
@@ -50,6 +50,32 @@ public enum WriteAuxiliary {
5050
return content
5151
}
5252
}
53+
54+
public struct SourcesFileList: AuxiliaryFileType {
55+
public static let name = "sources-file-list"
56+
57+
public static func computeInputs(sources: [AbsolutePath]) -> [Node] {
58+
return [.virtual(Self.name)] + sources.map { Node.file($0) }
59+
}
60+
61+
public static func getFileContents(inputs: [Node]) throws -> String {
62+
let sources = inputs.compactMap {
63+
if $0.kind == .file {
64+
return $0.name
65+
} else {
66+
return nil
67+
}
68+
}
69+
70+
guard sources.count > 0 else { return "" }
71+
72+
var contents = sources
73+
.map { $0.spm_shellEscaped() }
74+
.joined(separator: "\n")
75+
contents.append("\n")
76+
return contents
77+
}
78+
}
5379
}
5480

5581
public struct BuildManifest {
@@ -137,6 +163,16 @@ public struct BuildManifest {
137163
commands[name] = Command(name: name, tool: tool)
138164
}
139165

166+
public mutating func addWriteSourcesFileListCommand(
167+
sources: [AbsolutePath],
168+
sourcesFileListPath: AbsolutePath
169+
) {
170+
let inputs = WriteAuxiliary.SourcesFileList.computeInputs(sources: sources)
171+
let tool = WriteAuxiliaryFile(inputs: inputs, outputFilePath: sourcesFileListPath)
172+
let name = sourcesFileListPath.pathString
173+
commands[name] = Command(name: name, tool: tool)
174+
}
175+
140176
public mutating func addPkgStructureCmd(
141177
name: String,
142178
inputs: [Node],
@@ -222,6 +258,7 @@ public struct BuildManifest {
222258
objects: [AbsolutePath],
223259
otherArguments: [String],
224260
sources: [AbsolutePath],
261+
fileList: AbsolutePath,
225262
isLibrary: Bool,
226263
wholeModuleOptimization: Bool,
227264
outputFileMapPath: AbsolutePath
@@ -239,6 +276,7 @@ public struct BuildManifest {
239276
objects: objects,
240277
otherArguments: otherArguments,
241278
sources: sources,
279+
fileList: fileList,
242280
isLibrary: isLibrary,
243281
wholeModuleOptimization: wholeModuleOptimization,
244282
outputFileMapPath: outputFileMapPath

Sources/LLBuildManifest/Tools.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ public struct SwiftCompilerTool: ToolProtocol {
262262
public var objects: [AbsolutePath]
263263
public var otherArguments: [String]
264264
public var sources: [AbsolutePath]
265+
public var fileList: AbsolutePath
265266
public var isLibrary: Bool
266267
public var wholeModuleOptimization: Bool
267268
public var outputFileMapPath: AbsolutePath
@@ -278,6 +279,7 @@ public struct SwiftCompilerTool: ToolProtocol {
278279
objects: [AbsolutePath],
279280
otherArguments: [String],
280281
sources: [AbsolutePath],
282+
fileList: AbsolutePath,
281283
isLibrary: Bool,
282284
wholeModuleOptimization: Bool,
283285
outputFileMapPath: AbsolutePath
@@ -293,6 +295,7 @@ public struct SwiftCompilerTool: ToolProtocol {
293295
self.objects = objects
294296
self.otherArguments = otherArguments
295297
self.sources = sources
298+
self.fileList = fileList
296299
self.isLibrary = isLibrary
297300
self.wholeModuleOptimization = wholeModuleOptimization
298301
self.outputFileMapPath = outputFileMapPath
@@ -325,7 +328,7 @@ public struct SwiftCompilerTool: ToolProtocol {
325328
if wholeModuleOptimization {
326329
arguments += ["-whole-module-optimization", "-num-threads", "\(Self.numThreads)"]
327330
}
328-
arguments += ["-c"] + sources.map { $0.pathString }
331+
arguments += ["-c", "@\(self.fileList.pathString)"]
329332
arguments += ["-I", importPath.pathString]
330333
arguments += otherArguments
331334
return arguments

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ final class BuildPlanTests: XCTestCase {
877877
try llbuild.generateManifest(at: yaml)
878878
let contents: String = try fs.readFileContents(yaml)
879879
XCTAssertMatch(contents, .contains("""
880-
inputs: ["\(Pkg.appending(components: "Sources", "exe", "main.swift").escapedPathString())","\(buildPath.appending(components: "PkgLib.swiftmodule").escapedPathString())"]
880+
inputs: ["\(Pkg.appending(components: "Sources", "exe", "main.swift").escapedPathString())","\(buildPath.appending(components: "PkgLib.swiftmodule").escapedPathString())","\(buildPath.appending(components: "exe.build", "sources").escapedPathString())"]
881881
"""))
882882

883883
}
@@ -904,8 +904,9 @@ final class BuildPlanTests: XCTestCase {
904904
let llbuild = LLBuildManifestBuilder(plan, fileSystem: fs, observabilityScope: observability.topScope)
905905
try llbuild.generateManifest(at: yaml)
906906
let contents: String = try fs.readFileContents(yaml)
907+
let buildPath = plan.buildParameters.dataPath.appending(components: "debug")
907908
XCTAssertMatch(contents, .contains("""
908-
inputs: ["\(Pkg.appending(components: "Sources", "exe", "main.swift").escapedPathString())"]
909+
inputs: ["\(Pkg.appending(components: "Sources", "exe", "main.swift").escapedPathString())","\(buildPath.appending(components: "exe.build", "sources").escapedPathString())"]
909910
"""))
910911
}
911912
}
@@ -3722,17 +3723,16 @@ final class BuildPlanTests: XCTestCase {
37223723
let llbuild = LLBuildManifestBuilder(plan, fileSystem: fs, observabilityScope: observability.topScope)
37233724
try llbuild.generateManifest(at: yaml)
37243725
let contents: String = try fs.readFileContents(yaml)
3726+
37253727
#if os(Windows)
3728+
let suffix = ".exe"
3729+
#else // FIXME(5472) - the suffix is dropped
3730+
let suffix = ""
3731+
#endif
37263732
XCTAssertMatch(contents, .contains("""
3727-
inputs: ["\(PkgA.appending(components: "Sources", "swiftlib", "lib.swift").escapedPathString())","\(buildPath.appending(components: "exe.exe").escapedPathString())"]
3728-
outputs: ["\(buildPath.appending(components: "swiftlib.build", "lib.swift.o").escapedPathString())","\(buildPath.escapedPathString())
3729-
"""))
3730-
#else // FIXME(5472) - the suffix is dropped
3731-
XCTAssertMatch(contents, .contains("""
3732-
inputs: ["\(PkgA.appending(components: "Sources", "swiftlib", "lib.swift").escapedPathString())","\(buildPath.appending(components: "exe").escapedPathString())"]
3733+
inputs: ["\(PkgA.appending(components: "Sources", "swiftlib", "lib.swift").escapedPathString())","\(buildPath.appending(components: "exe\(suffix)").escapedPathString())","\(buildPath.appending(components: "swiftlib.build", "sources").escapedPathString())"]
37333734
outputs: ["\(buildPath.appending(components: "swiftlib.build", "lib.swift.o").escapedPathString())","\(buildPath.escapedPathString())
37343735
"""))
3735-
#endif
37363736
}
37373737

37383738
func testObjCHeader1() throws {

0 commit comments

Comments
 (0)