Skip to content

Commit fb654e2

Browse files
committed
Stop using llbuild's Swift compiler tool
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 c56e1ee commit fb654e2

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
@@ -677,7 +677,7 @@ public final class SwiftTargetBuildDescription {
677677
self.buildParameters.triple.isDarwin() && self.target.type == .library
678678
}
679679

680-
private func writeOutputFileMap() throws -> AbsolutePath {
680+
func writeOutputFileMap() throws -> AbsolutePath {
681681
let path = self.tempsPath.appending("output-file-map.json")
682682
let masterDepsPath = self.tempsPath.appending("master.swiftdeps")
683683

Sources/Build/LLBuildManifestBuilder.swift

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

Sources/LLBuildManifest/BuildManifest.swift

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

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)