Skip to content

Commit daaaa88

Browse files
committed
[Explicit Module Builds] Cache explicit dependency additions to main module command-lines
Cache input files and command-line argument additions describing main module explicit module dependencies to each individual job. Instead of re-computing them for each compile task, which includes serializing a whole new `.json` file with the inputs.
1 parent c283179 commit daaaa88

File tree

3 files changed

+87
-27
lines changed

3 files changed

+87
-27
lines changed

Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift

+31-11
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
5555
/// Does this compile support `.explicitInterfaceModuleBuild`
5656
private var supportsExplicitInterfaceBuild: Bool
5757

58+
/// Cached command-line additions for all main module compile jobs
59+
private struct ResolvedModuleDependenciesCommandLineComponents {
60+
let inputs: [TypedVirtualPath]
61+
let commandLine: [Job.ArgTemplate]
62+
}
63+
private var resolvedMainModuleDependenciesArgs: ResolvedModuleDependenciesCommandLineComponents? = nil
64+
5865
public init(dependencyGraph: InterModuleDependencyGraph,
5966
toolchain: Toolchain,
6067
dependencyOracle: InterModuleDependencyOracle,
@@ -396,18 +403,31 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
396403
/// inputs and command line flags.
397404
public mutating func resolveMainModuleDependencies(inputs: inout [TypedVirtualPath],
398405
commandLine: inout [Job.ArgTemplate]) throws {
399-
let mainModuleId: ModuleDependencyId = .swift(dependencyGraph.mainModuleName)
400-
401-
let mainModuleDetails = try dependencyGraph.swiftModuleDetails(of: mainModuleId)
402-
if let additionalArgs = mainModuleDetails.commandLine {
403-
additionalArgs.forEach { commandLine.appendFlag($0) }
406+
// If not previously computed, gather all dependency input files and command-line arguments
407+
if resolvedMainModuleDependenciesArgs == nil {
408+
var inputAdditions: [TypedVirtualPath] = []
409+
var commandLineAdditions: [Job.ArgTemplate] = []
410+
let mainModuleId: ModuleDependencyId = .swift(dependencyGraph.mainModuleName)
411+
let mainModuleDetails = try dependencyGraph.swiftModuleDetails(of: mainModuleId)
412+
if let additionalArgs = mainModuleDetails.commandLine {
413+
additionalArgs.forEach { commandLine.appendFlag($0) }
414+
}
415+
commandLineAdditions.appendFlags("-disable-implicit-swift-modules",
416+
"-Xcc", "-fno-implicit-modules",
417+
"-Xcc", "-fno-implicit-module-maps")
418+
try resolveExplicitModuleDependencies(moduleId: mainModuleId,
419+
inputs: &inputAdditions,
420+
commandLine: &commandLineAdditions)
421+
resolvedMainModuleDependenciesArgs = ResolvedModuleDependenciesCommandLineComponents(
422+
inputs: inputAdditions,
423+
commandLine: commandLineAdditions
424+
)
404425
}
405-
commandLine.appendFlags("-disable-implicit-swift-modules",
406-
"-Xcc", "-fno-implicit-modules",
407-
"-Xcc", "-fno-implicit-module-maps")
408-
try resolveExplicitModuleDependencies(moduleId: mainModuleId,
409-
inputs: &inputs,
410-
commandLine: &commandLine)
426+
guard let mainModuleDependenciesArgs = resolvedMainModuleDependenciesArgs else {
427+
fatalError("Failed to compute resolved explicit dependency arguments.")
428+
}
429+
inputs.append(contentsOf: mainModuleDependenciesArgs.inputs)
430+
commandLine.append(contentsOf: mainModuleDependenciesArgs.commandLine)
411431
}
412432

413433
/// Resolve all module dependencies of the main module and add them to the lists of

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

+7-16
Original file line numberDiff line numberDiff line change
@@ -736,30 +736,21 @@ extension Driver {
736736

737737
/// Adds all dependencies required for an explicit module build
738738
/// to inputs and command line arguments of a compile job.
739-
func addExplicitModuleBuildArguments(inputs: inout [TypedVirtualPath],
740-
commandLine: inout [Job.ArgTemplate]) throws {
741-
guard var dependencyPlanner = explicitDependencyBuildPlanner else {
742-
fatalError("No dependency planner in Explicit Module Build mode.")
743-
}
744-
try dependencyPlanner.resolveMainModuleDependencies(inputs: &inputs, commandLine: &commandLine)
739+
mutating func addExplicitModuleBuildArguments(inputs: inout [TypedVirtualPath],
740+
commandLine: inout [Job.ArgTemplate]) throws {
741+
try explicitDependencyBuildPlanner?.resolveMainModuleDependencies(inputs: &inputs, commandLine: &commandLine)
745742
}
746743

747744
/// Adds all dependencies required for an explicit module build of the bridging header
748745
/// to inputs and command line arguments of a compile job.
749-
func addExplicitPCHBuildArguments(inputs: inout [TypedVirtualPath],
750-
commandLine: inout [Job.ArgTemplate]) throws {
751-
guard var dependencyPlanner = explicitDependencyBuildPlanner else {
752-
fatalError("No dependency planner in Explicit Module Build mode.")
753-
}
754-
try dependencyPlanner.resolveBridgingHeaderDependencies(inputs: &inputs, commandLine: &commandLine)
746+
mutating func addExplicitPCHBuildArguments(inputs: inout [TypedVirtualPath],
747+
commandLine: inout [Job.ArgTemplate]) throws {
748+
try explicitDependencyBuildPlanner?.resolveBridgingHeaderDependencies(inputs: &inputs, commandLine: &commandLine)
755749
}
756750

757751
/// If explicit dependency planner supports creating bridging header pch command.
758752
public func supportsBridgingHeaderPCHCommand() throws -> Bool {
759-
guard let dependencyPlanner = explicitDependencyBuildPlanner else {
760-
return false
761-
}
762-
return try dependencyPlanner.supportsBridgingHeaderPCHCommand()
753+
return try explicitDependencyBuildPlanner?.supportsBridgingHeaderPCHCommand() ?? false
763754
}
764755

765756
/// In Explicit Module Build mode, distinguish between main module jobs and intermediate dependency build jobs,

Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift

+49
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,55 @@ final class ExplicitModuleBuildTests: XCTestCase {
230230
}
231231
}
232232

233+
func testModuleDependencyBuildCommandUniqueDepFile() throws {
234+
try withTemporaryDirectory { path in
235+
let source0 = path.appending(component: "testModuleDependencyBuildCommandUniqueDepFile1.swift")
236+
let source1 = path.appending(component: "testModuleDependencyBuildCommandUniqueDepFile2.swift")
237+
try localFileSystem.writeFileContents(source0, bytes:
238+
"""
239+
import C;
240+
"""
241+
)
242+
try localFileSystem.writeFileContents(source1, bytes:
243+
"""
244+
import G;
245+
"""
246+
)
247+
248+
let cHeadersPath: AbsolutePath =
249+
try testInputsPath.appending(component: "ExplicitModuleBuilds")
250+
.appending(component: "CHeaders")
251+
let bridgingHeaderpath: AbsolutePath =
252+
cHeadersPath.appending(component: "Bridging.h")
253+
let swiftModuleInterfacesPath: AbsolutePath =
254+
try testInputsPath.appending(component: "ExplicitModuleBuilds")
255+
.appending(component: "Swift")
256+
let sdkArgumentsForTesting = (try? Driver.sdkArgumentsForTesting()) ?? []
257+
var driver = try Driver(args: ["swiftc",
258+
"-target", "x86_64-apple-macosx11.0",
259+
"-I", cHeadersPath.nativePathString(escaped: true),
260+
"-I", swiftModuleInterfacesPath.nativePathString(escaped: true),
261+
"-explicit-module-build",
262+
"-import-objc-header", bridgingHeaderpath.nativePathString(escaped: true),
263+
source0.nativePathString(escaped: true),
264+
source1.nativePathString(escaped: true)] + sdkArgumentsForTesting)
265+
266+
let jobs = try driver.planBuild()
267+
let compileJobs = jobs.filter({ $0.kind == .compile })
268+
XCTAssertEqual(compileJobs.count, 2)
269+
let compileJob0 = compileJobs[0]
270+
let compileJob1 = compileJobs[1]
271+
let explicitDepsFlag = SwiftDriver.Job.ArgTemplate.flag(String("-explicit-swift-module-map-file"))
272+
XCTAssert(compileJob0.commandLine.contains(explicitDepsFlag))
273+
XCTAssert(compileJob1.commandLine.contains(explicitDepsFlag))
274+
let jsonDeps0PathIndex = compileJob0.commandLine.firstIndex(of: explicitDepsFlag)
275+
let jsonDeps0PathArg = compileJob0.commandLine[jsonDeps0PathIndex! + 1]
276+
let jsonDeps1PathIndex = compileJob1.commandLine.firstIndex(of: explicitDepsFlag)
277+
let jsonDeps1PathArg = compileJob1.commandLine[jsonDeps1PathIndex! + 1]
278+
XCTAssertEqual(jsonDeps0PathArg, jsonDeps1PathArg)
279+
}
280+
}
281+
233282
private func pathMatchesSwiftModule(path: VirtualPath, _ name: String) -> Bool {
234283
return path.basenameWithoutExt.starts(with: "\(name)-") &&
235284
path.extension! == FileType.swiftModule.rawValue

0 commit comments

Comments
 (0)