Skip to content

Commit 3c5f7fc

Browse files
committed
[Explicit Module Builds] Add a setting to allow creating a reproducer for errors.
The idea is the same as Clang flag `-gen-reproducer=error` but for explicit module builds. The name of the setting is a subject to change depending on how it ends up being used. Not all module-related issues are crashes, so it is useful to allow creating and sharing reproducers for errors. rdar://158780565
1 parent 7d824ea commit 3c5f7fc

File tree

4 files changed

+22
-5
lines changed

4 files changed

+22
-5
lines changed

Sources/SWBCore/Settings/BuiltinMacros.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ public final class BuiltinMacros {
508508
public static let CLANG_EXPLICIT_MODULES_IGNORE_LIBCLANG_VERSION_MISMATCH = BuiltinMacros.declareBooleanMacro("CLANG_EXPLICIT_MODULES_IGNORE_LIBCLANG_VERSION_MISMATCH")
509509
public static let CLANG_EXPLICIT_MODULES_OUTPUT_PATH = BuiltinMacros.declarePathMacro("CLANG_EXPLICIT_MODULES_OUTPUT_PATH")
510510
public static let SWIFT_EXPLICIT_MODULES_OUTPUT_PATH = BuiltinMacros.declarePathMacro("SWIFT_EXPLICIT_MODULES_OUTPUT_PATH")
511+
public static let CLANG_EXPLICIT_MODULES_ENABLE_REPRODUCER_FOR_ERRORS = BuiltinMacros.declareBooleanMacro("_EXPERIMENTAL_CLANG_EXPLICIT_MODULES_ENABLE_REPRODUCER_FOR_ERRORS")
511512
public static let CLANG_ENABLE_COMPILE_CACHE = BuiltinMacros.declareBooleanMacro("CLANG_ENABLE_COMPILE_CACHE")
512513
public static let CLANG_CACHE_FINE_GRAINED_OUTPUTS = BuiltinMacros.declareEnumMacro("CLANG_CACHE_FINE_GRAINED_OUTPUTS") as EnumMacroDeclaration<FineGrainedCachingSetting>
513514
public static let CLANG_CACHE_FINE_GRAINED_OUTPUTS_VERIFICATION = BuiltinMacros.declareEnumMacro("CLANG_CACHE_FINE_GRAINED_OUTPUTS_VERIFICATION") as EnumMacroDeclaration<FineGrainedCachingVerificationSetting>
@@ -1510,6 +1511,7 @@ public final class BuiltinMacros {
15101511
CLANG_EXPLICIT_MODULES_IGNORE_LIBCLANG_VERSION_MISMATCH,
15111512
CLANG_EXPLICIT_MODULES_OUTPUT_PATH,
15121513
SWIFT_EXPLICIT_MODULES_OUTPUT_PATH,
1514+
CLANG_EXPLICIT_MODULES_ENABLE_REPRODUCER_FOR_ERRORS,
15131515
CLANG_EXTRACT_API_EXEC,
15141516
CLANG_GENERATE_OPTIMIZATION_REMARKS,
15151517
CLANG_GENERATE_OPTIMIZATION_REMARKS_FILTER,

Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,9 @@ public struct ClangExplicitModulesPayload: Serializable, Encodable, Sendable {
361361
public let dependencyFilteringRootPath: Path?
362362
public let reportRequiredTargetDependencies: BooleanWarningLevel
363363
public let verifyingModule: String?
364+
public let shouldGenerateReproducerForErrors: Bool
364365

365-
fileprivate init(uniqueID: String, sourcePath: Path, libclangPath: Path, usesCompilerLauncher: Bool, outputPath: Path, scanningOutputPath: Path, casOptions: CASOptions?, cacheFallbackIfNotAvailable: Bool, dependencyFilteringRootPath: Path?, reportRequiredTargetDependencies: BooleanWarningLevel, verifyingModule: String?) {
366+
fileprivate init(uniqueID: String, sourcePath: Path, libclangPath: Path, usesCompilerLauncher: Bool, outputPath: Path, scanningOutputPath: Path, casOptions: CASOptions?, cacheFallbackIfNotAvailable: Bool, dependencyFilteringRootPath: Path?, reportRequiredTargetDependencies: BooleanWarningLevel, verifyingModule: String?, shouldGenerateReproducerForErrors: Bool) {
366367
self.uniqueID = uniqueID
367368
self.sourcePath = sourcePath
368369
self.libclangPath = libclangPath
@@ -374,10 +375,11 @@ public struct ClangExplicitModulesPayload: Serializable, Encodable, Sendable {
374375
self.dependencyFilteringRootPath = dependencyFilteringRootPath
375376
self.reportRequiredTargetDependencies = reportRequiredTargetDependencies
376377
self.verifyingModule = verifyingModule
378+
self.shouldGenerateReproducerForErrors = shouldGenerateReproducerForErrors
377379
}
378380

379381
public func serialize<T: Serializer>(to serializer: T) {
380-
serializer.serializeAggregate(11) {
382+
serializer.serializeAggregate(12) {
381383
serializer.serialize(uniqueID)
382384
serializer.serialize(sourcePath)
383385
serializer.serialize(libclangPath)
@@ -389,11 +391,12 @@ public struct ClangExplicitModulesPayload: Serializable, Encodable, Sendable {
389391
serializer.serialize(dependencyFilteringRootPath)
390392
serializer.serialize(reportRequiredTargetDependencies)
391393
serializer.serialize(verifyingModule)
394+
serializer.serialize(shouldGenerateReproducerForErrors)
392395
}
393396
}
394397

395398
public init(from deserializer: any Deserializer) throws {
396-
try deserializer.beginAggregate(11)
399+
try deserializer.beginAggregate(12)
397400
self.uniqueID = try deserializer.deserialize()
398401
self.sourcePath = try deserializer.deserialize()
399402
self.libclangPath = try deserializer.deserialize()
@@ -405,6 +408,7 @@ public struct ClangExplicitModulesPayload: Serializable, Encodable, Sendable {
405408
self.dependencyFilteringRootPath = try deserializer.deserialize()
406409
self.reportRequiredTargetDependencies = try deserializer.deserialize()
407410
self.verifyingModule = try deserializer.deserialize()
411+
self.shouldGenerateReproducerForErrors = try deserializer.deserialize()
408412
}
409413

410414
}
@@ -997,7 +1001,8 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible
9971001
// To match the behavior of -MMD, our scan task should filter out headers in the SDK when discovering dependencies. In the long run, libclang should do this for us.
9981002
dependencyFilteringRootPath: isForPCHTask ? nil : cbc.producer.sdk?.path,
9991003
reportRequiredTargetDependencies: cbc.scope.evaluate(BuiltinMacros.DIAGNOSE_MISSING_TARGET_DEPENDENCIES),
1000-
verifyingModule: verifyingModule(cbc)
1004+
verifyingModule: verifyingModule(cbc),
1005+
shouldGenerateReproducerForErrors: cbc.scope.evaluate(BuiltinMacros.CLANG_EXPLICIT_MODULES_ENABLE_REPRODUCER_FOR_ERRORS)
10011006
)
10021007
let explicitModulesSignatureData = cachedBuild ? "cached" : nil
10031008

Sources/SWBCore/TaskResult.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ public enum TaskResult: Hashable, Sendable {
4949
}
5050
}
5151

52+
public var isCrashed: Bool {
53+
if !self.isCancelled, case .exit(exitStatus: .uncaughtSignal, metrics: _) = self {
54+
return true
55+
}
56+
return false
57+
}
58+
5259
public var metrics: CommandMetrics? {
5360
guard case let .exit(_, metrics) = self else {
5461
return nil

Sources/SWBTaskExecution/TaskActions/ClangCompileTaskAction.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,10 @@ public final class ClangCompileTaskAction: TaskAction, BuildValueValidatingTaskA
319319
outputDelegate.emitOutput(ByteString(encodingAsUTF8: commandString) + "\n")
320320
}
321321

322-
if case .some(.failed) = lastResult, case .some(.exit(.uncaughtSignal, _)) = outputDelegate.result {
322+
let shouldGenerateReproducer = (lastResult == .failed) &&
323+
(explicitModulesPayload.shouldGenerateReproducerForErrors ||
324+
(outputDelegate.result?.isCrashed ?? false))
325+
if shouldGenerateReproducer {
323326
do {
324327
if let reproducerMessage = try clangModuleDependencyGraph.generateReproducer(
325328
forFailedDependency: dependencyInfo,

0 commit comments

Comments
 (0)