Skip to content

Commit 54b0992

Browse files
committed
Refactor BuildRecordInfo
Steal a number of its file reading, writing, and validation routines away from it. These are better managed by the incremental build state.
1 parent 6a44874 commit 54b0992

File tree

6 files changed

+33
-115
lines changed

6 files changed

+33
-115
lines changed

Sources/SwiftDriver/IncrementalCompilation/BuildRecordInfo.swift

Lines changed: 2 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,8 @@ import class Dispatch.DispatchQueue
156156
/// - skippedInputs: All primary inputs that were not compiled because the
157157
/// incremental build plan determined they could be
158158
/// skipped.
159-
func writeBuildRecord(_ jobs: [Job], _ skippedInputs: Set<TypedVirtualPath>?) {
160-
guard let absPath = buildRecordPath.absolutePath else {
161-
diagnosticEngine.emit(
162-
.warning_could_not_write_build_record_not_absolutePath(buildRecordPath))
163-
return
164-
}
165-
preservePreviousBuildRecord(absPath)
166-
167-
let buildRecord = self.confinementQueue.sync {
159+
@_spi(Testing) public func buildRecord(_ jobs: [Job], _ skippedInputs: Set<TypedVirtualPath>?) -> BuildRecord {
160+
return self.confinementQueue.sync {
168161
BuildRecord(
169162
jobs: jobs,
170163
finishedJobResults: finishedJobResults,
@@ -175,18 +168,6 @@ import class Dispatch.DispatchQueue
175168
timeBeforeFirstJob: timeBeforeFirstJob,
176169
timeAfterLastJob: .now())
177170
}
178-
179-
guard let contents = buildRecord.encode(currentArgsHash: currentArgsHash,
180-
diagnosticEngine: diagnosticEngine)
181-
else {
182-
return
183-
}
184-
do {
185-
try fileSystem.writeFileContents(absPath,
186-
bytes: ByteString(encodingAsUTF8: contents))
187-
} catch {
188-
diagnosticEngine.emit(.warning_could_not_write_build_record(absPath))
189-
}
190171
}
191172

192173
func removeBuildRecord() {
@@ -203,67 +184,9 @@ import class Dispatch.DispatchQueue
203184
try? fileSystem.removeFileTree(absPath)
204185
}
205186

206-
/// Before writing to the dependencies file path, preserve any previous file
207-
/// that may have been there. No error handling -- this is just a nicety, it
208-
/// doesn't matter if it fails.
209-
/// Added for the sake of compatibility with the legacy driver.
210-
private func preservePreviousBuildRecord(_ oldPath: AbsolutePath) {
211-
let newPath = oldPath.withTilde()
212-
try? fileSystem.move(from: oldPath, to: newPath)
213-
}
214-
215-
216-
// TODO: Incremental too many names, buildRecord BuildRecord outofdatemap
217-
func populateOutOfDateBuildRecord(
218-
reporter: IncrementalCompilationState.Reporter?
219-
) -> BuildRecord? {
220-
let contents: String
221-
do {
222-
contents = try fileSystem.readFileContents(buildRecordPath).cString
223-
} catch {
224-
reporter?.report("Incremental compilation could not read build record at ", buildRecordPath)
225-
reporter?.reportDisablingIncrementalBuild("could not read build record")
226-
return nil
227-
}
228-
func failedToReadOutOfDateMap(_ reason: String? = nil) {
229-
let why = "malformed build record file\(reason.map {" " + $0} ?? "")"
230-
reporter?.report(
231-
"Incremental compilation has been disabled due to \(why)", buildRecordPath)
232-
reporter?.reportDisablingIncrementalBuild(why)
233-
}
234-
guard let outOfDateBuildRecord = BuildRecord(contents: contents,
235-
failedToReadOutOfDateMap: failedToReadOutOfDateMap)
236-
else {
237-
return nil
238-
}
239-
guard actualSwiftVersion == outOfDateBuildRecord.swiftVersion
240-
else {
241-
let why = "compiler version mismatch. Compiling with: \(actualSwiftVersion). Previously compiled with: \(outOfDateBuildRecord.swiftVersion)"
242-
// mimic legacy
243-
reporter?.reportIncrementalCompilationHasBeenDisabled("due to a " + why)
244-
reporter?.reportDisablingIncrementalBuild(why)
245-
return nil
246-
}
247-
guard outOfDateBuildRecord.argsHash.map({ $0 == currentArgsHash }) ?? true else {
248-
let why = "different arguments were passed to the compiler"
249-
// mimic legacy
250-
reporter?.reportIncrementalCompilationHasBeenDisabled("because " + why)
251-
reporter?.reportDisablingIncrementalBuild(why)
252-
return nil
253-
}
254-
return outOfDateBuildRecord
255-
}
256-
257187
func readOutOfDateInterModuleDependencyGraph(
258-
buildRecord: BuildRecord?,
259188
reporter: IncrementalCompilationState.Reporter?
260189
) -> InterModuleDependencyGraph? {
261-
// If a valid build record could not be produced, do not bother here
262-
guard buildRecord != nil else {
263-
reporter?.report("Incremental compilation did not attempt to read inter-module dependency graph.")
264-
return nil
265-
}
266-
267190
let decodedGraph: InterModuleDependencyGraph
268191
do {
269192
let contents = try fileSystem.readFileContents(interModuleDependencyGraphPath).cString
@@ -309,9 +232,3 @@ import class Dispatch.DispatchQueue
309232
buildRecordPath.parentDirectory
310233
}
311234
}
312-
313-
fileprivate extension AbsolutePath {
314-
func withTilde() -> Self {
315-
parentDirectory.appending(component: basename + "~")
316-
}
317-
}

Sources/SwiftDriver/IncrementalCompilation/IncrementalCompilationProtectedState.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ extension IncrementalCompilationState.ProtectedState {
150150

151151
func writeGraph(to path: VirtualPath,
152152
on fs: FileSystem,
153-
buildRecord: BuildRecordInfo,
153+
buildRecord: BuildRecord,
154154
mockSerializedGraphVersion: Version? = nil
155155
) throws {
156156
accessSafetyPrecondition()

Sources/SwiftDriver/IncrementalCompilation/IncrementalCompilationState+Extensions.swift

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -393,22 +393,16 @@ extension IncrementalCompilationState {
393393
}
394394
}
395395

396-
func writeDependencyGraph(_ buildRecordInfo: BuildRecordInfo?) throws {
397-
// If the cross-module build is not enabled, the status quo dictates we
398-
// not emit this file.
399-
guard info.isCrossModuleIncrementalBuildEnabled else {
400-
return
401-
}
402-
guard
403-
let recordInfo = buildRecordInfo
404-
else {
405-
throw WriteDependencyGraphError.noBuildRecordInfo
406-
}
407-
try blockingConcurrentMutationToProtectedState {
396+
func writeDependencyGraph(
397+
to path: VirtualPath,
398+
_ buildRecord: BuildRecord
399+
) throws {
400+
precondition(info.isCrossModuleIncrementalBuildEnabled)
401+
try blockingConcurrentAccessOrMutationToProtectedState {
408402
try $0.writeGraph(
409-
to: recordInfo.dependencyGraphPath,
403+
to: path,
410404
on: info.fileSystem,
411-
buildRecord: recordInfo)
405+
buildRecord: buildRecord)
412406
}
413407
}
414408

@@ -488,7 +482,12 @@ extension OutputFileMap {
488482
// MARK: SourceFiles
489483

490484
/// Handy information about the source files in the current invocation
491-
@_spi(Testing) public struct SourceFiles {
485+
///
486+
/// Usages of this structure are deprecated and should be removed on sight. For
487+
/// large driver jobs, it is extremely expensive both in terms of memory and
488+
/// compilation latency to instantiate as it rematerializes the entire input set
489+
/// multiple times.
490+
struct SourceFiles {
492491
/// The current (.swift) files in same order as the invocation
493492
let currentInOrder: [SwiftSourceFile]
494493

@@ -501,10 +500,10 @@ extension OutputFileMap {
501500
/// The files that were in the previous but not in the current invocation
502501
let disappeared: [SwiftSourceFile]
503502

504-
init(inputFiles: [TypedVirtualPath], buildRecord: BuildRecord?) {
503+
init(inputFiles: [TypedVirtualPath], buildRecord: BuildRecord) {
505504
self.currentInOrder = inputFiles.swiftSourceFiles
506505
self.currentSet = Set(currentInOrder)
507-
guard let buildRecord = buildRecord else {
506+
guard !buildRecord.inputInfos.isEmpty else {
508507
self.previousSet = Set()
509508
self.disappeared = []
510509
return

Sources/SwiftDriver/IncrementalCompilation/IncrementalCompilationState.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ public final class IncrementalCompilationState {
6464
reporter?.reportOnIncrementalImports(
6565
initialState.incrementalOptions.contains(.enableCrossModuleIncrementalBuild))
6666

67-
let firstWave =
68-
try FirstWaveComputer(initialState: initialState, jobsInPhases: jobsInPhases,
69-
driver: driver, reporter: reporter).compute(batchJobFormer: &driver)
67+
let firstWave = try FirstWaveComputer(
68+
initialState: initialState,
69+
jobsInPhases: jobsInPhases,
70+
driver: driver,
71+
reporter: reporter)
72+
.compute(batchJobFormer: &driver)
7073

7174
self.info = initialState.graph.info
7275
self.upToDateInterModuleDependencyGraph = interModuleDependencyGraph

Tests/SwiftDriverTests/Helpers/MockingIncrementalCompilation.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ extension IncrementalCompilationState.IncrementalDependencyAndInputSetup {
142142
compilerVersion: "for-testing")
143143
return Self(options, outputFileMap,
144144
buildRecord,
145-
nil, nil, nil, inputFiles, fileSystem,
145+
nil, inputFiles, fileSystem,
146146
diagnosticEngine)
147147
}
148148
}
@@ -176,19 +176,18 @@ struct MockModuleDependencyGraphCreator {
176176
}
177177

178178
func mockUpAGraph() -> ModuleDependencyGraph {
179-
.createForBuildingFromSwiftDeps(info)
179+
.createForBuildingFromSwiftDeps(info.buildRecordInfo.buildRecord([], []), info)
180180
}
181181
}
182182

183183

184184
extension OutputFileMap {
185185
static func mock(maxIndex: Int) -> Self {
186-
OutputFileMap( entries: (0...maxIndex) .reduce(into: [:]) {
186+
OutputFileMap(entries: (0...maxIndex) .reduce(into: [:]) {
187187
entries, index in
188188
let inputHandle = SwiftSourceFile(mock: index).fileHandle
189189
let swiftDepsHandle = SwiftSourceFile(mock: index).fileHandle
190190
entries[inputHandle] = [.swiftDeps: swiftDepsHandle]
191-
}
192-
)
191+
})
193192
}
194193
}

Tests/SwiftDriverTests/IncrementalBuildPerformanceTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class IncrementalBuildPerformanceTests: XCTestCase {
3838
throw XCTSkip()
3939
#else
4040

41-
let packageRootPath = AbsolutePath(#file)
41+
let packageRootPath = try AbsolutePath(validating: #file)
4242
.parentDirectory
4343
.parentDirectory
4444
.parentDirectory
@@ -69,7 +69,7 @@ class IncrementalBuildPerformanceTests: XCTestCase {
6969
let info = IncrementalCompilationState.IncrementalDependencyAndInputSetup
7070
.mock(options: [], outputFileMap: outputFileMap)
7171

72-
let g = ModuleDependencyGraph.createForSimulatingCleanBuild(info)
72+
let g = ModuleDependencyGraph.createForSimulatingCleanBuild(info.buildRecordInfo.buildRecord([], []), info)
7373
g.blockingConcurrentAccessOrMutation {
7474
switch whatToMeasure {
7575
case .readingSwiftDeps:
@@ -79,14 +79,14 @@ class IncrementalBuildPerformanceTests: XCTestCase {
7979
measure {
8080
_ = ModuleDependencyGraph.Serializer.serialize(
8181
g,
82-
info.buildRecordInfo,
82+
g.buildRecord,
8383
ModuleDependencyGraph.serializedGraphVersion)
8484
}
8585
case .readingPriors:
8686
readSwiftDeps(for: inputs, into: g)
8787
let data = ModuleDependencyGraph.Serializer.serialize(
8888
g,
89-
info.buildRecordInfo,
89+
g.buildRecord,
9090
ModuleDependencyGraph.serializedGraphVersion)
9191
measure {
9292
try? XCTAssertNoThrow(ModuleDependencyGraph.deserialize(data, info: info))

0 commit comments

Comments
 (0)