Skip to content

Commit d9918d3

Browse files
committed
[Incremental Builds] Produce an empty first wave if only job to run is verify module interface job.
Existing check decides to skip all compilation if there are no compile jobs and no post-compile job depends on before-compile jobs' outputs. This change refines the check to also ensure we do not run before-compile jobs whose only dependents are interface verification jobs. Otherwise, we would have an emit-module job, followed by verify-module-interface jobs on a null incremental build. Resolves rdar://89913538
1 parent 0f9f247 commit d9918d3

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

Sources/SwiftDriver/IncrementalCompilation/FirstWaveComputer.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,23 @@ extension IncrementalCompilationState.FirstWaveComputer {
128128
// In the case where there are no compilation jobs to run on this build (no source-files were changed),
129129
// we can skip running `beforeCompiles` jobs if we also ensure that none of the `afterCompiles` jobs
130130
// have any dependencies on them.
131-
let skipAllJobs = batchedCompilationJobs.isEmpty ? !afterCompileJobsDependOnBeforeCompileJobs() : false
131+
let skipAllJobs = batchedCompilationJobs.isEmpty ? !nonVerifyAfterCompileJobsDependOnBeforeCompileJobs() : false
132132
let mandatoryJobsInOrder = skipAllJobs ? [] : jobsInPhases.beforeCompiles + batchedCompilationJobs
133133
return (initiallySkippedCompileGroups: initiallySkippedCompileGroups,
134134
mandatoryJobsInOrder: mandatoryJobsInOrder)
135135
}
136136

137137
/// Determine if any of the jobs in the `afterCompiles` group depend on outputs produced by jobs in
138-
/// `beforeCompiles` group.
139-
private func afterCompileJobsDependOnBeforeCompileJobs() -> Bool {
140-
let beforeCompileJobOutputs = jobsInPhases.beforeCompiles.reduce(into: Set<TypedVirtualPath>(),
141-
{ (pathSet, job) in pathSet.formUnion(job.outputs) })
142-
return jobsInPhases.afterCompiles.contains {postCompileJob in postCompileJob.inputs.contains(where: beforeCompileJobOutputs.contains)}
138+
/// `beforeCompiles` group, which are not also verification jobs.
139+
private func nonVerifyAfterCompileJobsDependOnBeforeCompileJobs() -> Bool {
140+
let beforeCompileJobOutputs = jobsInPhases.beforeCompiles.reduce(into: Set<TypedVirtualPath>(),
141+
{ (pathSet, job) in pathSet.formUnion(job.outputs) })
142+
let afterCompilesDependnigJobs = jobsInPhases.afterCompiles.filter {postCompileJob in postCompileJob.inputs.contains(where: beforeCompileJobOutputs.contains)}
143+
if afterCompilesDependnigJobs.isEmpty || afterCompilesDependnigJobs.allSatisfy({ $0.kind == .verifyModuleInterface }) {
144+
return false
145+
} else {
146+
return true
147+
}
143148
}
144149

145150
/// Figure out which compilation inputs are *not* mandatory at the start

Tests/SwiftDriverTests/IncrementalCompilationTests.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,14 @@ extension IncrementalCompilationTests {
331331
XCTAssertTrue(mandatoryJobs.isEmpty)
332332
}
333333

334+
func testNullBuildNoVerify() throws {
335+
let extraArguments = ["-experimental-emit-module-separately", "-emit-module", "-emit-module-interface", "-enable-library-evolution", "-verify-emitted-module-interface"]
336+
try buildInitialState(extraArguments: extraArguments)
337+
let driver = try checkNullBuild(extraArguments: extraArguments)
338+
let mandatoryJobs = try XCTUnwrap(driver.incrementalCompilationState?.mandatoryJobsInOrder)
339+
XCTAssertTrue(mandatoryJobs.isEmpty)
340+
}
341+
334342
func testSymlinkModification() throws {
335343
// Remap
336344
// main.swift -> links/main.swift

0 commit comments

Comments
 (0)