Skip to content

Commit f936c29

Browse files
committed
Build: adjust the BuildSystemDelegate hander
llbuild does not make guarantees that the output from subcommands are emitted in complete buffers. This shows up particularly well on Windows. clang will emit diagnostics which get read in different chunks. By emitting these eagerly we would print partial messages which would leave the terminal in the improper state due to the message not being complete. With multiple parallel threads writing the messages partially, we would get splits in the message that would yield unreadable messages. Switch to a buffering approach, buffering the entire content until the command exits. At that time we can emit the complete message in a "single" write (which is locked). This ensures that the output is no longer partially emitted and corrects the rendering with the animated emission on Windows.
1 parent 910552c commit f936c29

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

Sources/Build/BuildOperationBuildSystemDelegateHandler.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ final class BuildOperationBuildSystemDelegateHandler: LLBuildBuildSystemDelegate
410410
/// Swift parsers keyed by llbuild command name.
411411
private var swiftParsers: [String: SwiftCompilerOutputParser] = [:]
412412

413+
private var nonSwiftMessageBuffers: [String:[UInt8]] = [:]
414+
413415
/// The build execution context.
414416
private let buildExecutionContext: BuildExecutionContext
415417

@@ -565,11 +567,7 @@ final class BuildOperationBuildSystemDelegateHandler: LLBuildBuildSystemDelegate
565567
if let swiftParser = swiftParsers[command.name] {
566568
swiftParser.parse(bytes: data)
567569
} else {
568-
queue.async {
569-
self.progressAnimation.clear()
570-
self.outputStream <<< data
571-
self.outputStream.flush()
572-
}
570+
self.nonSwiftMessageBuffers[command.name, default: []] += data
573571
}
574572
}
575573

@@ -578,6 +576,14 @@ final class BuildOperationBuildSystemDelegateHandler: LLBuildBuildSystemDelegate
578576
process: ProcessHandle,
579577
result: CommandExtendedResult
580578
) {
579+
if let buffer = self.nonSwiftMessageBuffers[command.name] {
580+
queue.async {
581+
self.progressAnimation.clear()
582+
self.outputStream <<< buffer
583+
self.outputStream.flush()
584+
self.nonSwiftMessageBuffers[command.name] = nil
585+
}
586+
}
581587
if result.result == .failed {
582588
// The command failed, so we queue up an asynchronous task to see if we have any error messages from the target to provide advice about.
583589
queue.async {

0 commit comments

Comments
 (0)