@@ -69,81 +69,48 @@ public final class IncrementalCompilationState {
69
69
/// be protected by the confinement queue.
70
70
private var skippedCompileGroups = [ TypedVirtualPath: CompileJobGroup] ( )
71
71
72
- // MARK: - Creating IncrementalCompilationState if possible
72
+ // MARK: - Creating IncrementalCompilationState
73
73
/// Return nil if not compiling incrementally
74
- init ? (
74
+ internal init (
75
75
driver: inout Driver ,
76
- options : Options ,
77
- jobsInPhases : JobsInPhases
76
+ jobsInPhases : JobsInPhases ,
77
+ initialState : InitialStateForPlanning
78
78
) throws {
79
- guard driver. shouldAttemptIncrementalCompilation else { return nil }
80
-
81
- if options. contains ( . showIncremental) {
79
+ if initialState. incrementalOptions. contains ( . showIncremental) {
82
80
self . reporter = Reporter ( diagnosticEngine: driver. diagnosticEngine,
83
81
outputFileMap: driver. outputFileMap)
84
82
} else {
85
83
self . reporter = nil
86
84
}
87
85
88
- let enablingOrDisabling = options. contains ( . enableCrossModuleIncrementalBuild)
86
+ let enablingOrDisabling =
87
+ initialState. incrementalOptions. contains ( . enableCrossModuleIncrementalBuild)
89
88
? " Enabling "
90
89
: " Disabling "
91
90
reporter? . report (
92
91
" \( enablingOrDisabling) incremental cross-module building " )
93
92
93
+ let firstWave =
94
+ try FirstWaveComputer ( initialState: initialState, jobsInPhases: jobsInPhases,
95
+ driver: driver, reporter: reporter) . compute ( batchJobFormer: & driver)
94
96
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
133
99
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
137
103
self . fileSystem = driver. fileSystem
138
104
self . driver = driver
139
105
}
140
106
}
141
107
142
108
// MARK: - Initial State
143
-
144
109
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 {
147
114
/// The dependency graph.
148
115
///
149
116
/// In a status quo build, the dependency graph is derived from the state
@@ -154,17 +121,32 @@ extension IncrementalCompilationState {
154
121
/// In a cross-module build, the dependency graph is derived from prior
155
122
/// state that is serialized alongside the build record.
156
123
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 {
157
143
/// The set of compile jobs we can definitely skip given the state of the
158
144
/// incremental dependency graph and the status of the input files for this
159
145
/// incremental build.
160
146
let skippedCompileGroups : [ TypedVirtualPath : CompileJobGroup ]
161
147
/// All of the pre-compile or compilation job (groups) known to be required
162
148
/// for the first wave to execute.
163
149
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
168
150
}
169
151
}
170
152
@@ -204,7 +186,7 @@ fileprivate extension CompilerMode {
204
186
}
205
187
206
188
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 {
208
190
. warning( " ignoring -incremental (currently requires an output file map) " )
209
191
}
210
192
static var warning_incremental_requires_build_record_entry : Diagnostic . Message {
@@ -220,7 +202,7 @@ extension Diagnostic.Message {
220
202
return . remark( " Incremental compilation has been disabled: \( why) " )
221
203
}
222
204
223
- fileprivate static func remark_incremental_compilation( because why: String ) -> Diagnostic . Message {
205
+ static func remark_incremental_compilation( because why: String ) -> Diagnostic . Message {
224
206
. remark( " Incremental compilation: \( why) " )
225
207
}
226
208
}
0 commit comments