@@ -158,6 +158,7 @@ internal extension InterModuleDependencyGraph {
158
158
/// between it and the root (source module being built by this driver
159
159
/// instance) must also be re-built.
160
160
func computeInvalidatedModuleDependencies( fileSystem: FileSystem ,
161
+ cas: SwiftScanCAS ? ,
161
162
forRebuild: Bool ,
162
163
reporter: IncrementalCompilationState . Reporter ? = nil )
163
164
throws -> Set < ModuleDependencyId > {
@@ -169,7 +170,7 @@ internal extension InterModuleDependencyGraph {
169
170
for dependencyId in mainModuleInfo. directDependencies ?? [ ] {
170
171
try outOfDateModuleScan ( from: dependencyId, visited: & visited,
171
172
modulesRequiringRebuild: & modulesRequiringRebuild,
172
- fileSystem: fileSystem, forRebuild: forRebuild,
173
+ fileSystem: fileSystem, cas : cas , forRebuild: forRebuild,
173
174
reporter: reporter)
174
175
}
175
176
@@ -183,10 +184,11 @@ internal extension InterModuleDependencyGraph {
183
184
/// filter out those with a fully up-to-date output
184
185
func filterMandatoryModuleDependencyCompileJobs( _ allJobs: [ Job ] ,
185
186
fileSystem: FileSystem ,
187
+ cas: SwiftScanCAS ? ,
186
188
reporter: IncrementalCompilationState . Reporter ? = nil ) throws -> [ Job ] {
187
189
// Determine which module pre-build jobs must be re-run
188
190
let modulesRequiringReBuild =
189
- try computeInvalidatedModuleDependencies ( fileSystem: fileSystem, forRebuild: true , reporter: reporter)
191
+ try computeInvalidatedModuleDependencies ( fileSystem: fileSystem, cas : cas , forRebuild: true , reporter: reporter)
190
192
191
193
// Filter the `.generatePCM` and `.compileModuleFromInterface` jobs for
192
194
// modules which do *not* need re-building.
@@ -209,6 +211,7 @@ internal extension InterModuleDependencyGraph {
209
211
visited: inout Set < ModuleDependencyId > ,
210
212
modulesRequiringRebuild: inout Set < ModuleDependencyId > ,
211
213
fileSystem: FileSystem ,
214
+ cas: SwiftScanCAS ? ,
212
215
forRebuild: Bool ,
213
216
reporter: IncrementalCompilationState . Reporter ? = nil ) throws {
214
217
let reportOutOfDate = { ( name: String , reason: String ) in
@@ -227,7 +230,7 @@ internal extension InterModuleDependencyGraph {
227
230
if !visited. contains ( dependencyId) {
228
231
try outOfDateModuleScan ( from: dependencyId, visited: & visited,
229
232
modulesRequiringRebuild: & modulesRequiringRebuild,
230
- fileSystem: fileSystem, forRebuild: forRebuild,
233
+ fileSystem: fileSystem, cas : cas , forRebuild: forRebuild,
231
234
reporter: reporter)
232
235
}
233
236
// Even if we're not revisiting a dependency, we must check if it's already known to be out of date.
@@ -237,7 +240,7 @@ internal extension InterModuleDependencyGraph {
237
240
if hasOutOfDateModuleDependency {
238
241
reportOutOfDate ( sourceModuleId. moduleNameForDiagnostic, " Invalidated by downstream dependency " )
239
242
modulesRequiringRebuild. insert ( sourceModuleId)
240
- } else if try ! verifyModuleDependencyUpToDate( moduleID: sourceModuleId, fileSystem: fileSystem, reporter: reporter) {
243
+ } else if try ! verifyModuleDependencyUpToDate( moduleID: sourceModuleId, fileSystem: fileSystem, cas : cas , reporter: reporter) {
241
244
reportOutOfDate ( sourceModuleId. moduleNameForDiagnostic, " Out-of-date " )
242
245
modulesRequiringRebuild. insert ( sourceModuleId)
243
246
}
@@ -246,10 +249,44 @@ internal extension InterModuleDependencyGraph {
246
249
visited. insert ( sourceModuleId)
247
250
}
248
251
252
+ func outputMissingFromCAS( moduleInfo: ModuleInfo ,
253
+ cas: SwiftScanCAS ? ) throws -> Bool {
254
+ func casOutputMissing( _ key: String ? ) throws -> Bool {
255
+ // Caching not enabled.
256
+ guard let id = key, let cas = cas else { return false }
257
+ // Do a local query to see if the output exists.
258
+ let result = try cas. queryCacheKey ( id, globally: false )
259
+ // Make sure all outputs are available in local CAS.
260
+ guard let outputs = result else { return true }
261
+ return !outputs. allSatisfy { $0. isMaterialized }
262
+ }
263
+
264
+ switch moduleInfo. details {
265
+ case . swift( let swiftDetails) :
266
+ return try casOutputMissing ( swiftDetails. moduleCacheKey)
267
+ case . clang( let clangDetails) :
268
+ return try casOutputMissing ( clangDetails. moduleCacheKey)
269
+ case . swiftPrebuiltExternal( _) :
270
+ return false ;
271
+ case . swiftPlaceholder( _) :
272
+ // TODO: This should never ever happen. Hard error?
273
+ return true ;
274
+ }
275
+ }
276
+
249
277
func verifyModuleDependencyUpToDate( moduleID: ModuleDependencyId ,
250
278
fileSystem: FileSystem ,
279
+ cas: SwiftScanCAS ? ,
251
280
reporter: IncrementalCompilationState . Reporter ? ) throws -> Bool {
252
281
let checkedModuleInfo = try moduleInfo ( of: moduleID)
282
+ // Check if there is a module cache key available, then the content that pointed by the cache key must
283
+ // exist for module to be up-to-date. Treat any CAS error as missing.
284
+ let missingFromCAS = ( try ? outputMissingFromCAS ( moduleInfo: checkedModuleInfo, cas: cas) ) ?? true
285
+ if missingFromCAS {
286
+ reporter? . reportExplicitDependencyMissingFromCAS ( moduleID. moduleName)
287
+ return false
288
+ }
289
+
253
290
// Verify that the specified input exists and is older than the specified output
254
291
let verifyInputOlderThanOutputModTime : ( String , VirtualPath , TimePoint ) -> Bool =
255
292
{ moduleName, inputPath, outputModTime in
0 commit comments