Skip to content

Commit c0fe9c6

Browse files
authored
Merge pull request #2959 from artemcm/AvoidRedundantRescan
[Explicit Module Builds] Communicate all previously-seen modules to swift-driver when planning explicit package build.
2 parents 9d5c37a + 830480a commit c0fe9c6

File tree

1 file changed

+55
-34
lines changed

1 file changed

+55
-34
lines changed

Sources/Build/ManifestBuilder.swift

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,11 @@ extension LLBuildManifestBuilder {
312312
}
313313
let allPackageDependencies = try! topologicalSort(nodes, successors: { $0.dependencies })
314314

315-
// Collect all targets' dependency graphs
316-
var targetDepGraphMap : [ResolvedTarget: InterModuleDependencyGraph] = [:]
315+
// All modules discovered so far as a part of this package manifest.
316+
// This includes modules that correspond to the package's own targets, package dependency
317+
// targets, and modules that are discovered as dependencies of the above in individual
318+
// dependency scanning actions
319+
var discoveredModulesMap : SwiftDriver.ModuleInfoMap = [:]
317320

318321
// Create commands for all target descriptions in the plan.
319322
for dependency in allPackageDependencies.reversed() {
@@ -341,7 +344,7 @@ extension LLBuildManifestBuilder {
341344
switch description {
342345
case .swift(let desc):
343346
try createExplicitSwiftTargetCompileCommand(description: desc,
344-
targetDepGraphMap: &targetDepGraphMap)
347+
discoveredModulesMap: &discoveredModulesMap)
345348
case .clang(let desc):
346349
createClangCompileCommand(desc)
347350
}
@@ -350,7 +353,7 @@ extension LLBuildManifestBuilder {
350353

351354
private func createExplicitSwiftTargetCompileCommand(
352355
description: SwiftTargetBuildDescription,
353-
targetDepGraphMap: inout [ResolvedTarget: InterModuleDependencyGraph]
356+
discoveredModulesMap: inout SwiftDriver.ModuleInfoMap
354357
) throws {
355358
// Inputs.
356359
let inputs = computeSwiftCompileCmdInputs(description)
@@ -362,92 +365,110 @@ extension LLBuildManifestBuilder {
362365

363366
// Commands.
364367
try addExplicitBuildSwiftCmds(description, inputs: inputs,
365-
targetDepGraphMap: &targetDepGraphMap)
368+
discoveredModulesMap: &discoveredModulesMap)
366369

367370
addTargetCmd(description, cmdOutputs: cmdOutputs)
368371
addModuleWrapCmd(description)
369372
}
370373

371374
private func addExplicitBuildSwiftCmds(
372375
_ targetDescription: SwiftTargetBuildDescription,
373-
inputs: [Node], targetDepGraphMap: inout [ResolvedTarget: InterModuleDependencyGraph]
376+
inputs: [Node],
377+
discoveredModulesMap: inout SwiftDriver.ModuleInfoMap
374378
) throws {
375379
// Pass the driver its external dependencies (target dependencies)
376-
var targetDependencyMap: SwiftDriver.ExternalDependencyArtifactMap = [:]
377-
collectTargetDependencyInfos(for: targetDescription.target,
378-
targetDepGraphMap: targetDepGraphMap,
379-
dependencyArtifactMap: &targetDependencyMap)
380+
var dependencyModulePathMap: SwiftDriver.ExternalTargetModulePathMap = [:]
381+
// Collect paths for target dependencies of this target (direct and transitive)
382+
collectTargetDependencyModulePaths(for: targetDescription.target,
383+
dependencyModulePathMap: &dependencyModulePathMap)
380384

381385
// Compute the set of frontend
382386
// jobs needed to build this Swift target.
383387
var commandLine = targetDescription.emitCommandLine();
384388
commandLine.append("-driver-use-frontend-path")
385389
commandLine.append(buildParameters.toolchain.swiftCompiler.pathString)
386390
commandLine.append("-experimental-explicit-module-build")
387-
// FIXME: At some point SwiftPM should provide its own executor for
388-
// running jobs/launching processes during planning
389391
let resolver = try ArgsResolver(fileSystem: targetDescription.fs)
390392
let executor = SPMSwiftDriverExecutor(resolver: resolver,
391393
fileSystem: targetDescription.fs,
392394
env: ProcessEnv.vars)
393395
var driver = try Driver(args: commandLine, fileSystem: targetDescription.fs,
394396
executor: executor,
395-
externalModuleDependencies: targetDependencyMap)
397+
externalBuildArtifacts: (dependencyModulePathMap, discoveredModulesMap))
396398

397399
let jobs = try driver.planBuild()
398400

401+
// Save the path to the target's module to be used by its dependents
399402
// Save the dependency graph of this target to be used by its dependents
400403
guard let dependencyGraph = driver.interModuleDependencyGraph else {
401404
fatalError("Expected module dependency graph for target: \(targetDescription)")
402405
}
403-
targetDepGraphMap[targetDescription.target] = dependencyGraph
406+
try accumulateDiscoveredModules(from: dependencyGraph,
407+
discoveredModules: &discoveredModulesMap)
408+
404409
try addSwiftDriverJobs(for: targetDescription, jobs: jobs, inputs: inputs, resolver: resolver,
405410
isMainModule: { driver.isExplicitMainModuleJob(job: $0)})
406411
}
407412

413+
private func accumulateDiscoveredModules(
414+
from dependencyGraph: InterModuleDependencyGraph,
415+
discoveredModules: inout SwiftDriver.ModuleInfoMap
416+
) throws {
417+
for (moduleId, moduleInfo) in dependencyGraph.modules {
418+
switch moduleId {
419+
case .swift:
420+
discoveredModules[moduleId] = moduleInfo
421+
case .clang:
422+
guard let existingModuleInfo = discoveredModules[moduleId] else {
423+
discoveredModules[moduleId] = moduleInfo
424+
break
425+
}
426+
// If this module *has* been seen before, merge the module infos to capture
427+
// the super-set of so-far discovered dependencies of this module at various
428+
// PCMArg scanning actions.
429+
let combinedDependenciesInfo =
430+
InterModuleDependencyGraph.mergeClangModuleInfoDependencies(moduleInfo,
431+
existingModuleInfo)
432+
discoveredModules[moduleId] = combinedDependenciesInfo
433+
case .swiftPlaceholder:
434+
fatalError("Unresolved placeholder dependencies at manifest build stage: \(moduleId)")
435+
}
436+
}
437+
}
438+
408439
/// Collect a map from all target dependencies of the specified target to the build planning artifacts for said dependency,
409440
/// in the form of a path to a .swiftmodule file and the dependency's InterModuleDependencyGraph.
410-
private func collectTargetDependencyInfos(for target: ResolvedTarget,
411-
targetDepGraphMap: [ResolvedTarget: InterModuleDependencyGraph],
412-
dependencyArtifactMap: inout SwiftDriver.ExternalDependencyArtifactMap
413-
) {
441+
private func collectTargetDependencyModulePaths(
442+
for target: ResolvedTarget,
443+
dependencyModulePathMap: inout SwiftDriver.ExternalTargetModulePathMap) {
414444
for dependency in target.dependencies {
415445
switch dependency {
416446
case .product:
417447
// Product dependencies are broken down into the targets that make them up.
418448
let dependencyProduct = dependency.product!
419449
for dependencyProductTarget in dependencyProduct.targets {
420450
addTargetDependencyInfo(for: dependencyProductTarget,
421-
targetDepGraphMap: targetDepGraphMap,
422-
dependencyArtifactMap: &dependencyArtifactMap)
451+
dependencyModulePathMap: &dependencyModulePathMap)
423452

424453
}
425454
case .target:
426455
// Product dependencies are broken down into the targets that make them up.
427456
let dependencyTarget = dependency.target!
428457
addTargetDependencyInfo(for: dependencyTarget,
429-
targetDepGraphMap: targetDepGraphMap,
430-
dependencyArtifactMap: &dependencyArtifactMap)
458+
dependencyModulePathMap: &dependencyModulePathMap)
431459
}
432460
}
433461
}
434462

