Skip to content

Commit 1a0b14e

Browse files
committed
Trade A Pack of Booleans for a Formal OptionSet
1 parent 8649aa1 commit 1a0b14e

File tree

7 files changed

+149
-77
lines changed

7 files changed

+149
-77
lines changed

Sources/SwiftDriver/IncrementalCompilation/IncrementalCompilationState.swift

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
import TSCBasic
1313
import Foundation
1414
import SwiftOptions
15+
1516
public class IncrementalCompilationState {
16-
/// Whether cross-module incrementality is enabled
17-
private let isCrossModuleIncrementalBuildEnabled: Bool
1817

1918
/// The oracle for deciding what depends on what. Applies to this whole module.
2019
private let moduleDependencyGraph: ModuleDependencyGraph
@@ -45,24 +44,23 @@ public class IncrementalCompilationState {
4544
/// Return nil if not compiling incrementally
4645
init?(
4746
driver: inout Driver,
47+
options: Options,
4848
jobsInPhases: JobsInPhases
4949
) throws {
5050
guard driver.shouldAttemptIncrementalCompilation()
5151
else {
5252
return nil
5353
}
5454

55-
if driver.parsedOptions.hasArgument(.driverShowIncremental) || driver.showJobLifecycle {
55+
if options.contains(.showIncremental) {
5656
self.reporter = Reporter(diagnosticEngine: driver.diagnosticEngine,
5757
outputFileMap: driver.outputFileMap)
5858
} else {
5959
self.reporter = nil
6060
}
6161

62-
self.isCrossModuleIncrementalBuildEnabled =
63-
driver.parsedOptions.contains(.enableExperimentalCrossModuleIncrementalBuild)
6462
reporter?.report(
65-
"\(self.isCrossModuleIncrementalBuildEnabled ? "Enabling" : "Disabling") incremental cross-module building")
63+
"\(options.contains(.enableCrossModuleIncrementalBuild) ? "Enabling" : "Disabling") incremental cross-module building")
6664

6765

6866
guard let (outputFileMap, buildRecordInfo, outOfDateBuildRecord)
@@ -75,18 +73,19 @@ public class IncrementalCompilationState {
7573
moduleDependencyGraph,
7674
inputsHavingMalformedDependencySources: inputsHavingMalformedDependencySources
7775
) = Self.computeModuleDependencyGraph(
76+
options,
7877
buildRecordInfo,
7978
outOfDateBuildRecord,
8079
outputFileMap,
81-
&driver,
82-
self.reporter,
83-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled)
80+
driver,
81+
self.reporter)
8482
else {
8583
return nil
8684
}
8785

8886
(skippedCompileGroups: self.skippedCompileGroups,
8987
mandatoryJobsInOrder: self.mandatoryJobsInOrder) = try Self.computeInputsAndGroups(
88+
options,
9089
jobsInPhases,
9190
&driver,
9291
buildRecordInfo,
@@ -101,14 +100,18 @@ public class IncrementalCompilationState {
101100
self.driver = driver
102101
}
103102

103+
@_spi(Testing) public var options: Options {
104+
self.moduleDependencyGraph.options
105+
}
106+
104107

105108
private static func computeModuleDependencyGraph(
109+
_ options: Options,
106110
_ buildRecordInfo: BuildRecordInfo,
107111
_ outOfDateBuildRecord: BuildRecord,
108112
_ outputFileMap: OutputFileMap,
109-
_ driver: inout Driver,
110-
_ reporter: Reporter?,
111-
isCrossModuleIncrementalBuildEnabled: Bool
113+
_ driver: Driver,
114+
_ reporter: Reporter?
112115
)
113116
-> (ModuleDependencyGraph,
114117
inputsHavingMalformedDependencySources: [TypedVirtualPath])?
@@ -123,12 +126,10 @@ public class IncrementalCompilationState {
123126
inputs: buildRecordInfo.compilationInputModificationDates.keys,
124127
previousInputs: outOfDateBuildRecord.allInputs,
125128
outputFileMap: outputFileMap,
126-
parsedOptions: &driver.parsedOptions,
129+
options: options,
127130
remarkDisabled: Diagnostic.Message.remark_incremental_compilation_has_been_disabled,
128131
reporter: reporter,
129-
fileSystem: driver.fileSystem,
130-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled
131-
)
132+
fileSystem: driver.fileSystem)
132133
else {
133134
return nil
134135
}
@@ -147,6 +148,7 @@ public class IncrementalCompilationState {
147148
}
148149

149150
private static func computeInputsAndGroups(
151+
_ options: Options,
150152
_ jobsInPhases: JobsInPhases,
151153
_ driver: inout Driver,
152154
_ buildRecordInfo: BuildRecordInfo,
@@ -168,7 +170,7 @@ public class IncrementalCompilationState {
168170
inputsHavingMalformedDependencySources: inputsHavingMalformedDependencySources,
169171
moduleDependencyGraph: moduleDependencyGraph,
170172
outOfDateBuildRecord: outOfDateBuildRecord,
171-
alwaysRebuildDependents: driver.parsedOptions.contains(.driverAlwaysRebuildDependents),
173+
alwaysRebuildDependents: options.contains(.alwaysRebuildDependents),
172174
reporter: reporter)
173175

174176
let skippedCompileGroups = compileGroups.filter {skippedInputs.contains($0.key)}
@@ -699,3 +701,37 @@ extension IncrementalCompilationState {
699701
}
700702
}
701703
}
704+
705+
extension IncrementalCompilationState {
706+
/// Options that control the behavior of various aspects of the
707+
/// incremental build.
708+
public struct Options: OptionSet {
709+
public var rawValue: UInt8
710+
711+
public init(rawValue: UInt8) {
712+
self.rawValue = rawValue
713+
}
714+
715+
/// Be maximally conservative about rebuilding dependents of dirtied files
716+
/// during the incremental build. Dependent files are always scheduled to
717+
/// rebuild.
718+
public static let alwaysRebuildDependents = Options(rawValue: 1 << 0)
719+
/// Print incremental build decisions as remarks.
720+
public static let showIncremental = Options(rawValue: 1 << 1)
721+
/// After integrating each source file dependency graph into the driver's
722+
/// module dependency graph, dump a dot file to the current working
723+
/// directory showing the state of the driver's dependency graph.
724+
///
725+
/// FIXME: This option is not yet implemented.
726+
public static let emitDependencyDotFileAfterEveryImport = Options(rawValue: 1 << 2)
727+
/// After integrating each source file dependency graph, verifies the
728+
/// integrity of the driver's dependency graph and aborts if any errors
729+
/// are detected.
730+
public static let verifyDependencyGraphAfterEveryImport = Options(rawValue: 1 << 3)
731+
/// Enables the cross-module incremental build infrastructure.
732+
///
733+
/// FIXME: This option is transitory. We intend to make this the
734+
/// default behavior. This option should flip to a "disable" bit after that.
735+
public static let enableCrossModuleIncrementalBuild = Options(rawValue: 1 << 4)
736+
}
737+
}

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraph.swift

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,26 @@ import SwiftOptions
3434
// The set of paths to incremental external dependencies known to be in the graph
3535
public internal(set) var incrementalExternalDependencies = Set<ExternalDependency>()
3636

37-
let isCrossModuleIncrementalBuildEnabled: Bool
38-
let verifyDependencyGraphAfterEveryImport: Bool
39-
let emitDependencyDotFileAfterEveryImport: Bool
37+
let options: IncrementalCompilationState.Options
4038
let reporter: IncrementalCompilationState.Reporter?
4139

4240
private let diagnosticEngine: DiagnosticsEngine
4341

4442
public init(
4543
diagnosticEngine: DiagnosticsEngine,
4644
reporter: IncrementalCompilationState.Reporter?,
47-
isCrossModuleIncrementalBuildEnabled: Bool,
48-
emitDependencyDotFileAfterEveryImport: Bool,
49-
verifyDependencyGraphAfterEveryImport: Bool
45+
options: IncrementalCompilationState.Options
5046
) {
51-
self.isCrossModuleIncrementalBuildEnabled = isCrossModuleIncrementalBuildEnabled
52-
self.verifyDependencyGraphAfterEveryImport = verifyDependencyGraphAfterEveryImport
53-
self.emitDependencyDotFileAfterEveryImport = emitDependencyDotFileAfterEveryImport
5447
self.reporter = reporter
5548
self.diagnosticEngine = diagnosticEngine
49+
self.options = options
50+
}
51+
52+
var isCrossModuleIncrementalBuildEnabled: Bool {
53+
self.options.contains(.enableCrossModuleIncrementalBuild)
5654
}
5755
}
56+
5857
// MARK: - initial build only
5958
extension ModuleDependencyGraph {
6059
/// Builds a graph
@@ -65,25 +64,20 @@ extension ModuleDependencyGraph {
6564
inputs: Inputs,
6665
previousInputs: Set<VirtualPath>,
6766
outputFileMap: OutputFileMap?,
68-
parsedOptions: inout ParsedOptions,
67+
options: IncrementalCompilationState.Options,
6968
remarkDisabled: (String) -> Diagnostic.Message,
7069
reporter: IncrementalCompilationState.Reporter?,
71-
fileSystem: FileSystem,
72-
isCrossModuleIncrementalBuildEnabled: Bool
70+
fileSystem: FileSystem
7371
) -> (
7472
ModuleDependencyGraph,
7573
inputsAndMalformedSwiftDeps: [(TypedVirtualPath, VirtualPath)]
7674
)?
7775
where Inputs.Element == TypedVirtualPath
7876
{
79-
let emitOpt = Option.driverEmitFineGrainedDependencyDotFileAfterEveryImport
80-
let veriOpt = Option.driverVerifyFineGrainedDependencyGraphAfterEveryImport
8177
let graph = Self(
8278
diagnosticEngine: diagnosticEngine,
8379
reporter: reporter,
84-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled,
85-
emitDependencyDotFileAfterEveryImport: parsedOptions.contains(emitOpt),
86-
verifyDependencyGraphAfterEveryImport: parsedOptions.contains(veriOpt))
80+
options: options)
8781

8882
let inputsAndSwiftdeps = inputs.map { input in
8983
(input, outputFileMap?.existingOutput(inputFile: input.file,
@@ -118,7 +112,7 @@ extension ModuleDependencyGraph {
118112
reporter: reporter,
119113
diagnosticEngine: diagnosticEngine,
120114
fileSystem: fileSystem,
121-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled)
115+
options: options)
122116
else {
123117
return (input, swiftDepsFile)
124118
}
@@ -188,7 +182,7 @@ extension ModuleDependencyGraph {
188182
reporter: reporter,
189183
diagnosticEngine: diagnosticEngine,
190184
fileSystem: fileSystem,
191-
isCrossModuleIncrementalBuildEnabled: graph.isCrossModuleIncrementalBuildEnabled)
185+
options: graph.options)
192186
return results
193187
}
194188

@@ -258,7 +252,7 @@ extension ModuleDependencyGraph {
258252
reporter: self.reporter,
259253
diagnosticEngine: diagnosticEngine,
260254
fileSystem: fileSystem,
261-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled)
255+
options: self.options)
262256
guard let results = resultsIfOK else {
263257
return nil
264258
}
@@ -437,7 +431,7 @@ extension ModuleDependencyGraph {
437431
on fileSystem: FileSystem,
438432
diagnosticEngine: DiagnosticsEngine,
439433
reporter: IncrementalCompilationState.Reporter?,
440-
isCrossModuleIncrementalBuildEnabled: Bool
434+
options: IncrementalCompilationState.Options
441435
) throws -> ModuleDependencyGraph {
442436
let data = try fileSystem.readFileContents(path)
443437

@@ -456,14 +450,12 @@ extension ModuleDependencyGraph {
456450
init(
457451
diagnosticEngine: DiagnosticsEngine,
458452
reporter: IncrementalCompilationState.Reporter?,
459-
isCrossModuleIncrementalBuildEnabled: Bool
453+
options: IncrementalCompilationState.Options
460454
) {
461455
self.graph = ModuleDependencyGraph(
462456
diagnosticEngine: diagnosticEngine,
463457
reporter: reporter,
464-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled,
465-
emitDependencyDotFileAfterEveryImport: false,
466-
verifyDependencyGraphAfterEveryImport: false)
458+
options: options)
467459
}
468460

469461
func finalizeGraph() -> ModuleDependencyGraph {
@@ -591,7 +583,7 @@ extension ModuleDependencyGraph {
591583
let data = Data(bytesNoCopy: baseAddr, count: buf.count, deallocator: .none)
592584
var visitor = Visitor(diagnosticEngine: diagnosticEngine,
593585
reporter: reporter,
594-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled)
586+
options: options)
595587
try Bitcode.read(stream: data, using: &visitor)
596588
guard let major = visitor.majorVersion,
597589
let minor = visitor.minorVersion,

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraphParts/Integrator.swift

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,24 @@ extension ModuleDependencyGraph {
3838
/// the graph to be integrated into
3939
let destination: ModuleDependencyGraph
4040

41-
let isCrossModuleIncrementalBuildEnabled: Bool
42-
4341
/// Starts with all nodes in dependencySource. Nodes that persist will be removed.
4442
/// After integration is complete, contains the nodes that have disappeared.
4543
var disappearedNodes = [DependencyKey: Graph.Node]()
4644

4745
init(source: SourceFileDependencyGraph,
4846
dependencySource: DependencySource,
49-
destination: ModuleDependencyGraph,
50-
isCrossModuleIncrementalBuildEnabled: Bool)
47+
destination: ModuleDependencyGraph)
5148
{
5249
self.source = source
5350
self.dependencySource = dependencySource
5451
self.destination = destination
55-
self.isCrossModuleIncrementalBuildEnabled = isCrossModuleIncrementalBuildEnabled
5652
self.disappearedNodes = destination.nodeFinder.findNodes(for: dependencySource)
5753
?? [:]
5854
}
55+
56+
var isCrossModuleIncrementalBuildEnabled: Bool {
57+
destination.options.contains(.enableCrossModuleIncrementalBuild)
58+
}
5959
}
6060
}
6161

