@@ -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-
144109extension 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
206188extension 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