Skip to content

Commit 8b1e46e

Browse files
authored
Merge pull request #621 from artemcm/IncrementalRefactorForExplicit
Refactor `IncrementalCompilationState` to compute initial state before job-generation.
2 parents 9afe294 + ccc4024 commit 8b1e46e

10 files changed

+423
-317
lines changed

Sources/SwiftDriver/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ add_library(SwiftDriver
4747
"IncrementalCompilation/DirectAndTransitiveCollections.swift"
4848
"IncrementalCompilation/ExternalDependencyAndFingerprintEnforcer.swift"
4949
"IncrementalCompilation/IncrementalCompilationState.swift"
50-
"IncrementalCompilation/InitialStateComputer.swift"
50+
"IncrementalCompilation/IncrementalDependencyAndInputSetup.swift"
51+
"IncrementalCompilation/FirstWaveComputer.swift"
5152
"IncrementalCompilation/InputInfo.swift"
5253
"IncrementalCompilation/KeyAndFingerprintHolder.swift"
5354
"IncrementalCompilation/ModuleDependencyGraph.swift"

Sources/SwiftDriver/IncrementalCompilation/DependencyGraphDotFileWriter.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import TSCBasic
1414
// MARK: - Asking to write dot files / interface
1515
public class DependencyGraphDotFileWriter {
1616
/// Holds file-system and options
17-
private let info: IncrementalCompilationState.InitialStateComputer
17+
private let info: IncrementalCompilationState.IncrementalDependencyAndInputSetup
1818

1919
private var versionNumber = 0
2020

21-
init(_ info: IncrementalCompilationState.InitialStateComputer) {
21+
init(_ info: IncrementalCompilationState.IncrementalDependencyAndInputSetup) {
2222
self.info = info
2323
}
2424

Sources/SwiftDriver/IncrementalCompilation/InitialStateComputer.swift renamed to Sources/SwiftDriver/IncrementalCompilation/FirstWaveComputer.swift

Lines changed: 56 additions & 190 deletions
Large diffs are not rendered by default.

Sources/SwiftDriver/IncrementalCompilation/IncrementalCompilationState.swift

Lines changed: 40 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -69,81 +69,48 @@ public final class IncrementalCompilationState {
6969
/// be protected by the confinement queue.
7070
private var skippedCompileGroups = [TypedVirtualPath: CompileJobGroup]()
7171

72-
// MARK: - Creating IncrementalCompilationState if possible
72+
// MARK: - Creating IncrementalCompilationState
7373
/// Return nil if not compiling incrementally
74-
init?(
74+
internal init(
7575
driver: inout Driver,
76-
options: Options,
77-
jobsInPhases: JobsInPhases
76+
jobsInPhases: JobsInPhases,
77+
initialState: InitialStateForPlanning
7878
) throws {
79-
guard driver.shouldAttemptIncrementalCompilation else { return nil }
80-
81-
if options.contains(.showIncremental) {
79+
if initialState.incrementalOptions.contains(.showIncremental) {
8280
self.reporter = Reporter(diagnosticEngine: driver.diagnosticEngine,
8381
outputFileMap: driver.outputFileMap)
8482
} else {
8583
self.reporter = nil
8684
}
8785

88-
let enablingOrDisabling = options.contains(.enableCrossModuleIncrementalBuild)
86+
let enablingOrDisabling =
87+
initialState.incrementalOptions.contains(.enableCrossModuleIncrementalBuild)
8988
? "Enabling"
9089
: "Disabling"
9190
reporter?.report(
9291
"\(enablingOrDisabling) incremental cross-module building")
9392

93+
let firstWave =
94+
try FirstWaveComputer(initialState: initialState, jobsInPhases: jobsInPhases,
95+
driver: driver, reporter: reporter).compute(batchJobFormer: &driver)
9496

95-
guard let outputFileMap = driver.outputFileMap else {
96-
driver.diagnosticEngine.emit(.warning_incremental_requires_output_file_map)
97-
return nil
98-
}
99-
100-
guard let buildRecordInfo = driver.buildRecordInfo else {
101-
reporter?.reportDisablingIncrementalBuild("no build record path")
102-
return nil
103-
}
104-
105-
// FIXME: This should work without an output file map. We should have
106-
// another way to specify a build record and where to put intermediates.
107-
let maybeBuildRecord = buildRecordInfo.populateOutOfDateBuildRecord(
108-
inputFiles: driver.inputFiles, reporter: reporter)
109-
110-
// Forming batch jobs requires passing in the driver "inout". But that's the
111-
// only "inout" use needed, among many other values needed from the driver.
112-
// So, pass the other values individually, and pass the driver "inout" as
113-
// the "batchJobFormer". Maybe someday there will be a better way.
114-
guard
115-
let initial = try InitialStateComputer(
116-
options,
117-
jobsInPhases,
118-
outputFileMap,
119-
buildRecordInfo,
120-
maybeBuildRecord,
121-
self.reporter,
122-
driver.inputFiles,
123-
driver.fileSystem,
124-
showJobLifecycle: driver.showJobLifecycle,
125-
driver.diagnosticEngine)
126-
.compute(batchJobFormer: &driver)
127-
else {
128-
return nil
129-
}
130-
131-
self.skippedCompileGroups = initial.skippedCompileGroups
132-
self.mandatoryJobsInOrder = initial.mandatoryJobsInOrder
97+
self.skippedCompileGroups = firstWave.skippedCompileGroups
98+
self.mandatoryJobsInOrder = firstWave.mandatoryJobsInOrder
13399
self.jobsAfterCompiles = jobsInPhases.afterCompiles
134-
self.moduleDependencyGraph = initial.graph
135-
self.buildStartTime = initial.buildStartTime
136-
self.buildEndTime = initial.buildEndTime
100+
self.moduleDependencyGraph = initialState.graph
101+
self.buildStartTime = initialState.buildStartTime
102+
self.buildEndTime = initialState.buildEndTime
137103
self.fileSystem = driver.fileSystem
138104
self.driver = driver
139105
}
140106
}
141107

142108
// MARK: - Initial State
143-
144109
extension IncrementalCompilationState {
145-
/// The initial state of an incremental compilation plan.
146-
@_spi(Testing) public struct InitialState {
110+
/// The initial state of an incremental compilation plan that consists of the module dependency graph
111+
/// and computes which inputs were invalidated by external changes.
112+
/// This set of incremental information is used during planning - job-generation, and is computed early.
113+
@_spi(Testing) public struct InitialStateForPlanning {
147114
/// The dependency graph.
148115
///
149116
/// In a status quo build, the dependency graph is derived from the state
@@ -154,17 +121,32 @@ extension IncrementalCompilationState {
154121
/// In a cross-module build, the dependency graph is derived from prior
155122
/// state that is serialized alongside the build record.
156123
let graph: ModuleDependencyGraph
124+
/// Information about the last known compilation, incl. the location of build artifacts such as the dependency graph.
125+
let buildRecordInfo: BuildRecordInfo
126+
/// Record about existence and time of the last compile.
127+
let maybeBuildRecord: BuildRecord?
128+
/// A set of inputs invalidated by external chagnes.
129+
let inputsInvalidatedByExternals: TransitivelyInvalidatedInputSet
130+
/// Compiler options related to incremental builds.
131+
let incrementalOptions: IncrementalCompilationState.Options
132+
/// The last time this compilation was started. Used to compare against e.g. input file mod dates.
133+
let buildStartTime: Date
134+
/// The last time this compilation finished. Used to compare against output file mod dates
135+
let buildEndTime: Date
136+
}
137+
}
138+
139+
// MARK: - First Wave
140+
extension IncrementalCompilationState {
141+
/// The first set of mandatory jobs for inputs which *must* be built
142+
struct FirstWave {
157143
/// The set of compile jobs we can definitely skip given the state of the
158144
/// incremental dependency graph and the status of the input files for this
159145
/// incremental build.
160146
let skippedCompileGroups: [TypedVirtualPath: CompileJobGroup]
161147
/// All of the pre-compile or compilation job (groups) known to be required
162148
/// for the first wave to execute.
163149
let mandatoryJobsInOrder: [Job]
164-
/// The last time this compilation was started. Used to compare against e.g. input file mod dates.
165-
let buildStartTime: Date
166-
/// The last time this compilation finished. Used to compare against output file mod dates
167-
let buildEndTime: Date
168150
}
169151
}
170152

@@ -204,7 +186,7 @@ fileprivate extension CompilerMode {
204186
}
205187

206188
extension Diagnostic.Message {
207-
fileprivate static var warning_incremental_requires_output_file_map: Diagnostic.Message {
189+
static var warning_incremental_requires_output_file_map: Diagnostic.Message {
208190
.warning("ignoring -incremental (currently requires an output file map)")
209191
}
210192
static var warning_incremental_requires_build_record_entry: Diagnostic.Message {
@@ -220,7 +202,7 @@ extension Diagnostic.Message {
220202
return .remark("Incremental compilation has been disabled: \(why)")
221203
}
222204

223-
fileprivate static func remark_incremental_compilation(because why: String) -> Diagnostic.Message {
205+
static func remark_incremental_compilation(because why: String) -> Diagnostic.Message {
224206
.remark("Incremental compilation: \(why)")
225207
}
226208
}

0 commit comments

Comments
 (0)