Skip to content

Commit 706d1f1

Browse files
authored
Stop using llbuild's Swift compiler tool (#6585)
This allows us to take control of these compiler invocations and is a first step towards unifying all the various ways of generating compiler arguments that are currently in `SwiftTargetBuildDescription`. This PR aims to keep the behavior of the existing tool as far as possible, the only known differences are single quotes instead of double for arguments with spaces and the fact that the output file map will be created eagerly. resolves #6575
1 parent 80dfa98 commit 706d1f1

File tree

6 files changed

+55
-25
lines changed

6 files changed

+55
-25
lines changed

IntegrationTests/Tests/IntegrationTests/BasicTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ final class BasicTests: XCTestCase {
215215

216216
// Check the build.
217217
let buildOutput = try sh(swiftBuild, "--package-path", packagePath, "-v").stdout
218-
XCTAssertMatch(buildOutput, .regex(#"swiftc.* -module-name special_tool .* ".*/more spaces/special tool/some file.swift""#))
218+
XCTAssertMatch(buildOutput, .regex(#"swiftc.* -module-name special_tool .* '.*/more spaces/special tool/some file.swift'"#))
219219
XCTAssertMatch(buildOutput, .contains("Build complete"))
220220

221221
// Verify that the tool exists and works.

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ public final class SwiftTargetBuildDescription {
689689
self.buildParameters.triple.isDarwin() && self.target.type == .library
690690
}
691691

692-
private func writeOutputFileMap() throws -> AbsolutePath {
692+
func writeOutputFileMap() throws -> AbsolutePath {
693693
let path = self.tempsPath.appending("output-file-map.json")
694694
let masterDepsPath = self.tempsPath.appending("master.swiftdeps")
695695

Sources/Build/LLBuildManifestBuilder.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,8 @@ extension LLBuildManifestBuilder {
628628
otherArguments: try target.compileArguments(),
629629
sources: target.sources,
630630
isLibrary: isLibrary,
631-
wholeModuleOptimization: self.buildParameters.configuration == .release
631+
wholeModuleOptimization: self.buildParameters.configuration == .release,
632+
outputFileMapPath: try target.writeOutputFileMap() // FIXME: Eliminate side effect.
632633
)
633634
}
634635

Sources/LLBuildManifest/BuildManifest.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ public struct BuildManifest {
173173
otherArguments: [String],
174174
sources: [AbsolutePath],
175175
isLibrary: Bool,
176-
wholeModuleOptimization: Bool
176+
wholeModuleOptimization: Bool,
177+
outputFileMapPath: AbsolutePath
177178
) {
178179
assert(commands[name] == nil, "already had a command named '\(name)'")
179180
let tool = SwiftCompilerTool(
@@ -189,7 +190,8 @@ public struct BuildManifest {
189190
otherArguments: otherArguments,
190191
sources: sources,
191192
isLibrary: isLibrary,
192-
wholeModuleOptimization: wholeModuleOptimization
193+
wholeModuleOptimization: wholeModuleOptimization,
194+
outputFileMapPath: outputFileMapPath
193195
)
194196
commands[name] = Command(name: name, tool: tool)
195197
}

Sources/LLBuildManifest/Tools.swift

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public struct SwiftFrontendTool: ToolProtocol {
226226

227227
/// Swift compiler llbuild tool.
228228
public struct SwiftCompilerTool: ToolProtocol {
229-
public static let name: String = "swift-compiler"
229+
public static let name: String = "shell"
230230

231231
public static let numThreads: Int = ProcessInfo.processInfo.activeProcessorCount
232232

@@ -244,6 +244,7 @@ public struct SwiftCompilerTool: ToolProtocol {
244244
public var sources: [AbsolutePath]
245245
public var isLibrary: Bool
246246
public var wholeModuleOptimization: Bool
247+
public var outputFileMapPath: AbsolutePath
247248

248249
init(
249250
inputs: [Node],
@@ -258,7 +259,8 @@ public struct SwiftCompilerTool: ToolProtocol {
258259
otherArguments: [String],
259260
sources: [AbsolutePath],
260261
isLibrary: Bool,
261-
wholeModuleOptimization: Bool
262+
wholeModuleOptimization: Bool,
263+
outputFileMapPath: AbsolutePath
262264
) {
263265
self.inputs = inputs
264266
self.outputs = outputs
@@ -273,24 +275,43 @@ public struct SwiftCompilerTool: ToolProtocol {
273275
self.sources = sources
274276
self.isLibrary = isLibrary
275277
self.wholeModuleOptimization = wholeModuleOptimization
278+
self.outputFileMapPath = outputFileMapPath
276279
}
277280

278-
public func write(to stream: ManifestToolStream) {
279-
stream["executable"] = executable
280-
stream["module-name"] = moduleName
281-
if let moduleAliases {
282-
// Format the key and value to pass to -module-alias flag
283-
let formatted = moduleAliases.map {$0.key + "=" + $0.value}
284-
stream["module-aliases"] = formatted
281+
var description: String {
282+
return "Compiling Swift Module '\(moduleName)' (\(sources.count) sources)"
283+
}
284+
285+
var arguments: [String] {
286+
var arguments = [
287+
executable.pathString,
288+
"-module-name", moduleName,
289+
]
290+
if let moduleAliases = moduleAliases {
291+
for (original, alias) in moduleAliases {
292+
arguments += ["-module-alias", "\(original)=\(alias)"]
293+
}
294+
}
295+
arguments += [
296+
"-incremental",
297+
"-emit-dependencies",
298+
"-emit-module",
299+
"-emit-module-path", moduleOutputPath.pathString,
300+
"-output-file-map", outputFileMapPath.pathString,
301+
]
302+
if isLibrary {
303+
arguments += ["-parse-as-library"]
285304
}
286-
stream["module-output-path"] = moduleOutputPath
287-
stream["import-paths"] = [importPath]
288-
stream["temps-path"] = tempsPath
289-
stream["objects"] = objects
290-
stream["other-args"] = otherArguments
291-
stream["sources"] = sources
292-
stream["is-library"] = isLibrary
293-
stream["enable-whole-module-optimization"] = wholeModuleOptimization
294-
stream["num-threads"] = Self.numThreads
295-
}
305+
if wholeModuleOptimization {
306+
arguments += ["-whole-module-optimization", "-num-threads", "\(Self.numThreads)"]
307+
}
308+
arguments += ["-c"] + sources.map { $0.pathString }
309+
arguments += ["-I", importPath.pathString]
310+
arguments += otherArguments
311+
return arguments
312+
}
313+
314+
public func write(to stream: ManifestToolStream) {
315+
ShellTool(description: description, inputs: inputs, outputs: outputs, arguments: arguments).write(to: stream)
316+
}
296317
}

Tests/CommandsTests/BuildToolTests.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ final class BuildToolTests: CommandsTestCase {
4141
defer { try! SwiftPM.Package.execute(["clean"], packagePath: packagePath) }
4242
let (binPathOutput, _) = try execute(["--show-bin-path"], packagePath: packagePath)
4343
let binPath = try AbsolutePath(validating: binPathOutput.trimmingCharacters(in: .whitespacesAndNewlines))
44-
let binContents = try localFileSystem.getDirectoryContents(binPath)
44+
let binContents = try localFileSystem.getDirectoryContents(binPath).filter {
45+
guard let contents = try? localFileSystem.getDirectoryContents(binPath.appending(component: $0)) else {
46+
return true
47+
}
48+
// Filter directories which only contain an output file map since we didn't build anything for those which is what `binContents` is meant to represent.
49+
return contents != ["output-file-map.json"]
50+
}
4551
return BuildResult(binPath: binPath, output: output, binContents: binContents)
4652
}
4753

0 commit comments

Comments
 (0)