435463
private func addTargetDependencyInfo(for target: ResolvedTarget,
436-
targetDepGraphMap: [ResolvedTarget: InterModuleDependencyGraph],
437-
dependencyArtifactMap: inout SwiftDriver.ExternalDependencyArtifactMap) {
464+
dependencyModulePathMap: inout SwiftDriver.ExternalTargetModulePathMap) {
438465
guard case .swift(let dependencySwiftTargetDescription) = plan.targetMap[target] else {
439466
return
440467
}
441-
guard let dependencyGraph = targetDepGraphMap[target] else {
442-
fatalError("Expected dependency graph for target: \(target.description)")
443-
}
444-
let dependencyModulePath = dependencySwiftTargetDescription.moduleOutputPath
445-
dependencyArtifactMap[ModuleDependencyId.swiftPlaceholder(target.c99name)] =
446-
(dependencyModulePath, dependencyGraph)
447-
448-
collectTargetDependencyInfos(for: target,
449-
targetDepGraphMap: targetDepGraphMap,
450-
dependencyArtifactMap: &dependencyArtifactMap)
468+
dependencyModulePathMap[ModuleDependencyId.swiftPlaceholder(target.c99name)] =
469+
dependencySwiftTargetDescription.moduleOutputPath
470+
collectTargetDependencyModulePaths(for: target,
471+
dependencyModulePathMap: &dependencyModulePathMap)
451472
}
452473

453474
private func addSwiftCmdsEmitSwiftModuleSeparately(

0 commit comments

Comments
 (0)