Skip to content

Commit b1b6f06

Browse files
author
David Ungar
authored
Merge pull request #334 from davidungar/incr-10-27c
[Incremental] Redoing do incremental builds
2 parents b185ddf + 4a93b7f commit b1b6f06

18 files changed

+978
-289
lines changed

Sources/SwiftDriver/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ add_library(SwiftDriver
4444
"Incremental Compilation/ModuleDependencyGraph.swift"
4545
"Incremental Compilation/Multidictionary.swift"
4646
"Incremental Compilation/SourceFileDependencyGraph.swift"
47+
"Incremental Compilation/SynchronizedQueue.swift"
4748
"Incremental Compilation/TwoDMap.swift"
4849

4950
Jobs/AutolinkExtractJob.swift

Sources/SwiftDriver/Driver/CompilerMode.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ extension CompilerMode {
7171
}
7272
}
7373

74+
public var batchModeInfo: BatchModeInfo? {
75+
switch self {
76+
case let .batchCompile(info):
77+
return info
78+
default:
79+
return nil
80+
}
81+
}
82+
7483
// Whether this compilation mode supports the use of bridging pre-compiled
7584
// headers.
7685
public var supportsBridgingPCH: Bool {

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -825,8 +825,9 @@ extension Driver {
825825
}
826826

827827
if jobs.contains(where: { $0.requiresInPlaceExecution })
828-
// Only one job and no cleanup required
829-
|| (jobs.count == 1 && !parsedOptions.hasArgument(.parseableOutput)) {
828+
// Only one job and no cleanup required, e.g. not writing build record
829+
|| (jobs.count == 1 && !parsedOptions.hasArgument(.parseableOutput) &&
830+
buildRecordInfo == nil) {
830831
assert(jobs.count == 1, "Cannot execute in place for multi-job build plans")
831832
var job = jobs[0]
832833
// Require in-place execution for all single job plans.
@@ -837,17 +838,11 @@ extension Driver {
837838
return
838839
}
839840

840-
// Create and use the tool execution delegate if one is not provided explicitly.
841-
let executorDelegate = createToolExecutionDelegate()
842-
843-
// Perform the build
844-
try executor.execute(jobs: jobs,
845-
delegate: executorDelegate,
846-
numParallelJobs: numParallelJobs ?? 1,
847-
forceResponseFiles: forceResponseFiles,
848-
recordedInputModificationDates: recordedInputModificationDates)
841+
try performTheBuild(allJobs: jobs, forceResponseFiles: forceResponseFiles)
849842

850-
buildRecordInfo?.writeBuildRecord( jobs, nil)
843+
buildRecordInfo?.writeBuildRecord(
844+
jobs,
845+
incrementalCompilationState?.skippedCompilationInputs)
851846

852847
// If requested, warn for options that weren't used by the driver after the build is finished.
853848
if parsedOptions.hasArgument(.driverWarnUnusedOptions) {
@@ -875,6 +870,35 @@ extension Driver {
875870
diagnosticEngine: diagnosticEngine)
876871
}
877872

873+
private mutating func performTheBuild(
874+
allJobs: [Job],
875+
forceResponseFiles: Bool
876+
) throws {
877+
// Create and use the tool execution delegate if one is not provided explicitly.
878+
let executorDelegate = createToolExecutionDelegate()
879+
880+
func execute(jobs: [Job]) throws {
881+
try executor.execute(jobs: jobs,
882+
delegate: executorDelegate,
883+
numParallelJobs: numParallelJobs ?? 1,
884+
forceResponseFiles: forceResponseFiles,
885+
recordedInputModificationDates: recordedInputModificationDates)
886+
}
887+
888+
guard let incrementalCompilationState = incrementalCompilationState else {
889+
try execute(jobs: allJobs)
890+
return
891+
}
892+
while let jobs = incrementalCompilationState.preOrCompileJobs.removeAll() {
893+
try execute(jobs: formBatchedJobs(jobs, forIncremental: true))
894+
}
895+
guard let postCompileJobs = incrementalCompilationState.postCompileJobs
896+
else {
897+
fatalError("planning must have finished by now")
898+
}
899+
try execute(jobs: postCompileJobs)
900+
}
901+
878902
private func printBindings(_ job: Job) {
879903
stdoutStream <<< #"# ""# <<< targetTriple.triple
880904
stdoutStream <<< #"" - ""# <<< job.tool.basename

Sources/SwiftDriver/Driver/OutputFileMap.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ public struct OutputFileMap: Hashable, Codable {
7777
}))
7878
}
7979

80+
/// Slow, but only for debugging output
81+
public func getInput(outputFile: VirtualPath) -> VirtualPath? {
82+
entries
83+
.compactMap {
84+
$0.value.values.contains(outputFile)
85+
? $0.key
86+
: nil
87+
}
88+
.first
89+
}
90+
8091
/// Load the output file map at the given path.
8192
@_spi(Testing) public static func load(
8293
fileSystem: FileSystem,

Sources/SwiftDriver/Driver/ToolExecutionDelegate.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ struct ToolExecutionDelegate: JobExecutionDelegate {
6868
}
6969

7070
public func jobFinished(job: Job, result: ProcessResult, pid: Int) {
71-
if showJobLifecycle {
71+
if showJobLifecycle {
7272
diagnosticEngine.emit(.remark_job_lifecycle("Finished", job))
7373
}
7474

@@ -116,6 +116,6 @@ struct ToolExecutionDelegate: JobExecutionDelegate {
116116
fileprivate extension Diagnostic.Message {
117117
static func remark_job_lifecycle(_ what: String, _ job: Job
118118
) -> Diagnostic.Message {
119-
.remark("\(what) \(job)")
119+
.remark("\(what) \(job.descriptionForLifecycle)")
120120
}
121121
}

Sources/SwiftDriver/Incremental Compilation/BuildRecord.swift

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -129,22 +129,6 @@ public extension BuildRecord {
129129
}
130130
)
131131
}
132-
133-
/// Returns why it did not match
134-
@_spi(Testing) func mismatchReason(buildRecordInfo: BuildRecordInfo, inputFiles: [TypedVirtualPath]) -> String? {
135-
guard buildRecordInfo.actualSwiftVersion == self.swiftVersion else {
136-
return "the compiler version has changed from \(self.swiftVersion) to \(buildRecordInfo.actualSwiftVersion)"
137-
}
138-
guard buildRecordInfo.argsHash == self.argsHash else {
139-
return "different arguments were passed to the compiler"
140-
}
141-
let missingInputs = Set(self.inputInfos.keys).subtracting(inputFiles.map {$0.file})
142-
guard missingInputs.isEmpty else {
143-
return "the following inputs were used in the previous compilation but not in this one: "
144-
+ missingInputs.map {$0.name} .joined(separator: ", ")
145-
}
146-
return nil
147-
}
148132
}
149133

150134
// MARK: - Creating and writing a new map
@@ -235,11 +219,3 @@ extension Diagnostic.Message {
235219
.warning("next compile won't be incremental; could not write build record to \(path)")
236220
}
237221
}
238-
239-
extension Diagnostic.Message {
240-
static func remark_could_not_read_build_record(_ path: VirtualPath,
241-
_ error: Error
242-
) -> Diagnostic.Message {
243-
.remark("incremental compilation could not read build record at \(path): \(error.localizedDescription).")
244-
}
245-
}

Sources/SwiftDriver/Incremental Compilation/BuildRecordInfo.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,36 @@ import SwiftOptions
128128
}
129129

