Skip to content

Commit e8c2b0e

Browse files
committed
Read and Write The Driver's Dependency Graph For Cross-Module Builds
The refactoring of the incremental compilation state class is in three pieces: 1) Formalize the type of the InitialState computed by the initializer 2) Internalize computeModuleDependencyGraph and instead make a unified computeInitialState entrypoint (we'll need this for testing later) 3) Divide the status quo and cross-module initial state computations. There is no change to the status quo outside of the breakup of Driver.getBuildInfo The cross-module path is slightly different than the status quo. For one, the incremental build need not fail entirely when either the build record or dependency graph cannot be read. In fact, it is a requirement that the incremental build proceed but schedule every single input file to rebuild, otherwise we won't have a module dependency graph to serialize! As an aside, we ought to consider unifying the build record with the module dependency graph state we're writing here. They're read and written in lock-step when cross-module builds are turned on.
1 parent 2b01735 commit e8c2b0e

File tree

5 files changed

+272
-77
lines changed

5 files changed

+272
-77
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,22 @@ public struct Driver {
201201
/// Only used for reading when compiling incrementally.
202202
let buildRecordInfo: BuildRecordInfo?
203203

204+
/// A build-record-relative path to the location of a serialized copy of the
205+
/// driver's dependency graph.
206+
///
207+
/// FIXME: This is a little ridiculous. We could probably just replace the
208+
/// build record outright with a serialized format.
209+
var driverDependencyGraphPath: AbsolutePath? {
210+
guard
211+
let recordInfo = self.buildRecordInfo,
212+
let recordPath = recordInfo.buildRecordPath.absolutePath
213+
else {
214+
return nil
215+
}
216+
let filename = recordPath.basenameWithoutExt
217+
return recordPath.parentDirectory.appending(component: filename + ".priors")
218+
}
219+
204220
/// Code & data for incremental compilation. Nil if not running in incremental mode.
205221
/// Set during planning because needs the jobs to look at outputs.
206222
@_spi(Testing) public private(set) var incrementalCompilationState: IncrementalCompilationState? = nil
@@ -910,6 +926,7 @@ extension Driver {
910926
if !childJobs.isEmpty {
911927
do {
912928
defer {
929+
self.incrementalCompilationState?.writeDependencyGraph()
913930
buildRecordInfo?.writeBuildRecord(
914931
jobs,
915932
incrementalCompilationState?.skippedCompilationInputs)

Sources/SwiftDriver/IncrementalCompilation/BuildRecordInfo.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import SwiftOptions
1818
/// compilation record).
1919
///
2020
/// This info is always written, but only read for incremental compilation.
21-
final class BuildRecordInfo {
21+
@_spi(Testing) public final class BuildRecordInfo {
2222
/// A pair of a `Job` and the `ProcessResult` corresponding to the outcome of
2323
/// its execution during this compilation session.
2424
struct JobResult {
@@ -122,16 +122,19 @@ final class BuildRecordInfo {
122122
}
123123

124124
/// Write out the build record.
125-
/// `Jobs` must include all of the compilation jobs.
126-
/// `Inputs` will hold all the primary inputs that were not compiled because of incremental compilation
127-
func writeBuildRecord(_ jobs: [Job], _ skippedInputs: Set<TypedVirtualPath>? ) {
125+
///
126+
/// - Parameters:
127+
/// - jobs: All compilation jobs formed during this build.
128+
/// - skippedInputs: All primary inputs that were not compiled because the
129+
/// incremental build plan determined they could be
130+
/// skipped.
131+
func writeBuildRecord(_ jobs: [Job], _ skippedInputs: Set<TypedVirtualPath>?) {
128132
guard let absPath = buildRecordPath.absolutePath else {
129133
diagnosticEngine.emit(
130134
.warning_could_not_write_build_record_not_absolutePath(buildRecordPath))
131135
return
132136
}
133137
preservePreviousBuildRecord(absPath)
134-
135138

136139
let buildRecord = self.confinementQueue.sync {
137140
BuildRecord(
@@ -155,7 +158,7 @@ final class BuildRecordInfo {
155158
} catch {
156159
diagnosticEngine.emit(.warning_could_not_write_build_record(absPath))
157160
}
158-
}
161+
}
159162

160163
/// Before writing to the dependencies file path, preserve any previous file
161164
/// that may have been there. No error handling -- this is just a nicety, it

0 commit comments

Comments
 (0)