Skip to content

Commit f0edadd

Browse files
committed
[Explicit Module Builds] Revert the explicit dependency build planner to operate on dependency graphs instead of querying the oracle
1 parent e9e96d2 commit f0edadd

File tree

5 files changed

+75
-77
lines changed

5 files changed

+75
-77
lines changed

Sources/SwiftDriver/Explicit Module Builds/ClangVersionedDependencyResolution.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ internal extension Driver {
6565
}
6666
}
6767

68-
/// Resolution of versioned clang dependencies.
69-
/// FIXME: This code currently operates on instances of InterModuleDependencyGraph,
70-
/// It should be transitioned to operate on an instance of an InterModuleDependencyOracle.
7168
private extension InterModuleDependencyGraph {
7269
/// For each module scanned at multiple target versions, combine their dependencies across version-specific graphs.
7370
mutating func resolveVersionedClangModules(using versionedGraphMap: ModuleVersionedGraphMap)

Sources/SwiftDriver/Explicit Module Builds/ExplicitDependencyBuildPlanner.swift

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,8 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
2323
/// build jobs for all module dependencies and providing compile command options
2424
/// that specify said explicit module dependencies.
2525
@_spi(Testing) public struct ExplicitDependencyBuildPlanner {
26-
/// The module ID of the main module for the current target
27-
public let mainModuleId: ModuleDependencyId
28-
29-
/// The module dependency oracle.
30-
public let dependencyOracle: InterModuleDependencyOracle
26+
/// The module dependency graph.
27+
public var dependencyGraph: InterModuleDependencyGraph
3128

3229
/// Cache Clang modules for which a build job has already been constructed with a given
3330
/// target triple.
@@ -39,11 +36,9 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
3936
/// The toolchain to be used for frontend job generation.
4037
private let toolchain: Toolchain
4138

42-
public init(mainModuleId: ModuleDependencyId,
43-
dependencyOracle: InterModuleDependencyOracle,
39+
public init(dependencyGraph: InterModuleDependencyGraph,
4440
toolchain: Toolchain) throws {
45-
self.mainModuleId = mainModuleId
46-
self.dependencyOracle = dependencyOracle
41+
self.dependencyGraph = dependencyGraph
4742
self.toolchain = toolchain
4843
}
4944

@@ -121,9 +116,9 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
121116
/// inputs and command line flags.
122117
mutating public func resolveMainModuleDependencies(inputs: inout [TypedVirtualPath],
123118
commandLine: inout [Job.ArgTemplate]) throws {
119+
let mainModuleId: ModuleDependencyId = .swift(dependencyGraph.mainModuleName)
124120
try resolveExplicitModuleDependencies(moduleId: mainModuleId,
125-
pcmArgs:
126-
try dependencyOracle.getSwiftModulePCMArgs(of: mainModuleId),
121+
pcmArgs: try dependencyGraph.swiftModulePCMArgs(of: mainModuleId),
127122
inputs: &inputs,
128123
commandLine: &commandLine)
129124
}
@@ -132,23 +127,20 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
132127
/// Resolving a module's dependencies will ensure that the dependencies' build jobs are also
133128
/// generated.
134129
mutating private func genSwiftModuleBuildJob(moduleId: ModuleDependencyId) throws {
135-
guard let moduleInfo = dependencyOracle.getModuleInfo(of: moduleId) else {
136-
throw Driver.Error.missingModuleDependency(moduleId.moduleName)
137-
}
130+
let moduleInfo = try dependencyGraph.moduleInfo(of: moduleId)
138131
var inputs: [TypedVirtualPath] = []
139132
let outputs: [TypedVirtualPath] = [
140133
TypedVirtualPath(file: try VirtualPath(path: moduleInfo.modulePath), type: .swiftModule)
141134
]
142135
var commandLine: [Job.ArgTemplate] = []
143136

144137
// First, take the command line options provided in the dependency information
145-
let moduleDetails = try dependencyOracle.getSwiftModuleDetails(of: moduleId)
138+
let moduleDetails = try dependencyGraph.swiftModuleDetails(of: moduleId)
146139
moduleDetails.commandLine?.forEach { commandLine.appendFlags($0) }
147140

148141
// Resolve all dependency module inputs for this Swift module
149142
try resolveExplicitModuleDependencies(moduleId: moduleId,
150-
pcmArgs:
151-
dependencyOracle.getSwiftModulePCMArgs(of: moduleId),
143+
pcmArgs: dependencyGraph.swiftModulePCMArgs(of: moduleId),
152144
inputs: &inputs, commandLine: &commandLine)
153145

154146
// Build the .swiftinterfaces file using a list of command line options specified in the
@@ -191,15 +183,13 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
191183
/// generated.
192184
mutating private func genClangModuleBuildJob(moduleId: ModuleDependencyId,
193185
pcmArgs: [String]) throws {
194-
guard let moduleInfo = dependencyOracle.getModuleInfo(of: moduleId) else {
195-
throw Driver.Error.missingModuleDependency(moduleId.moduleName)
196-
}
186+
let moduleInfo = try dependencyGraph.moduleInfo(of: moduleId)
197187
var inputs: [TypedVirtualPath] = []
198188
var outputs: [TypedVirtualPath] = []
199189
var commandLine: [Job.ArgTemplate] = []
200190

201191
// First, take the command line options provided in the dependency information
202-
let moduleDetails = try dependencyOracle.getClangModuleDetails(of: moduleId)
192+
let moduleDetails = try dependencyGraph.clangModuleDetails(of: moduleId)
203193
moduleDetails.commandLine.forEach { commandLine.appendFlags($0) }
204194

205195
// Add the `-target` option as inherited from the dependent Swift module's PCM args
@@ -305,7 +295,7 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
305295
clangDependencyArtifacts: inout [ClangModuleArtifactInfo],
306296
swiftDependencyArtifacts: inout [SwiftModuleArtifactInfo]
307297
) throws {
308-
for dependencyId in dependencyOracle.getDependencies(of: moduleId)! {
298+
for dependencyId in try dependencyGraph.moduleInfo(of: moduleId).directDependencies! {
309299
guard addedDependenciesSet.insert(dependencyId).inserted else {
310300
continue
311301
}
@@ -346,9 +336,7 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
346336
swiftDependencyArtifacts: inout [SwiftModuleArtifactInfo]
347337
) throws {
348338
// Add it as an explicit dependency
349-
guard let dependencyInfo = dependencyOracle.getModuleInfo(of: dependencyId) else {
350-
throw Driver.Error.missingModuleDependency(moduleId.moduleName)
351-
}
339+
let dependencyInfo = try dependencyGraph.moduleInfo(of: dependencyId)
352340
let swiftModulePath: TypedVirtualPath
353341
let isFramework: Bool
354342

@@ -359,7 +347,7 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
359347
}
360348
swiftModulePath = .init(file: try VirtualPath(path: dependencyInfo.modulePath),
361349
type: .swiftModule)
362-
isFramework = try dependencyOracle.getSwiftModuleDetails(of: dependencyId).isFramework
350+
isFramework = try dependencyGraph.swiftModuleDetails(of: dependencyId).isFramework
363351

364352
// Collect the required information about this module
365353
// TODO: add .swiftdoc and .swiftsourceinfo for this module.
@@ -393,10 +381,8 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
393381
}
394382

395383
// Add it as an explicit dependency
396-
guard let dependencyInfo = dependencyOracle.getModuleInfo(of: dependencyId) else {
397-
throw Driver.Error.missingModuleDependency(moduleId.moduleName)
398-
}
399-
let dependencyClangModuleDetails = try dependencyOracle.getClangModuleDetails(of: dependencyId)
384+
let dependencyInfo = try dependencyGraph.moduleInfo(of: dependencyId)
385+
let dependencyClangModuleDetails = try dependencyGraph.clangModuleDetails(of: dependencyId)
400386
let clangModulePath =
401387
try ExplicitDependencyBuildPlanner.targetEncodedClangModuleFilePath(for: dependencyInfo,
402388
pcmArgs: pcmArgs)
@@ -423,8 +409,9 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
423409
swiftDependencyArtifacts: inout [SwiftModuleArtifactInfo]
424410
) throws {
425411
// Add it as an explicit dependency
426-
let compiledModulePath =
427-
try dependencyOracle.getSwiftPrebuiltDetails(of: dependencyId).compiledModulePath
412+
let compiledModulePath = try dependencyGraph
413+
.swiftPrebuiltDetails(of: dependencyId)
414+
.compiledModulePath
428415
let swiftModulePath: TypedVirtualPath = .init(file: try VirtualPath(path: compiledModulePath),
429416
type: .swiftModule)
430417

@@ -470,33 +457,50 @@ extension ExplicitDependencyBuildPlanner {
470457

471458
/// Encapsulates some of the common queries of the ExplicitDependencyBuildPlanner with error-checking
472459
/// on the dependency graph's structure.
473-
internal extension InterModuleDependencyOracle {
474-
func getSwiftModuleDetails(of moduleId: ModuleDependencyId) throws -> SwiftModuleDetails {
475-
guard case .swift(let swiftModuleDetails) = getModuleInfo(of: moduleId)?.details else {
460+
internal extension InterModuleDependencyGraph {
461+
func moduleInfo(of moduleId: ModuleDependencyId) throws -> ModuleInfo {
462+
guard let moduleInfo = modules[moduleId] else {
463+
throw Driver.Error.missingModuleDependency(moduleId.moduleName)
464+
}
465+
return moduleInfo
466+
}
467+
468+
func swiftModuleDetails(of moduleId: ModuleDependencyId) throws -> SwiftModuleDetails {
469+
guard case .swift(let swiftModuleDetails) = try moduleInfo(of: moduleId).details else {
476470
throw Driver.Error.malformedModuleDependency(moduleId.moduleName, "no Swift `details` object")
477471
}
478472
return swiftModuleDetails
479473
}
480474

481-
func getSwiftPrebuiltDetails(of moduleId: ModuleDependencyId)
475+
func swiftPrebuiltDetails(of moduleId: ModuleDependencyId)
482476
throws -> SwiftPrebuiltExternalModuleDetails {
483477
guard case .swiftPrebuiltExternal(let prebuiltModuleDetails) =
484-
getModuleInfo(of: moduleId)?.details else {
478+
try moduleInfo(of: moduleId).details else {
485479
throw Driver.Error.malformedModuleDependency(moduleId.moduleName,
486480
"no SwiftPrebuiltExternal `details` object")
487481
}
488482
return prebuiltModuleDetails
489483
}
490484

491-
func getClangModuleDetails(of moduleId: ModuleDependencyId) throws -> ClangModuleDetails {
492-
guard case .clang(let clangModuleDetails) = getModuleInfo(of: moduleId)?.details else {
485+
func clangModuleDetails(of moduleId: ModuleDependencyId) throws -> ClangModuleDetails {
486+
guard case .clang(let clangModuleDetails) = try moduleInfo(of: moduleId).details else {
493487
throw Driver.Error.malformedModuleDependency(moduleId.moduleName, "no Clang `details` object")
494488
}
495489
return clangModuleDetails
496490
}
497491

498-
func getSwiftModulePCMArgs(of moduleId: ModuleDependencyId) throws -> [String] {
499-
let moduleDetails = try getSwiftModuleDetails(of: moduleId)
492+
func swiftModulePCMArgs(of moduleId: ModuleDependencyId) throws -> [String] {
493+
let moduleDetails = try swiftModuleDetails(of: moduleId)
500494
return moduleDetails.extraPcmArgs
501495
}
502496
}
497+
498+
// InterModuleDependencyGraph printing, useful for debugging
499+
internal extension InterModuleDependencyGraph {
500+
func prettyPrintString() throws -> String {
501+
let encoder = JSONEncoder()
502+
encoder.outputFormatting = [.prettyPrinted]
503+
let contents = try encoder.encode(self)
504+
return String(data: contents, encoding: .utf8)!
505+
}
506+
}

Sources/SwiftDriver/Explicit Module Builds/Inter Module Dependencies/CommonDependencyOperations.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
}
2121
}
2222

23-
// This is a backwards-compatibility shim
2423
public extension InterModuleDependencyGraph {
2524
// This is a shim for backwards-compatibility with existing API used by SwiftPM.
2625
// TODO: After SwiftPM switches to using the oracle, this should be deleted.

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,18 +372,17 @@ extension Driver {
372372
/// by re-scanning all Clang modules against all possible targets they will be built against.
373373
public mutating func generateExplicitModuleDependenciesJobs() throws -> [Job] {
374374
// Run the dependency scanner and update the dependency oracle with the results
375-
try gatherModuleDependencies(into: interModuleDependencyOracle)
375+
let dependencyGraph = try gatherModuleDependencies(into: interModuleDependencyOracle)
376376

377377
// Plan build jobs for all direct and transitive module dependencies of the current target
378378
explicitDependencyBuildPlanner =
379-
try ExplicitDependencyBuildPlanner(mainModuleId: .swift(moduleOutputInfo.name),
380-
dependencyOracle: interModuleDependencyOracle,
379+
try ExplicitDependencyBuildPlanner(dependencyGraph: dependencyGraph,
381380
toolchain: toolchain)
382381
return try explicitDependencyBuildPlanner!.generateExplicitModuleDependenciesBuildJobs()
383382
}
384383

385384
private mutating func gatherModuleDependencies(into dependencyOracle: InterModuleDependencyOracle)
386-
throws {
385+
throws -> InterModuleDependencyGraph {
387386
let dependencyScannerJob = try dependencyScanningJob()
388387
let forceResponseFiles = parsedOptions.hasArgument(.driverForceResponseFiles)
389388

@@ -407,6 +406,8 @@ extension Driver {
407406

408407
// Update the dependency oracle, adding this new dependency graph to its store
409408
try dependencyOracle.mergeModules(from: dependencyGraph)
409+
410+
return dependencyGraph
410411
}
411412

412413
/// Update the given inter-module dependency graph to set module paths to be within the module cache,

Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
162162
let dependencyOracle = InterModuleDependencyOracle()
163163
try dependencyOracle.mergeModules(from: moduleDependencyGraph)
164164
driver.explicitDependencyBuildPlanner =
165-
try ExplicitDependencyBuildPlanner(mainModuleId:
166-
.swift("test"),
167-
dependencyOracle: dependencyOracle,
165+
try ExplicitDependencyBuildPlanner(dependencyGraph: moduleDependencyGraph,
168166
toolchain: driver.toolchain)
169167
let modulePrebuildJobs =
170168
try driver.explicitDependencyBuildPlanner!.generateExplicitModuleDependenciesBuildJobs()
@@ -243,8 +241,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
243241
// Merge the resolved version of the graph into the oracle
244242
try dependencyOracle.mergeModules(from: moduleDependencyGraph)
245243
driver.explicitDependencyBuildPlanner =
246-
try ExplicitDependencyBuildPlanner(mainModuleId: .swift("A"),
247-
dependencyOracle: dependencyOracle,
244+
try ExplicitDependencyBuildPlanner(dependencyGraph: moduleDependencyGraph,
248245
toolchain: driver.toolchain)
249246
let modulePrebuildJobs =
250247
try driver.explicitDependencyBuildPlanner!.generateExplicitModuleDependenciesBuildJobs()
@@ -411,29 +408,29 @@ final class ExplicitModuleBuildTests: XCTestCase {
411408
}
412409

413410
func testDependencyGraphMerge() throws {
414-
// let moduleDependencyGraph1 =
415-
// try JSONDecoder().decode(
416-
// InterModuleDependencyGraph.self,
417-
// from: ModuleDependenciesInputs.mergeGraphInput1.data(using: .utf8)!)
418-
// let moduleDependencyGraph2 =
419-
// try JSONDecoder().decode(
420-
// InterModuleDependencyGraph.self,
421-
// from: ModuleDependenciesInputs.mergeGraphInput2.data(using: .utf8)!)
422-
//
423-
// var accumulatingModuleInfoMap: [ModuleDependencyId: ModuleInfo] = [:]
424-
//
425-
// try InterModuleDependencyGraph.mergeModules(from: moduleDependencyGraph1,
426-
// into: &accumulatingModuleInfoMap)
427-
// try InterModuleDependencyGraph.mergeModules(from: moduleDependencyGraph2,
428-
// into: &accumulatingModuleInfoMap)
429-
//
430-
// // Ensure the dependencies of the diplicate clang "B" module are merged
431-
// let clangIDs = accumulatingModuleInfoMap.keys.filter { $0.moduleName == "B" }
432-
// XCTAssertTrue(clangIDs.count == 1)
433-
// let clangBInfo = accumulatingModuleInfoMap[clangIDs[0]]!
434-
// XCTAssertTrue(clangBInfo.directDependencies!.count == 2)
435-
// XCTAssertTrue(clangBInfo.directDependencies!.contains(ModuleDependencyId.clang("D")))
436-
// XCTAssertTrue(clangBInfo.directDependencies!.contains(ModuleDependencyId.clang("C")))
411+
let moduleDependencyGraph1 =
412+
try JSONDecoder().decode(
413+
InterModuleDependencyGraph.self,
414+
from: ModuleDependenciesInputs.mergeGraphInput1.data(using: .utf8)!)
415+
let moduleDependencyGraph2 =
416+
try JSONDecoder().decode(
417+
InterModuleDependencyGraph.self,
418+
from: ModuleDependenciesInputs.mergeGraphInput2.data(using: .utf8)!)
419+
420+
var accumulatingModuleInfoMap: [ModuleDependencyId: ModuleInfo] = [:]
421+
422+
try InterModuleDependencyGraph.mergeModules(from: moduleDependencyGraph1,
423+
into: &accumulatingModuleInfoMap)
424+
try InterModuleDependencyGraph.mergeModules(from: moduleDependencyGraph2,
425+
into: &accumulatingModuleInfoMap)
426+
427+
// Ensure the dependencies of the diplicate clang "B" module are merged
428+
let clangIDs = accumulatingModuleInfoMap.keys.filter { $0.moduleName == "B" }
429+
XCTAssertTrue(clangIDs.count == 1)
430+
let clangBInfo = accumulatingModuleInfoMap[clangIDs[0]]!
431+
XCTAssertTrue(clangBInfo.directDependencies!.count == 2)
432+
XCTAssertTrue(clangBInfo.directDependencies!.contains(ModuleDependencyId.clang("D")))
433+
XCTAssertTrue(clangBInfo.directDependencies!.contains(ModuleDependencyId.clang("C")))
437434
}
438435

439436
func testExplicitSwiftModuleMap() throws {

0 commit comments

Comments
 (0)