130130
// TODO: Incremental too many names, buildRecord BuildRecord outofdatemap
131-
func populateOutOfDateBuildRecord() -> BuildRecord? {
131+
func populateOutOfDateBuildRecord(
132+
inputFiles: [TypedVirtualPath],
133+
failed: (String) -> Void
134+
) -> BuildRecord? {
135+
let outOfDateBuildRecord: BuildRecord
132136
do {
133137
let contents = try fileSystem.readFileContents(buildRecordPath).cString
134-
return try BuildRecord(contents: contents)
138+
outOfDateBuildRecord = try BuildRecord(contents: contents)
135139
}
136140
catch {
137-
diagnosticEngine.emit(.remark_could_not_read_build_record(buildRecordPath, error))
141+
failed("incremental compilation could not read build record at \(buildRecordPath): \(error.localizedDescription).")
138142
return nil
139143
}
144+
guard actualSwiftVersion == outOfDateBuildRecord.swiftVersion else {
145+
failed(
146+
"the compiler version has changed from \(outOfDateBuildRecord.swiftVersion) to \(actualSwiftVersion)"
147+
)
148+
return nil
149+
}
150+
guard argsHash == outOfDateBuildRecord.argsHash else {
151+
failed( "different arguments were passed to the compiler" )
152+
return nil
153+
}
154+
let missingInputs = Set(outOfDateBuildRecord.inputInfos.keys).subtracting(inputFiles.map {$0.file})
155+
guard missingInputs.isEmpty else {
156+
failed( "the following inputs were used in the previous compilation but not in this one: "
157+
+ missingInputs.map {$0.basename} .joined(separator: ", "))
158+
return nil
159+
}
160+
return outOfDateBuildRecord
140161
}
141162

142163
func jobFinished(job: Job, result: ProcessResult) {

0 commit comments

Comments
 (0)