@@ -24,33 +24,40 @@ public class PrebuitModuleGenerationDelegate: JobExecutionDelegate {
24
24
let diagnosticsEngine : DiagnosticsEngine
25
25
let verbose : Bool
26
26
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 ? ) {
28
29
self . diagnosticsEngine = diagnosticsEngine
29
30
self . verbose = verbose
30
31
self . failingCriticalOutputs = Set < VirtualPath > ( jobs. compactMap ( PrebuitModuleGenerationDelegate . getCriticalOutput) )
32
+ self . logPath = logPath
31
33
}
32
34
33
35
/// Dangling jobs are macabi-only modules. We should run those jobs if foundation
34
36
/// is built successfully for macabi.
35
37
public var shouldRunDanglingJobs : Bool {
36
38
return !failingCriticalOutputs. contains ( where: isIosMac)
37
39
}
38
- func printJobInfo( _ job: Job , _ start: Bool ) {
39
- guard verbose else {
40
- return
41
- }
40
+
41
+ func getInputInterfacePath( _ job: Job ) -> AbsolutePath {
42
42
for arg in job. commandLine {
43
43
if case . path( let p) = arg {
44
44
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!
51
46
}
52
47
}
53
48
}
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
+ }
54
61
}
55
62
56
63
static func getCriticalOutput( _ job: Job ) -> VirtualPath ? {
@@ -66,6 +73,24 @@ public class PrebuitModuleGenerationDelegate: JobExecutionDelegate {
66
73
return !failingCriticalOutputs. isEmpty
67
74
}
68
75
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
+
69
94
public func jobFinished( job: Job , result: ProcessResult , pid: Int ) {
70
95
switch result. exitStatus {
71
96
case . terminated( code: let code) :
@@ -86,6 +111,15 @@ public class PrebuitModuleGenerationDelegate: JobExecutionDelegate {
86
111
diagnosticsEngine. emit ( . remark( " \( job. moduleName) interrupted " ) )
87
112
#endif
88
113
}
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
+ }
89
123
}
90
124
91
125
public func jobSkipped( job: Job ) {
0 commit comments