Skip to content

Commit 21563e1

Browse files
Plan swiftinterface job and verify interface job together
Always plan the job producing swiftinterface and verifying swiftinterface together. This make sure the swiftinterface exists on disk or in CAS when verification job is running. rdar://147501517
1 parent 3dfab50 commit 21563e1

File tree

4 files changed

+54
-30
lines changed

4 files changed

+54
-30
lines changed

Sources/SwiftDriver/IncrementalCompilation/FirstWaveComputer.swift

+39-28
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,12 @@ extension IncrementalCompilationState {
5151

5252
public func compute(batchJobFormer: inout Driver) throws -> FirstWave {
5353
return try blockingConcurrentAccessOrMutation {
54-
let (initiallySkippedCompileJobs, mandatoryJobsInOrder) =
54+
let (initiallySkippedCompileJobs, mandatoryJobsInOrder, afterCompiles) =
5555
try computeInputsAndGroups(batchJobFormer: &batchJobFormer)
5656
return FirstWave(
5757
initiallySkippedCompileJobs: initiallySkippedCompileJobs,
58-
mandatoryJobsInOrder: mandatoryJobsInOrder)
58+
mandatoryJobsInOrder: mandatoryJobsInOrder,
59+
jobsAfterCompiles: afterCompiles)
5960
}
6061
}
6162
}
@@ -74,34 +75,39 @@ extension IncrementalCompilationState.FirstWaveComputer {
7475
/// listed in fingerprintExternalDependencies.
7576
private func computeInputsAndGroups(batchJobFormer: inout Driver)
7677
throws -> (initiallySkippedCompileJobs: [TypedVirtualPath: Job],
77-
mandatoryJobsInOrder: [Job])
78+
mandatoryJobsInOrder: [Job],
79+
jobsAfterCompiles: [Job])
7880
{
7981
let compileJobs =
8082
Dictionary(uniqueKeysWithValues:
8183
jobsInPhases.compileJobs.map { ($0.primaryInputs[0], $0) })
8284
let buildRecord = self.moduleDependencyGraph.buildRecord
83-
let jobCreatingPch = jobsInPhases.beforeCompiles.first(where: {$0.kind == .generatePCH})
84-
guard !buildRecord.inputInfos.isEmpty else {
85-
func everythingIsMandatory()
86-
throws -> (initiallySkippedCompileJobs: [TypedVirtualPath: Job],
87-
mandatoryJobsInOrder: [Job])
88-
{
89-
let mandatoryCompileJobsInOrder = self.inputFiles.swiftSourceFiles.compactMap {
90-
input -> Job? in
91-
compileJobs[input.typedFile]
92-
}
85+
let jobCreatingPch = jobsInPhases.beforeCompiles.first { $0.kind == .generatePCH }
86+
87+
func everythingIsMandatory()
88+
throws -> (initiallySkippedCompileJobs: [TypedVirtualPath: Job],
89+
mandatoryJobsInOrder: [Job],
90+
jobsAfterCompiles: [Job])
91+
{
92+
let mandatoryCompileJobsInOrder = self.inputFiles.swiftSourceFiles.compactMap {
93+
input -> Job? in
94+
compileJobs[input.typedFile]
95+
}
9396

94-
let mandatoryJobsInOrder = try
95-
jobsInPhases.beforeCompiles +
96-
batchJobFormer.formBatchedJobs(
97-
mandatoryCompileJobsInOrder,
98-
showJobLifecycle: showJobLifecycle,
99-
jobCreatingPch: jobCreatingPch)
97+
let mandatoryJobsInOrder = try
98+
jobsInPhases.beforeCompiles +
99+
batchJobFormer.formBatchedJobs(
100+
mandatoryCompileJobsInOrder,
101+
showJobLifecycle: showJobLifecycle,
102+
jobCreatingPch: jobCreatingPch)
103+
104+
moduleDependencyGraph.setPhase(to: .buildingAfterEachCompilation)
105+
return (initiallySkippedCompileJobs: [:],
106+
mandatoryJobsInOrder: mandatoryJobsInOrder,
107+
jobsAfterCompiles: jobsInPhases.afterCompiles)
108+
}
100109

101-
moduleDependencyGraph.setPhase(to: .buildingAfterEachCompilation)
102-
return (initiallySkippedCompileJobs: [:],
103-
mandatoryJobsInOrder: mandatoryJobsInOrder)
104-
}
110+
guard !buildRecord.inputInfos.isEmpty else {
105111
return try everythingIsMandatory()
106112
}
107113
moduleDependencyGraph.setPhase(to: .updatingAfterCompilation)
@@ -115,9 +121,7 @@ extension IncrementalCompilationState.FirstWaveComputer {
115121

116122
let mandatoryCompileJobsInOrder = inputFiles.compactMap {
117123
input -> Job? in
118-
initiallySkippedInputs.contains(input)
119-
? nil
120-
: compileJobs[input]
124+
return initiallySkippedInputs.contains(input) ? nil : compileJobs[input]
121125
}
122126

123127
let batchedCompilationJobs = try batchJobFormer.formBatchedJobs(
@@ -129,9 +133,16 @@ extension IncrementalCompilationState.FirstWaveComputer {
129133
// we can skip running `beforeCompiles` jobs if we also ensure that none of the `afterCompiles` jobs
130134
// have any dependencies on them.
131135
let skipAllJobs = batchedCompilationJobs.isEmpty ? !nonVerifyAfterCompileJobsDependOnBeforeCompileJobs() : false
132-
let mandatoryJobsInOrder = skipAllJobs ? [] : jobsInPhases.beforeCompiles + batchedCompilationJobs
136+
137+
// Schedule emitModule job together with verify module interface job.
138+
let beforeCompileJobs = skipAllJobs ? [] : jobsInPhases.beforeCompiles
139+
let afterCompileJobs = jobsInPhases.afterCompiles.compactMap { job in
140+
skipAllJobs && job.kind == .verifyModuleInterface ? nil : job
141+
}
142+
let mandatoryJobsInOrder = beforeCompileJobs + batchedCompilationJobs
133143
return (initiallySkippedCompileJobs: initiallySkippedCompileJobs,
134-
mandatoryJobsInOrder: mandatoryJobsInOrder)
144+
mandatoryJobsInOrder: mandatoryJobsInOrder,
145+
jobsAfterCompiles: afterCompileJobs)
135146
}
136147

137148
/// Determine if any of the jobs in the `afterCompiles` group depend on outputs produced by jobs in

Sources/SwiftDriver/IncrementalCompilation/IncrementalCompilationState+Extensions.swift

+2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ extension IncrementalCompilationState {
6969
/// for the first wave to execute.
7070
/// The primaries could be other than .swift files, i.e. .sib
7171
let mandatoryJobsInOrder: [Job]
72+
73+
let jobsAfterCompiles: [Job]
7274
}
7375
}
7476

Sources/SwiftDriver/IncrementalCompilation/IncrementalCompilationState.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public final class IncrementalCompilationState {
7777
jobsInPhases.allJobs.first(where: {$0.kind == .generatePCH}),
7878
&driver)
7979
self.mandatoryJobsInOrder = firstWave.mandatoryJobsInOrder
80-
self.jobsAfterCompiles = jobsInPhases.afterCompiles
80+
self.jobsAfterCompiles = firstWave.jobsAfterCompiles
8181
}
8282

8383
/// Allow concurrent access to while preventing mutation of ``IncrementalCompilationState/protectedState``

Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift

+12-1
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
815815
}
816816
"""))
817817

818+
let swiftInterfaceOutput = path.appending(component: "Test.swiftinterface")
818819
let cHeadersPath: AbsolutePath =
819820
try testInputsPath.appending(component: "ExplicitModuleBuilds")
820821
.appending(component: "CHeaders")
@@ -825,11 +826,12 @@ final class ExplicitModuleBuildTests: XCTestCase {
825826
let invocationArguments = ["swiftc",
826827
"-incremental", "-c",
827828
"-emit-module",
828-
"-enable-library-evolution", "-emit-module-interface", "-driver-show-incremental", "-v",
829+
"-enable-library-evolution", "-emit-module-interface", "-driver-show-incremental",
829830
"-Xcc", "-Xclang", "-Xcc", "-fbuiltin-headers-in-system-modules",
830831
"-I", cHeadersPath.nativePathString(escaped: true),
831832
"-I", swiftModuleInterfacesPath.nativePathString(escaped: true),
832833
"-explicit-module-build",
834+
"-emit-module-interface-path", swiftInterfaceOutput.nativePathString(escaped: true),
833835
"-output-file-map", outputFileMap.nativePathString(escaped: true),
834836
"-module-cache-path", moduleCachePath.nativePathString(escaped: true),
835837
"-working-directory", path.nativePathString(escaped: true),
@@ -843,6 +845,15 @@ final class ExplicitModuleBuildTests: XCTestCase {
843845
let incrementalJobs = try incrementalDriver.planBuild()
844846
try incrementalDriver.run(jobs: incrementalJobs)
845847
XCTAssertFalse(incrementalDriver.diagnosticEngine.hasErrors)
848+
849+
// TODO: emitModule job should run again if interface is deleted.
850+
// try localFileSystem.removeFileTree(swiftInterfaceOutput)
851+
852+
// This should be a null build but it is actually building the main module due to the previous build of all the modules.
853+
var reDriver = try Driver(args: invocationArguments + ["-color-diagnostics"])
854+
let reJobs = try reDriver.planBuild()
855+
XCTAssertFalse(reJobs.contains { $0.kind == .emitModule })
856+
XCTAssertFalse(reJobs.contains { $0.kind == .verifyModuleInterface })
846857
}
847858
}
848859

0 commit comments

Comments
 (0)