@@ -294,7 +294,6 @@ internal extension InterModuleDependencyGraph {
294
294
let sourceModuleInfo = try moduleInfo ( of: sourceModuleId)
295
295
// Visit the module's dependencies
296
296
var hasOutOfDateModuleDependency = false
297
- var mostRecentlyUpdatedDependencyOutput : TimePoint = . zero
298
297
for dependencyId in sourceModuleInfo. directDependencies ?? [ ] {
299
298
// If we have not already visited this module, recurse.
300
299
if !visited. contains ( dependencyId) {
@@ -304,32 +303,101 @@ internal extension InterModuleDependencyGraph {
304
303
}
305
304
// Even if we're not revisiting a dependency, we must check if it's already known to be out of date.
306
305
hasOutOfDateModuleDependency = hasOutOfDateModuleDependency || modulesRequiringRebuild. contains ( dependencyId)
307
-
308
- // Keep track of dependencies' output file time stamp to determine if it is newer than the current module.
309
- if let depOutputTimeStamp = try ? fileSystem. lastModificationTime ( for: VirtualPath . lookup ( moduleInfo ( of: dependencyId) . modulePath. path) ) ,
310
- depOutputTimeStamp > mostRecentlyUpdatedDependencyOutput {
311
- mostRecentlyUpdatedDependencyOutput = depOutputTimeStamp
312
- }
313
306
}
314
307
315
308
if hasOutOfDateModuleDependency {
316
309
reporter? . reportExplicitDependencyWillBeReBuilt ( sourceModuleId. moduleNameForDiagnostic, reason: " Invalidated by downstream dependency " )
317
310
modulesRequiringRebuild. insert ( sourceModuleId)
318
- } else if try ! IncrementalCompilationState. IncrementalDependencyAndInputSetup. verifyModuleDependencyUpToDate ( moduleID: sourceModuleId, moduleInfo: sourceModuleInfo,
319
- fileSystem: fileSystem, reporter: reporter) {
311
+ } else if try ! verifyModuleDependencyUpToDate( moduleID: sourceModuleId, fileSystem: fileSystem, reporter: reporter) {
320
312
reporter? . reportExplicitDependencyWillBeReBuilt ( sourceModuleId. moduleNameForDiagnostic, reason: " Out-of-date " )
321
313
modulesRequiringRebuild. insert ( sourceModuleId)
322
- } else if let outputModTime = try ? fileSystem. lastModificationTime ( for: VirtualPath . lookup ( sourceModuleInfo. modulePath. path) ) ,
323
- outputModTime < mostRecentlyUpdatedDependencyOutput {
324
- // If a prior variant of this module dependnecy exists, and is older than any of its direct or transitive
325
- // module dependency outputs, it must also be re-built.
326
- reporter? . reportExplicitDependencyWillBeReBuilt ( sourceModuleId. moduleNameForDiagnostic, reason: " Has newer module dependency inputs " )
327
- modulesRequiringRebuild. insert ( sourceModuleId)
328
314
}
329
315
330
316
// Now that we've determined if this module must be rebuilt, mark it as visited.
331
317
visited. insert ( sourceModuleId)
332
318
}
319
+
320
+ func verifyModuleDependencyUpToDate( moduleID: ModuleDependencyId ,
321
+ fileSystem: FileSystem ,
322
+ reporter: IncrementalCompilationState . Reporter ? ) throws -> Bool {
323
+ let checkedModuleInfo = try moduleInfo ( of: moduleID)
324
+ // Verify that the specified input exists and is older than the specified output
325
+ let verifyInputOlderThanOutputModTime : ( String , VirtualPath , TimePoint ) -> Bool =
326
+ { moduleName, inputPath, outputModTime in
327
+ guard let inputModTime =
328
+ try ? fileSystem. lastModificationTime ( for: inputPath) else {
329
+ reporter? . report ( " Unable to 'stat' \( inputPath. description) " )
330
+ return false
331
+ }
332
+ if inputModTime > outputModTime {
333
+ reporter? . reportExplicitDependencyOutOfDate ( moduleName,
334
+ inputPath: inputPath. description)
335
+ return false
336
+ }
337
+ return true
338
+ }
339
+
340
+ // Check if the output file exists
341
+ guard let outputModTime = try ? fileSystem. lastModificationTime ( for: VirtualPath . lookup ( checkedModuleInfo. modulePath. path) ) else {
342
+ reporter? . report ( " Module output not found: ' \( moduleID. moduleNameForDiagnostic) ' " )
343
+ return false
344
+ }
345
+
346
+ // Check if a dependency of this module has a newer output than this module
347
+ for dependencyId in checkedModuleInfo. directDependencies ?? [ ] {
348
+ let dependencyInfo = try moduleInfo ( of: dependencyId)
349
+ if !verifyInputOlderThanOutputModTime( moduleID. moduleName,
350
+ VirtualPath . lookup ( dependencyInfo. modulePath. path) ,
351
+ outputModTime) {
352
+ return false
353
+ }
354
+ }
355
+
356
+ // Check if any of the textual sources of this module are newer than this module
357
+ switch checkedModuleInfo. details {
358
+ case . swift( let swiftDetails) :
359
+ if let moduleInterfacePath = swiftDetails. moduleInterfacePath {
360
+ if !verifyInputOlderThanOutputModTime( moduleID. moduleName,
361
+ VirtualPath . lookup ( moduleInterfacePath. path) ,
362
+ outputModTime) {
363
+ return false
364
+ }
365
+ }
366
+ if let bridgingHeaderPath = swiftDetails. bridgingHeaderPath {
367
+ if !verifyInputOlderThanOutputModTime( moduleID. moduleName,
368
+ VirtualPath . lookup ( bridgingHeaderPath. path) ,
369
+ outputModTime) {
370
+ return false
371
+ }
372
+ }
373
+ for bridgingSourceFile in swiftDetails. bridgingSourceFiles ?? [ ] {
374
+ if !verifyInputOlderThanOutputModTime( moduleID. moduleName,
375
+ VirtualPath . lookup ( bridgingSourceFile. path) ,
376
+ outputModTime) {
377
+ return false
378
+ }
379
+ }
380
+ case . clang( _) :
381
+ for inputSourceFile in checkedModuleInfo. sourceFiles ?? [ ] {
382
+ if !verifyInputOlderThanOutputModTime( moduleID. moduleName,
383
+ try VirtualPath ( path: inputSourceFile) ,
384
+ outputModTime) {
385
+ return false
386
+ }
387
+ }
388
+ case . swiftPrebuiltExternal( _) :
389
+ // TODO: We have to give-up here until we have a way to verify the timestamp of the binary module.
390
+ // We can do better here by knowing if this module hasn't changed - which would allows us to not
391
+ // invalidate any of the dependencies that depend on it.
392
+ reporter? . report ( " Unable to verify binary module dependency up-to-date: \( moduleID. moduleNameForDiagnostic) " )
393
+ return false ;
394
+ case . swiftPlaceholder( _) :
395
+ // TODO: This should never ever happen. Hard error?
396
+ return false ;
397
+ }
398
+
399
+ return true
400
+ }
333
401
}
334
402
335
403
internal extension InterModuleDependencyGraph {
0 commit comments