@@ -35,6 +35,8 @@ public struct Driver {
35
35
case missingProfilingData( String )
36
36
case conditionalCompilationFlagHasRedundantPrefix( String )
37
37
case conditionalCompilationFlagIsNotValidIdentifier( String )
38
+ case baselineGenerationRequiresTopLevelModule( String )
39
+ case optionRequiresAnother( String , String )
38
40
// Explicit Module Build Failures
39
41
case malformedModuleDependency( String , String )
40
42
case missingPCMArguments( String )
@@ -103,6 +105,10 @@ public struct Driver {
103
105
return " unable to load output file map ' \( path) ': no such file or directory "
104
106
case . missingExternalDependency( let moduleName) :
105
107
return " Missing External dependency info for module: \( moduleName) "
108
+ case . baselineGenerationRequiresTopLevelModule( let arg) :
109
+ return " generating a baseline with ' \( arg) ' is only supported with '-emit-module' or '-emit-module-path' "
110
+ case . optionRequiresAnother( let first, let second) :
111
+ return " ' \( first) ' cannot be specified if ' \( second) ' is not present "
106
112
}
107
113
}
108
114
}
@@ -291,6 +297,12 @@ public struct Driver {
291
297
/// Path to the Swift module source information file.
292
298
let moduleSourceInfoPath : VirtualPath . Handle ?
293
299
300
+ /// Path to the module's digester baseline file.
301
+ let digesterBaselinePath : VirtualPath . Handle ?
302
+
303
+ /// The mode the API digester should run in.
304
+ let digesterMode : DigesterMode
305
+
294
306
/// Force the driver to emit the module first and then run compile jobs. This could be used to unblock
295
307
/// dependencies in parallel builds.
296
308
var forceEmitModuleBeforeCompile : Bool = false
@@ -539,6 +551,16 @@ public struct Driver {
539
551
self . numThreads = Self . determineNumThreads ( & parsedOptions, compilerMode: compilerMode, diagnosticsEngine: diagnosticEngine)
540
552
self . numParallelJobs = Self . determineNumParallelJobs ( & parsedOptions, diagnosticsEngine: diagnosticEngine, env: env)
541
553
554
+ var mode = DigesterMode . api
555
+ if let modeArg = parsedOptions. getLastArgument ( . digesterMode) ? . asSingle {
556
+ if let digesterMode = DigesterMode ( rawValue: modeArg) {
557
+ mode = digesterMode
558
+ } else {
559
+ diagnosticsEngine. emit ( Error . invalidArgumentValue ( Option . digesterMode. spelling, modeArg) )
560
+ }
561
+ }
562
+ self . digesterMode = mode
563
+
542
564
Self . validateWarningControlArgs ( & parsedOptions, diagnosticEngine: diagnosticEngine)
543
565
Self . validateProfilingArgs ( & parsedOptions,
544
566
fileSystem: fileSystem,
@@ -591,7 +613,7 @@ public struct Driver {
591
613
diagnosticEngine: diagnosticEngine,
592
614
toolchain: toolchain,
593
615
targetInfo: frontendTargetInfo)
594
-
616
+
595
617
Self . validateSanitizerAddressUseOdrIndicatorFlag ( & parsedOptions, diagnosticEngine: diagnosticsEngine, addressSanitizerEnabled: enabledSanitizers. contains ( . address) )
596
618
597
619
Self . validateSanitizerRecoverArgValues ( & parsedOptions, diagnosticEngine: diagnosticsEngine, enabledSanitizers: enabledSanitizers)
@@ -667,6 +689,15 @@ public struct Driver {
667
689
outputFileMap: self . outputFileMap,
668
690
moduleName: moduleOutputInfo. name,
669
691
projectDirectory: projectDirectory)
692
+ self . digesterBaselinePath = try Self . computeDigesterBaselineOutputPath (
693
+ & parsedOptions,
694
+ moduleOutputPath: self . moduleOutputInfo. output? . outputPath,
695
+ mode: self . digesterMode,
696
+ compilerOutputType: compilerOutputType,
697
+ compilerMode: compilerMode,
698
+ outputFileMap: self . outputFileMap,
699
+ moduleName: moduleOutputInfo. name,
700
+ projectDirectory: projectDirectory)
670
701
self . swiftInterfacePath = try Self . computeSupplementaryOutputPath (
671
702
& parsedOptions, type: . swiftInterface, isOutputOptions: [ . emitModuleInterface] ,
672
703
outputPath: . emitModuleInterfacePath,
@@ -704,6 +735,12 @@ public struct Driver {
704
735
outputFileMap: self . outputFileMap,
705
736
moduleName: moduleOutputInfo. name)
706
737
738
+ Self . validateDigesterArgs ( & parsedOptions,
739
+ moduleOutputInfo: moduleOutputInfo,
740
+ digesterMode: self . digesterMode,
741
+ swiftInterfacePath: self . swiftInterfacePath,
742
+ diagnosticEngine: diagnosticsEngine)
743
+
707
744
try verifyOutputOptions ( )
708
745
}
709
746
@@ -2182,6 +2219,36 @@ extension Driver {
2182
2219
}
2183
2220
}
2184
2221
2222
+ static func validateDigesterArgs( _ parsedOptions: inout ParsedOptions ,
2223
+ moduleOutputInfo: ModuleOutputInfo ,
2224
+ digesterMode: DigesterMode ,
2225
+ swiftInterfacePath: VirtualPath . Handle ? ,
2226
+ diagnosticEngine: DiagnosticsEngine ) {
2227
+ if moduleOutputInfo. output? . isTopLevel != true {
2228
+ for arg in parsedOptions. arguments ( for: . emitDigesterBaseline, . emitDigesterBaselinePath, . compareToBaselinePath) {
2229
+ diagnosticEngine. emit ( Error . baselineGenerationRequiresTopLevelModule ( arg. option. spelling) )
2230
+ }
2231
+ }
2232
+
2233
+ if parsedOptions. hasArgument ( . serializeBreakingChangesPath) && !parsedOptions. hasArgument ( . compareToBaselinePath) {
2234
+ diagnosticEngine. emit ( Error . optionRequiresAnother ( Option . serializeBreakingChangesPath. spelling,
2235
+ Option . compareToBaselinePath. spelling) )
2236
+ }
2237
+ if parsedOptions. hasArgument ( . digesterBreakageAllowlistPath) && !parsedOptions. hasArgument ( . compareToBaselinePath) {
2238
+ diagnosticEngine. emit ( Error . optionRequiresAnother ( Option . digesterBreakageAllowlistPath. spelling,
2239
+ Option . compareToBaselinePath. spelling) )
2240
+ }
2241
+ if digesterMode == . abi && !parsedOptions. hasArgument ( . enableLibraryEvolution) {
2242
+ diagnosticEngine. emit ( Error . optionRequiresAnother ( " \( Option . digesterMode. spelling) abi " ,
2243
+ Option . enableLibraryEvolution. spelling) )
2244
+ }
2245
+ if digesterMode == . abi && swiftInterfacePath == nil {
2246
+ diagnosticEngine. emit ( Error . optionRequiresAnother ( " \( Option . digesterMode. spelling) abi " ,
2247
+ Option . emitModuleInterface. spelling) )
2248
+ }
2249
+ }
2250
+
2251
+
2185
2252
static func validateProfilingArgs( _ parsedOptions: inout ParsedOptions ,
2186
2253
fileSystem: FileSystem ,
2187
2254
workingDirectory: AbsolutePath ? ,
@@ -2634,6 +2701,31 @@ extension Driver {
2634
2701
projectDirectory: projectDirectory)
2635
2702
}
2636
2703
2704
+ static func computeDigesterBaselineOutputPath(
2705
+ _ parsedOptions: inout ParsedOptions ,
2706
+ moduleOutputPath: VirtualPath . Handle ? ,
2707
+ mode: DigesterMode ,
2708
+ compilerOutputType: FileType ? ,
2709
+ compilerMode: CompilerMode ,
2710
+ outputFileMap: OutputFileMap ? ,
2711
+ moduleName: String ,
2712
+ projectDirectory: VirtualPath . Handle ?
2713
+ ) throws -> VirtualPath . Handle ? {
2714
+ // Only emit a baseline if at least of the arguments was provided.
2715
+ guard parsedOptions. hasArgument ( . emitDigesterBaseline, . emitDigesterBaselinePath) else { return nil }
2716
+ return try computeModuleAuxiliaryOutputPath ( & parsedOptions,
2717
+ moduleOutputPath: moduleOutputPath,
2718
+ type: mode. baselineFileType,
2719
+ isOutput: . emitDigesterBaseline,
2720
+ outputPath: . emitDigesterBaselinePath,
2721
+ compilerOutputType: compilerOutputType,
2722
+ compilerMode: compilerMode,
2723
+ outputFileMap: outputFileMap,
2724
+ moduleName: moduleName,
2725
+ projectDirectory: projectDirectory)
2726
+ }
2727
+
2728
+
2637
2729
2638
2730
/// Determine the output path for a module auxiliary output.
2639
2731
static func computeModuleAuxiliaryOutputPath(
0 commit comments