@@ -39,14 +39,17 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
39
39
private let integratedDriver : Bool
40
40
private let mainModuleName : String ?
41
41
42
+ /// Clang PCM names contain a hash of the command-line arguments that were used to build them.
43
+ /// We avoid re-running the hash computation with the use of this cache
44
+ private var hashedModuleNameCache : [ String : String ] = [ : ]
45
+
42
46
public init ( dependencyGraph: InterModuleDependencyGraph ,
43
47
toolchain: Toolchain ,
44
- integratedDriver: Bool = true ,
45
- mainModuleName: String ? = nil ) throws {
48
+ integratedDriver: Bool = true ) throws {
46
49
self . dependencyGraph = dependencyGraph
47
50
self . toolchain = toolchain
48
51
self . integratedDriver = integratedDriver
49
- self . mainModuleName = mainModuleName
52
+ self . mainModuleName = dependencyGraph . mainModuleName
50
53
self . reachabilityMap = try dependencyGraph. computeTransitiveClosure ( )
51
54
}
52
55
@@ -82,7 +85,7 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
82
85
/// module's target version (PCM Args).
83
86
/// 2. Generate jobs for all Clang modules, now that we have each module's set of PCM versions it must be
84
87
/// built against.
85
- public func generateExplicitModuleDependenciesBuildJobs( ) throws -> [ Job ] {
88
+ public mutating func generateExplicitModuleDependenciesBuildJobs( ) throws -> [ Job ] {
86
89
let mainModuleId : ModuleDependencyId = . swift( dependencyGraph. mainModuleName)
87
90
guard let mainModuleDependencies = reachabilityMap [ mainModuleId] else {
88
91
fatalError ( " Expected reachability information for the main module. " )
@@ -104,9 +107,9 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
104
107
}
105
108
106
109
/// Generate a build job for each Swift module in the set of supplied `dependencies`
107
- private func generateSwiftDependenciesBuildJobs( for dependencies: Set < ModuleDependencyId > ,
108
- clangPCMSetMap:
109
- inout [ ModuleDependencyId : Set < [ String ] > ] )
110
+ private mutating func generateSwiftDependenciesBuildJobs( for dependencies: Set < ModuleDependencyId > ,
111
+ clangPCMSetMap:
112
+ inout [ ModuleDependencyId : Set < [ String ] > ] )
110
113
throws -> [ Job ] {
111
114
var jobs : [ Job ] = [ ]
112
115
let swiftDependencies = dependencies. filter {
@@ -174,9 +177,9 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
174
177
175
178
/// Generate a build job for each Clang module in the set of supplied `dependencies`. Once per each required
176
179
/// PCMArgSet as queried from the supplied `clangPCMSetMap`
177
- private func generateClangDependenciesBuildJobs( for dependencies: Set < ModuleDependencyId > ,
178
- using clangPCMSetMap:
179
- [ ModuleDependencyId : Set < [ String ] > ] )
180
+ private mutating func generateClangDependenciesBuildJobs( for dependencies: Set < ModuleDependencyId > ,
181
+ using clangPCMSetMap:
182
+ [ ModuleDependencyId : Set < [ String ] > ] )
180
183
throws -> [ Job ] {
181
184
var jobs : [ Job ] = [ ]
182
185
let clangDependencies = dependencies. filter {
@@ -210,9 +213,8 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
210
213
211
214
// Encode the target triple pcm args into the output `.pcm` filename
212
215
let targetEncodedModulePath =
213
- try ExplicitDependencyBuildPlanner
214
- . targetEncodedClangModuleFilePath ( for: moduleInfo,
215
- hashParts: getPCMHashParts ( pcmArgs: pcmArgs) )
216
+ try targetEncodedClangModuleFilePath ( for: moduleInfo,
217
+ hashParts: getPCMHashParts ( pcmArgs: pcmArgs) )
216
218
outputs. append ( TypedVirtualPath ( file: targetEncodedModulePath, type: . pcm) )
217
219
commandLine. appendFlags ( " -emit-pcm " , " -module-name " , moduleId. moduleName,
218
220
" -o " , targetEncodedModulePath. description)
@@ -239,9 +241,9 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
239
241
240
242
/// For the specified module, update the given command line flags and inputs
241
243
/// to use explicitly-built module dependencies.
242
- private func resolveExplicitModuleDependencies( moduleId: ModuleDependencyId , pcmArgs: [ String ] ,
243
- inputs: inout [ TypedVirtualPath ] ,
244
- commandLine: inout [ Job . ArgTemplate ] ) throws {
244
+ private mutating func resolveExplicitModuleDependencies( moduleId: ModuleDependencyId , pcmArgs: [ String ] ,
245
+ inputs: inout [ TypedVirtualPath ] ,
246
+ commandLine: inout [ Job . ArgTemplate ] ) throws {
245
247
// Prohibit the frontend from implicitly building textual modules into binary modules.
246
248
commandLine. appendFlags ( " -disable-implicit-swift-modules " , " -Xcc " , " -Xclang " , " -Xcc " ,
247
249
" -fno-implicit-modules " )
@@ -286,9 +288,9 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
286
288
287
289
/// Add a specific module dependency as an input and a corresponding command
288
290
/// line flag.
289
- private func addModuleDependencies( moduleId: ModuleDependencyId , pcmArgs: [ String ] ,
290
- clangDependencyArtifacts: inout [ ClangModuleArtifactInfo ] ,
291
- swiftDependencyArtifacts: inout [ SwiftModuleArtifactInfo ]
291
+ private mutating func addModuleDependencies( moduleId: ModuleDependencyId , pcmArgs: [ String ] ,
292
+ clangDependencyArtifacts: inout [ ClangModuleArtifactInfo ] ,
293
+ swiftDependencyArtifacts: inout [ SwiftModuleArtifactInfo ]
292
294
) throws {
293
295
guard let moduleDependencies = reachabilityMap [ moduleId] else {
294
296
fatalError ( " Expected reachability information for the module: \( moduleId. moduleName) . " )
@@ -313,9 +315,8 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
313
315
let dependencyClangModuleDetails =
314
316
try dependencyGraph. clangModuleDetails ( of: dependencyId)
315
317
let clangModulePath =
316
- try ExplicitDependencyBuildPlanner
317
- . targetEncodedClangModuleFilePath ( for: dependencyInfo,
318
- hashParts: getPCMHashParts ( pcmArgs: pcmArgs) )
318
+ try targetEncodedClangModuleFilePath ( for: dependencyInfo,
319
+ hashParts: getPCMHashParts ( pcmArgs: pcmArgs) )
319
320
// Accumulate the requried information about this dependency
320
321
clangDependencyArtifacts. append (
321
322
ClangModuleArtifactInfo ( name: dependencyId. moduleName,
@@ -359,8 +360,8 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
359
360
360
361
/// Resolve all module dependencies of the main module and add them to the lists of
361
362
/// inputs and command line flags.
362
- public func resolveMainModuleDependencies( inputs: inout [ TypedVirtualPath ] ,
363
- commandLine: inout [ Job . ArgTemplate ] ) throws {
363
+ public mutating func resolveMainModuleDependencies( inputs: inout [ TypedVirtualPath ] ,
364
+ commandLine: inout [ Job . ArgTemplate ] ) throws {
364
365
let mainModuleId : ModuleDependencyId = . swift( dependencyGraph. mainModuleName)
365
366
try resolveExplicitModuleDependencies ( moduleId: mainModuleId,
366
367
pcmArgs:
@@ -401,8 +402,8 @@ public typealias ExternalBuildArtifacts = (ExternalTargetModulePathMap, ModuleIn
401
402
extension ExplicitDependencyBuildPlanner {
402
403
/// Compute a full path to the resulting .pcm file for a given Clang module, with the
403
404
/// target triple encoded in the name.
404
- public static func targetEncodedClangModuleFilePath( for moduleInfo: ModuleInfo ,
405
- hashParts: [ String ] ) throws -> VirtualPath {
405
+ public mutating func targetEncodedClangModuleFilePath( for moduleInfo: ModuleInfo ,
406
+ hashParts: [ String ] ) throws -> VirtualPath {
406
407
let plainModulePath = moduleInfo. modulePath. path
407
408
let targetEncodedBaseName =
408
409
try targetEncodedClangModuleName ( for: plainModulePath. basenameWithoutExt,
@@ -416,9 +417,15 @@ extension ExplicitDependencyBuildPlanner {
416
417
417
418
/// Compute the name of a given Clang module, along with a hash of extra PCM build arguments it
418
419
/// is to be constructed with.
419
- public static func targetEncodedClangModuleName( for moduleName: String ,
420
- hashParts: [ String ] ) throws -> String {
420
+ @_spi ( Testing) public mutating func targetEncodedClangModuleName( for moduleName: String ,
421
+ hashParts: [ String ] )
422
+ throws -> String {
421
423
let hashInput = hashParts. sorted ( ) . joined ( )
424
+ // Hash based on "moduleName + hashInput"
425
+ let cacheQuery = moduleName + hashInput
426
+ if let previouslyHashsedName = hashedModuleNameCache [ cacheQuery] {
427
+ return previouslyHashsedName
428
+ }
422
429
let hashedArguments : String
423
430
#if os(macOS)
424
431
if #available( macOS 10 . 15 , iOS 13 , * ) {
@@ -429,7 +436,9 @@ extension ExplicitDependencyBuildPlanner {
429
436
#else
430
437
hashedArguments = SHA256 ( ) . hash ( hashInput) . hexadecimalRepresentation
431
438
#endif
432
- return moduleName + hashedArguments
439
+ let resultingName = moduleName + hashedArguments
440
+ hashedModuleNameCache [ cacheQuery] = resultingName
441
+ return resultingName
433
442
}
434
443
}
435
444
0 commit comments