diff --git a/Sources/SwiftDriver/Jobs/PrebuiltModulesJob.swift b/Sources/SwiftDriver/Jobs/PrebuiltModulesJob.swift index cc96caa0a..f909d1b75 100644 --- a/Sources/SwiftDriver/Jobs/PrebuiltModulesJob.swift +++ b/Sources/SwiftDriver/Jobs/PrebuiltModulesJob.swift @@ -141,6 +141,30 @@ func printJobInfo(_ job: Job, _ start: Bool, _ verbose: Bool) { } } +class JSONOutputDelegate: Encodable { + enum SDKFailureKind: String, Encodable { + case BrokenTextualInterface + } + struct SDKFailure: Encodable { + let inputPath: String + let kind: SDKFailureKind + } + var allFailures = [SDKFailure]() + func jobFinished(_ job: Job, _ result: ProcessResult) { + switch result.exitStatus { + case .terminated(code: let code): + if code == 0 { + break + } else { + allFailures.append(SDKFailure(inputPath: getLastInputPath(job).pathString, + kind: .BrokenTextualInterface)) + } + default: + break + } + } +} + fileprivate class ModuleCompileDelegate: JobExecutionDelegate { var failingModules = Set() var commandMap: [Int: String] = [:] @@ -148,11 +172,14 @@ fileprivate class ModuleCompileDelegate: JobExecutionDelegate { let verbose: Bool var failingCriticalOutputs: Set let logPath: AbsolutePath? - public init(_ jobs: [Job], _ diagnosticsEngine: DiagnosticsEngine, _ verbose: Bool, _ logPath: AbsolutePath?) { + let jsonDelegate: JSONOutputDelegate + init(_ jobs: [Job], _ diagnosticsEngine: DiagnosticsEngine, _ verbose: Bool, + _ logPath: AbsolutePath?, _ jsonDelegate: JSONOutputDelegate) { self.diagnosticsEngine = diagnosticsEngine self.verbose = verbose self.failingCriticalOutputs = Set(jobs.compactMap(ModuleCompileDelegate.getCriticalOutput)) self.logPath = logPath + self.jsonDelegate = jsonDelegate } /// Dangling jobs are macabi-only modules. We should run those jobs if foundation @@ -175,6 +202,7 @@ fileprivate class ModuleCompileDelegate: JobExecutionDelegate { } public func jobFinished(job: Job, result: ProcessResult, pid: Int) { + self.jsonDelegate.jobFinished(job, result) switch result.exitStatus { case .terminated(code: let code): if code == 0 { @@ -249,6 +277,7 @@ fileprivate class ABICheckingDelegate: JobExecutionDelegate { public class PrebuiltModuleGenerationDelegate: JobExecutionDelegate { + fileprivate let jsonDelegate: JSONOutputDelegate fileprivate let compileDelegate: ModuleCompileDelegate fileprivate let abiCheckDelegate: ABICheckingDelegate @@ -264,7 +293,10 @@ public class PrebuiltModuleGenerationDelegate: JobExecutionDelegate { public init(_ jobs: [Job], _ diagnosticsEngine: DiagnosticsEngine, _ verbose: Bool, _ logPath: AbsolutePath?) { - self.compileDelegate = ModuleCompileDelegate(jobs.filter(ModuleCompileDelegate.canHandle), diagnosticsEngine, verbose, logPath) + self.jsonDelegate = JSONOutputDelegate() + self.compileDelegate = ModuleCompileDelegate(jobs.filter(ModuleCompileDelegate.canHandle), + diagnosticsEngine, verbose, logPath, + self.jsonDelegate) self.abiCheckDelegate = ABICheckingDelegate(verbose, logPath) } @@ -285,6 +317,13 @@ public class PrebuiltModuleGenerationDelegate: JobExecutionDelegate { public var hasCriticalFailure: Bool { return compileDelegate.hasCriticalFailure } + public func emitJsonOutput(to path: AbsolutePath) throws { + let data = try JSONEncoder().encode(self.jsonDelegate) + if let json = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers), + let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) { + try localFileSystem.writeFileContents(path, bytes: ByteString(jsonData)) + } + } } public struct PrebuiltModuleInput { diff --git a/Sources/swift-build-sdk-interfaces/main.swift b/Sources/swift-build-sdk-interfaces/main.swift index f79225df2..e34b4a6df 100644 --- a/Sources/swift-build-sdk-interfaces/main.swift +++ b/Sources/swift-build-sdk-interfaces/main.swift @@ -77,6 +77,7 @@ do { exit(1) } let logDir = try getArgumentAsPath("-log-path") + let jsonPath = try getArgumentAsPath("-json-path") let collector = SDKPrebuiltModuleInputsCollector(sdkPath, diagnosticsEngine) var outputDir = try VirtualPath(path: rawOutputDir).absolutePath! // if the given output dir ends with 'prebuilt-modules', we should @@ -174,6 +175,11 @@ do { exit(0) } let delegate = PrebuiltModuleGenerationDelegate(jobs, diagnosticsEngine, verbose, logDir) + defer { + if let jsonPath = jsonPath { + try! delegate.emitJsonOutput(to: jsonPath) + } + } do { try executor.execute(workload: DriverExecutorWorkload.init(jobs, nil, continueBuildingAfterErrors: true), delegate: delegate, numParallelJobs: 128)