@@ -34,6 +34,8 @@ public struct Driver {
34
34
case missingProfilingData( String )
35
35
case conditionalCompilationFlagHasRedundantPrefix( String )
36
36
case conditionalCompilationFlagIsNotValidIdentifier( String )
37
+ case baselineGenerationRequiresTopLevelModule( String )
38
+ case optionRequiresAnother( String , String )
37
39
// Explicit Module Build Failures
38
40
case malformedModuleDependency( String , String )
39
41
case missingPCMArguments( String )
@@ -100,6 +102,10 @@ public struct Driver {
100
102
return " unable to load output file map ' \( path) ': no such file or directory "
101
103
case . missingExternalDependency( let moduleName) :
102
104
return " Missing External dependency info for module: \( moduleName) "
105
+ case . baselineGenerationRequiresTopLevelModule( let arg) :
106
+ return " generating a baseline with ' \( arg) ' is only supported with '-emit-module' or '-emit-module-path' "
107
+ case . optionRequiresAnother( let first, let second) :
108
+ return " ' \( first) ' cannot be specified if ' \( second) ' is not present "
103
109
}
104
110
}
105
111
}
@@ -288,6 +294,12 @@ public struct Driver {
288
294
/// Path to the Swift module source information file.
289
295
let moduleSourceInfoPath : VirtualPath . Handle ?
290
296
297
+ /// Path to the module's digester baseline file.
298
+ let digesterBaselinePath : VirtualPath . Handle ?
299
+
300
+ /// The mode the API digester should run in.
301
+ let digesterMode : DigesterMode
302
+
291
303
/// Force the driver to emit the module first and then run compile jobs. This could be used to unblock
292
304
/// dependencies in parallel builds.
293
305
var forceEmitModuleBeforeCompile : Bool = false
@@ -535,6 +547,16 @@ public struct Driver {
535
547
self . numThreads = Self . determineNumThreads ( & parsedOptions, compilerMode: compilerMode, diagnosticsEngine: diagnosticEngine)
536
548
self . numParallelJobs = Self . determineNumParallelJobs ( & parsedOptions, diagnosticsEngine: diagnosticEngine, env: env)
537
549
550
+ var mode = DigesterMode . api
551
+ if let modeArg = parsedOptions. getLastArgument ( . digesterMode) ? . asSingle {
552
+ if let digesterMode = DigesterMode ( rawValue: modeArg) {
553
+ mode = digesterMode
554
+ } else {
555
+ diagnosticsEngine. emit ( Error . invalidArgumentValue ( Option . digesterMode. spelling, modeArg) )
556
+ }
557
+ }
558
+ self . digesterMode = mode
559
+
538
560
Self . validateWarningControlArgs ( & parsedOptions, diagnosticEngine: diagnosticEngine)
539
561
Self . validateProfilingArgs ( & parsedOptions,
540
562
fileSystem: fileSystem,
@@ -587,7 +609,7 @@ public struct Driver {
587
609
diagnosticEngine: diagnosticEngine,
588
610
toolchain: toolchain,
589
611
targetInfo: frontendTargetInfo)
590
-
612
+
591
613
Self . validateSanitizerAddressUseOdrIndicatorFlag ( & parsedOptions, diagnosticEngine: diagnosticsEngine, addressSanitizerEnabled: enabledSanitizers. contains ( . address) )
592
614
593
615
Self . validateSanitizerRecoverArgValues ( & parsedOptions, diagnosticEngine: diagnosticsEngine, enabledSanitizers: enabledSanitizers)
@@ -663,6 +685,15 @@ public struct Driver {
663
685
outputFileMap: self . outputFileMap,
664
686
moduleName: moduleOutputInfo. name,
665
687
projectDirectory: projectDirectory)
688
+ self . digesterBaselinePath = try Self . computeDigesterBaselineOutputPath (
689
+ & parsedOptions,
690
+ moduleOutputPath: self . moduleOutputInfo. output? . outputPath,
691
+ mode: self . digesterMode,
692
+ compilerOutputType: compilerOutputType,
693
+ compilerMode: compilerMode,
694
+ outputFileMap: self . outputFileMap,
695
+ moduleName: moduleOutputInfo. name,
696
+ projectDirectory: projectDirectory)
666
697
self . swiftInterfacePath = try Self . computeSupplementaryOutputPath (
667
698
& parsedOptions, type: . swiftInterface, isOutputOptions: [ . emitModuleInterface] ,
668
699
outputPath: . emitModuleInterfacePath,
@@ -700,6 +731,12 @@ public struct Driver {
700
731
outputFileMap: self . outputFileMap,
701
732
moduleName: moduleOutputInfo. name)
702
733
734
+ Self . validateDigesterArgs ( & parsedOptions,
735
+ moduleOutputInfo: moduleOutputInfo,
736
+ digesterMode: self . digesterMode,
737
+ swiftInterfacePath: self . swiftInterfacePath,
738
+ diagnosticEngine: diagnosticsEngine)
739
+
703
740
try verifyOutputOptions ( )
704
741
}
705
742
@@ -2196,6 +2233,36 @@ extension Driver {
2196
2233
}
2197
2234
}
2198
2235
2236
+ static func validateDigesterArgs( _ parsedOptions: inout ParsedOptions ,
2237
+ moduleOutputInfo: ModuleOutputInfo ,
2238
+ digesterMode: DigesterMode ,
2239
+ swiftInterfacePath: VirtualPath . Handle ? ,
2240
+ diagnosticEngine: DiagnosticsEngine ) {
2241
+ if moduleOutputInfo. output? . isTopLevel != true {
2242
+ for arg in parsedOptions. arguments ( for: . emitDigesterBaseline, . emitDigesterBaselinePath, . compareToBaselinePath) {
2243
+ diagnosticEngine. emit ( Error . baselineGenerationRequiresTopLevelModule ( arg. option. spelling) )
2244
+ }
2245
+ }
2246
+
2247
+ if parsedOptions. hasArgument ( . serializeBreakingChangesPath) && !parsedOptions. hasArgument ( . compareToBaselinePath) {
2248
+ diagnosticEngine. emit ( Error . optionRequiresAnother ( Option . serializeBreakingChangesPath. spelling,
2249
+ Option . compareToBaselinePath. spelling) )
2250
+ }
2251
+ if parsedOptions. hasArgument ( . digesterBreakageAllowlistPath) && !parsedOptions. hasArgument ( . compareToBaselinePath) {
2252
+ diagnosticEngine. emit ( Error . optionRequiresAnother ( Option . digesterBreakageAllowlistPath. spelling,
2253
+ Option . compareToBaselinePath. spelling) )
2254
+ }
2255
+ if digesterMode == . abi && !parsedOptions. hasArgument ( . enableLibraryEvolution) {
2256
+ diagnosticEngine. emit ( Error . optionRequiresAnother ( " \( Option . digesterMode. spelling) abi " ,
2257
+ Option . enableLibraryEvolution. spelling) )
2258
+ }
2259
+ if digesterMode == . abi && swiftInterfacePath == nil {
2260
+ diagnosticEngine. emit ( Error . optionRequiresAnother ( " \( Option . digesterMode. spelling) abi " ,
2261
+ Option . emitModuleInterface. spelling) )
2262
+ }
2263
+ }
2264
+
2265
+
2199
2266
static func validateProfilingArgs( _ parsedOptions: inout ParsedOptions ,
2200
2267
fileSystem: FileSystem ,
2201
2268
workingDirectory: AbsolutePath ? ,
@@ -2650,6 +2717,31 @@ extension Driver {
2650
2717
projectDirectory: projectDirectory)
2651
2718
}
2652
2719
2720
+ static func computeDigesterBaselineOutputPath(
2721
+ _ parsedOptions: inout ParsedOptions ,
2722
+ moduleOutputPath: VirtualPath . Handle ? ,
2723
+ mode: DigesterMode ,
2724
+ compilerOutputType: FileType ? ,
2725
+ compilerMode: CompilerMode ,
2726
+ outputFileMap: OutputFileMap ? ,
2727
+ moduleName: String ,
2728
+ projectDirectory: VirtualPath . Handle ?
2729
+ ) throws -> VirtualPath . Handle ? {
2730
+ // Only emit a baseline if at least of the arguments was provided.
2731
+ guard parsedOptions. hasArgument ( . emitDigesterBaseline, . emitDigesterBaselinePath) else { return nil }
2732
+ return try computeModuleAuxiliaryOutputPath ( & parsedOptions,
2733
+ moduleOutputPath: moduleOutputPath,
2734
+ type: mode. baselineFileType,
2735
+ isOutput: . emitDigesterBaseline,
2736
+ outputPath: . emitDigesterBaselinePath,
2737
+ compilerOutputType: compilerOutputType,
2738
+ compilerMode: compilerMode,
2739
+ outputFileMap: outputFileMap,
2740
+ moduleName: moduleName,
2741
+ projectDirectory: projectDirectory)
2742
+ }
2743
+
2744
+
2653
2745
2654
2746
/// Determine the output path for a module auxiliary output.
2655
2747
static func computeModuleAuxiliaryOutputPath(
0 commit comments