Skip to content

Commit d7db503

Browse files
committed
Remove Final Traces of "Time Traveling Priors"
Time Traveling priors occur when a file system cache lies to us about the state of the incremental build. Since I'd rather not deal with three operating system's worth of file systems to fix that particular problem, let's make sure this can never happen again by relegating one of the files to the legacy incremental build path. The idea is that the "incremental imports" flag controls things here: Incremental Imports Enabled: Read and write Module.priors bitstream files Incremental Imports Disabled: Read and write Module.swiftdeps YAML files The only notable thing needed to make this work is the old fallback that used to "disable" incremental compilation by bailing out of the entire incremental build now instead constructs an empty module dependency graph and fires off a "clean" incremental build. This should be a pretty significant optimization as it now means that on the happy path we can reach a steady state in the incremental build in one build instead of two.
1 parent 54b0992 commit d7db503

File tree

6 files changed

+225
-324
lines changed

6 files changed

+225
-324
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,30 +1424,69 @@ extension Driver {
14241424
// In case the write fails, don't crash the build.
14251425
// A mitigation to rdar://76359678.
14261426
// If the write fails, import incrementality is lost, but it is not a fatal error.
1427-
if let incrementalCompilationState = self.incrementalCompilationState {
1427+
guard
1428+
let buildRecordInfo = self.buildRecordInfo,
1429+
let absPath = buildRecordInfo.buildRecordPath.absolutePath
1430+
else {
1431+
return
1432+
}
1433+
1434+
let buildRecord = buildRecordInfo.buildRecord(
1435+
jobs, self.incrementalCompilationState?.blockingConcurrentMutationToProtectedState{
1436+
$0.skippedCompilationInputs
1437+
})
1438+
1439+
if
1440+
let incrementalCompilationState = self.incrementalCompilationState,
1441+
incrementalCompilationState.info.isCrossModuleIncrementalBuildEnabled
1442+
{
14281443
do {
1429-
try incrementalCompilationState.writeDependencyGraph(buildRecordInfo)
1430-
}
1431-
catch {
1444+
try incrementalCompilationState.writeDependencyGraph(to: buildRecordInfo.dependencyGraphPath, buildRecord)
1445+
} catch {
14321446
diagnosticEngine.emit(
14331447
.warning("next compile won't be incremental; could not write dependency graph: \(error.localizedDescription)"))
1434-
/// Ensure that a bogus dependency graph is not used next time.
1435-
buildRecordInfo?.removeBuildRecord()
1436-
return
1448+
/// Ensure that a bogus dependency graph is not used next time.
1449+
buildRecordInfo.removeBuildRecord()
1450+
buildRecordInfo.removeInterModuleDependencyGraph()
1451+
return
14371452
}
14381453
do {
14391454
try incrementalCompilationState.writeInterModuleDependencyGraph(buildRecordInfo)
1440-
}
1441-
catch {
1455+
} catch {
14421456
diagnosticEngine.emit(
14431457
.warning("next compile must run a full dependency scan; could not write inter-module dependency graph: \(error.localizedDescription)"))
1444-
buildRecordInfo?.removeInterModuleDependencyGraph()
1458+
buildRecordInfo.removeBuildRecord()
1459+
buildRecordInfo.removeInterModuleDependencyGraph()
14451460
return
14461461
}
1462+
} else {
1463+
// FIXME: This is all legacy code. Once the cross module incremental build
1464+
// becomes the default:
1465+
//
1466+
// 1) Delete this branch
1467+
// 2) Delete the parts of the incremental build that talk about anything
1468+
// derived from `buildRecordPath`
1469+
// 3) Delete the Yams dependency.
1470+
1471+
// Before writing to the dependencies file path, preserve any previous file
1472+
// that may have been there. No error handling -- this is just a nicety, it
1473+
// doesn't matter if it fails.
1474+
// Added for the sake of compatibility with the legacy driver.
1475+
try? fileSystem.move(
1476+
from: absPath, to: absPath.appending(component: absPath.basename + "~"))
1477+
1478+
guard let contents = buildRecord.encode(diagnosticEngine: diagnosticEngine) else {
1479+
diagnosticEngine.emit(.warning_could_not_write_build_record(absPath))
1480+
return
1481+
}
1482+
1483+
do {
1484+
try fileSystem.writeFileContents(absPath,
1485+
bytes: ByteString(encodingAsUTF8: contents))
1486+
} catch {
1487+
diagnosticEngine.emit(.warning_could_not_write_build_record(absPath))
1488+
}
14471489
}
1448-
buildRecordInfo?.writeBuildRecord(
1449-
jobs,
1450-
incrementalCompilationState?.blockingConcurrentMutationToProtectedState{$0.skippedCompilationInputs})
14511490
}
14521491

14531492
private func printBindings(_ job: Job) {

Sources/SwiftDriver/IncrementalCompilation/FirstWaveComputer.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,16 @@ extension IncrementalCompilationState.FirstWaveComputer {
7676
throws -> (initiallySkippedCompileGroups: [TypedVirtualPath: CompileJobGroup],
7777
mandatoryJobsInOrder: [Job])
7878
{
79-
precondition(sourceFiles.disappeared.isEmpty, "unimplemented")
80-
8179
let compileGroups =
8280
Dictionary(uniqueKeysWithValues:
8381
jobsInPhases.compileGroups.map { ($0.primaryInput, $0) })
84-
guard let buildRecord = maybeBuildRecord else {
82+
let buildRecord = self.moduleDependencyGraph.buildRecord
83+
guard !buildRecord.inputInfos.isEmpty else {
8584
func everythingIsMandatory()
8685
throws -> (initiallySkippedCompileGroups: [TypedVirtualPath: CompileJobGroup],
8786
mandatoryJobsInOrder: [Job])
8887
{
89-
let mandatoryCompileGroupsInOrder = sourceFiles.currentInOrder.compactMap {
88+
let mandatoryCompileGroupsInOrder = self.inputFiles.swiftSourceFiles.compactMap {
9089
input -> CompileJobGroup? in
9190
compileGroups[input.typedFile]
9291
}
@@ -166,7 +165,7 @@ extension IncrementalCompilationState.FirstWaveComputer {
166165
}
167166
}
168167

169-
let inputsMissingFromGraph = sourceFiles.currentInOrder.filter { sourceFile in
168+
let inputsMissingFromGraph = self.inputFiles.swiftSourceFiles.filter { sourceFile in
170169
!moduleDependencyGraph.containsNodes(forSourceFile: sourceFile)
171170
}
172171

0 commit comments

Comments
 (0)