@@ -69,7 +69,7 @@ extension ModuleDependencyGraph.Integrator {
6969
reporter: IncrementalCompilationState.Reporter?,
7070
diagnosticEngine: DiagnosticsEngine,
7171
fileSystem: FileSystem,
72-
isCrossModuleIncrementalBuildEnabled: Bool
72+
options: IncrementalCompilationState.Options
7373
) -> Results? {
7474
guard let sfdg = try? SourceFileDependencyGraph.read(
7575
from: dependencySource, on: fileSystem)
@@ -79,8 +79,7 @@ extension ModuleDependencyGraph.Integrator {
7979
}
8080
return integrate(from: sfdg,
8181
dependencySource: dependencySource,
82-
into: destination,
83-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled)
82+
into: destination)
8483
}
8584
}
8685
// MARK: - integrate a graph
@@ -92,19 +91,17 @@ extension ModuleDependencyGraph.Integrator {
9291
/*@_spi(Testing)*/ public static func integrate(
9392
from g: SourceFileDependencyGraph,
9493
dependencySource: Graph.DependencySource,
95-
into destination: Graph,
96-
isCrossModuleIncrementalBuildEnabled: Bool
97-
) -> Results {
94+
into destination: Graph
95+
) -> Results {
9896
var integrator = Self(source: g,
9997
dependencySource: dependencySource,
100-
destination: destination,
101-
isCrossModuleIncrementalBuildEnabled: isCrossModuleIncrementalBuildEnabled)
98+
destination: destination)
10299
integrator.integrate()
103100

104-
if destination.verifyDependencyGraphAfterEveryImport {
101+
if destination.options.contains(.verifyDependencyGraphAfterEveryImport) {
105102
integrator.verifyAfterImporting()
106103
}
107-
if destination.emitDependencyDotFileAfterEveryImport {
104+
if destination.options.contains(.emitDependencyDotFileAfterEveryImport) {
108105
destination.emitDotFile(g, dependencySource)
109106
}
110107
return integrator.results

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import TSCBasic
14+
import SwiftOptions
1415

1516
public enum PlanningError: Error, DiagnosticData {
1617
case replReceivedInput
@@ -117,6 +118,7 @@ extension Driver {
117118
// Determine the state for incremental compilation
118119
let incrementalCompilationState = try IncrementalCompilationState(
119120
driver: &self,
121+
options: self.computeIncrementalOptions(),
120122
jobsInPhases: jobsInPhases)
121123

122124
return try (
@@ -130,6 +132,27 @@ extension Driver {
130132
)
131133
}
132134

135+
mutating func computeIncrementalOptions() -> IncrementalCompilationState.Options {
136+
var options: IncrementalCompilationState.Options = []
137+
if self.parsedOptions.contains(.driverAlwaysRebuildDependents) {
138+
options.formUnion(.alwaysRebuildDependents)
139+
}
140+
if self.parsedOptions.contains(.driverShowIncremental) || self.showJobLifecycle {
141+
options.formUnion(.showIncremental)
142+
}
143+
let emitOpt = Option.driverEmitFineGrainedDependencyDotFileAfterEveryImport
144+
if self.parsedOptions.contains(emitOpt) {
145+
options.formUnion(.emitDependencyDotFileAfterEveryImport)
146+
}
147+
let veriOpt = Option.driverVerifyFineGrainedDependencyGraphAfterEveryImport
148+
if self.parsedOptions.contains(veriOpt) {
149+
options.formUnion(.verifyDependencyGraphAfterEveryImport)
150+
}
151+
if self.parsedOptions.contains(.enableExperimentalCrossModuleIncrementalBuild) {
152+
options.formUnion(.enableCrossModuleIncrementalBuild)
153+
}
154+
return options
155+
}
133156

134157
private mutating func addPrecompileModuleDependenciesJobs(addJob: (Job) -> Void) throws {
135158
// If asked, add jobs to precompile module dependencies

0 commit comments

Comments
 (0)