Skip to content

Commit 5fae1fd

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 3499bd1 commit 5fae1fd

File tree

3 files changed

+87
-27
lines changed

3 files changed

+87
-27
lines changed

Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift

Lines changed: 31 additions & 11 deletions
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,
@@ -391,18 +398,31 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
391398
/// inputs and command line flags.
392399
public mutating func resolveMainModuleDependencies(inputs: inout [TypedVirtualPath],
393400
commandLine: inout [Job.ArgTemplate]) throws {
394-
let mainModuleId: ModuleDependencyId = .swift(dependencyGraph.mainModuleName)
395-
396-
let mainModuleDetails = try dependencyGraph.swiftModuleDetails(of: mainModuleId)
397-
if let additionalArgs = mainModuleDetails.commandLine {
398-
additionalArgs.forEach { commandLine.appendFlag($0) }
401+
// If not previously computed, gather all dependency input files and command-line arguments
402+
if resolvedMainModuleDependenciesArgs == nil {
403+
var inputAdditions: [TypedVirtualPath] = []
404+
var commandLineAdditions: [Job.ArgTemplate] = []
405+
let mainModuleId: ModuleDependencyId = .swift(dependencyGraph.mainModuleName)
406+
let mainModuleDetails = try dependencyGraph.swiftModuleDetails(of: mainModuleId)
407+
if let additionalArgs = mainModuleDetails.commandLine {
408+
additionalArgs.forEach { commandLine.appendFlag($0) }
409+
}
410+
commandLineAdditions.appendFlags("-disable-implicit-swift-modules",
411+
"-Xcc", "-fno-implicit-modules",
412+
"-Xcc", "-fno-implicit-module-maps")
413+
try resolveExplicitModuleDependencies(moduleId: mainModuleId,
414+
inputs: &inputAdditions,
415+
commandLine: &commandLineAdditions)
416+
resolvedMainModuleDependenciesArgs = ResolvedModuleDependenciesCommandLineComponents(
417+
inputs: inputAdditions,
418+
commandLine: commandLineAdditions
419+
)
399420
}
400-
commandLine.appendFlags("-disable-implicit-swift-modules",
401-
"-Xcc", "-fno-implicit-modules",
402-
"-Xcc", "-fno-implicit-module-maps")
403-
try resolveExplicitModuleDependencies(moduleId: mainModuleId,
404-
inputs: &inputs,
405-
commandLine: &commandLine)
421+
guard let mainModuleDependenciesArgs = resolvedMainModuleDependenciesArgs else {
422+
fatalError("Failed to compute resolved explicit dependency arguments.")
423+
}
424+
inputs.append(contentsOf: mainModuleDependenciesArgs.inputs)
425+
commandLine.append(contentsOf: mainModuleDependenciesArgs.commandLine)
406426
}
407427

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

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 7 additions & 16 deletions
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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,55 @@ final class ExplicitModuleBuildTests: XCTestCase {
222222
}
223223
}
224224

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

0 commit comments

Comments
 (0)