@@ -24,33 +24,40 @@ public class PrebuitModuleGenerationDelegate: JobExecutionDelegate {
2424 let diagnosticsEngine : DiagnosticsEngine
2525 let verbose : Bool
2626 var failingCriticalOutputs : Set < VirtualPath >
27- public init ( _ jobs: [ Job ] , _ diagnosticsEngine: DiagnosticsEngine , _ verbose: Bool ) {
27+ let logPath : AbsolutePath ?
28+ public init ( _ jobs: [ Job ] , _ diagnosticsEngine: DiagnosticsEngine , _ verbose: Bool , logPath: AbsolutePath ? ) {
2829 self . diagnosticsEngine = diagnosticsEngine
2930 self . verbose = verbose
3031 self . failingCriticalOutputs = Set < VirtualPath > ( jobs. compactMap ( PrebuitModuleGenerationDelegate . getCriticalOutput) )
32+ self . logPath = logPath
3133 }
3234
3335 /// Dangling jobs are macabi-only modules. We should run those jobs if foundation
3436 /// is built successfully for macabi.
3537 public var shouldRunDanglingJobs : Bool {
3638 return !failingCriticalOutputs. contains ( where: isIosMac)
3739 }
38- func printJobInfo( _ job: Job , _ start: Bool ) {
39- guard verbose else {
40- return
41- }
40+
41+ func getInputInterfacePath( _ job: Job ) -> AbsolutePath {
4242 for arg in job. commandLine {
4343 if case . path( let p) = arg {
4444 if p. extension == " swiftinterface " {
45- Driver . stdErrQueue. sync {
46- stderrStream <<< ( start ? " started: " : " finished: " )
47- stderrStream <<< p. absolutePath!. pathString <<< " \n "
48- stderrStream. flush ( )
49- }
50- return
45+ return p. absolutePath!
5146 }
5247 }
5348 }
49+ fatalError ( )
50+ }
51+
52+ func printJobInfo( _ job: Job , _ start: Bool ) {
53+ guard verbose else {
54+ return
55+ }
56+ Driver . stdErrQueue. sync {
57+ stderrStream <<< ( start ? " started: " : " finished: " )
58+ stderrStream <<< getInputInterfacePath ( job) . pathString <<< " \n "
59+ stderrStream. flush ( )
60+ }
5461 }
5562
5663 static func getCriticalOutput( _ job: Job ) -> VirtualPath ? {
@@ -66,6 +73,24 @@ public class PrebuitModuleGenerationDelegate: JobExecutionDelegate {
6673 return !failingCriticalOutputs. isEmpty
6774 }
6875
76+ fileprivate func logOutput( _ job: Job , _ result: ProcessResult , _ stdout: Bool ) throws {
77+ guard let logPath = logPath else {
78+ return
79+ }
80+ let content = stdout ? try result. utf8Output ( ) : try result. utf8stderrOutput ( )
81+ guard !content. isEmpty else {
82+ return
83+ }
84+ if !localFileSystem. exists ( logPath) {
85+ try localFileSystem. createDirectory ( logPath, recursive: true )
86+ }
87+ let interfaceBase = getInputInterfacePath ( job) . basenameWithoutExt
88+ let fileName = " \( job. moduleName) - \( interfaceBase) - \( stdout ? " out " : " err " ) .txt "
89+ try localFileSystem. writeFileContents ( logPath. appending ( component: fileName) ) {
90+ $0 <<< content
91+ }
92+ }
93+
6994 public func jobFinished( job: Job , result: ProcessResult , pid: Int ) {
7095 switch result. exitStatus {
7196 case . terminated( code: let code) :
@@ -86,6 +111,15 @@ public class PrebuitModuleGenerationDelegate: JobExecutionDelegate {
86111 diagnosticsEngine. emit ( . remark( " \( job. moduleName) interrupted " ) )
87112#endif
88113 }
114+ do {
115+ try logOutput ( job, result, true )
116+ try logOutput ( job, result, false )
117+ } catch {
118+ Driver . stdErrQueue. sync {
119+ stderrStream <<< " Failed to generate log file "
120+ stderrStream. flush ( )
121+ }
122+ }
89123 }
90124
91125 public func jobSkipped( job: Job ) {
0 commit comments