authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-17 17:00:41-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:10-08:00
log608145c2f07d90c46cdaa8bc2013f31b965a5b8b
treea8704744b3808887c25ecf7b674eed030b2f6c7d
parentaa57793b680b3da05f1d888b4df15807905e57c8

fix more fallout from locking stderr


35 files changed, 446 insertions(+), 458 deletions(-)

lib/compiler/aro/aro/Diagnostics.zig+13-15
...@@ -24,20 +24,21 @@ pub const Message = struct {...@@ -24,20 +24,21 @@ pub const Message = struct {
24 @"fatal error",24 @"fatal error",
25 };25 };
2626
27 pub fn write(msg: Message, w: *std.Io.Writer, config: std.Io.File.Writer.Mode, details: bool) std.Io.tty.Config.SetColorError!void {27 pub fn write(msg: Message, t: std.Io.Terminal, details: bool) std.Io.Terminal.SetColorError!void {
28 try config.setColor(w, .bold);28 const w = t.writer;
29 try t.setColor(.bold);
29 if (msg.location) |loc| {30 if (msg.location) |loc| {
30 try w.print("{s}:{d}:{d}: ", .{ loc.path, loc.line_no, loc.col });31 try w.print("{s}:{d}:{d}: ", .{ loc.path, loc.line_no, loc.col });
31 }32 }
32 switch (msg.effective_kind) {33 switch (msg.effective_kind) {
33 .@"fatal error", .@"error" => try config.setColor(w, .bright_red),34 .@"fatal error", .@"error" => try t.setColor(.bright_red),
34 .note => try config.setColor(w, .bright_cyan),35 .note => try t.setColor(.bright_cyan),
35 .warning => try config.setColor(w, .bright_magenta),36 .warning => try t.setColor(.bright_magenta),
36 .off => unreachable,37 .off => unreachable,
37 }38 }
38 try w.print("{s}: ", .{@tagName(msg.effective_kind)});39 try w.print("{s}: ", .{@tagName(msg.effective_kind)});
3940
40 try config.setColor(w, .white);41 try t.setColor(.white);
41 try w.writeAll(msg.text);42 try w.writeAll(msg.text);
42 if (msg.opt) |some| {43 if (msg.opt) |some| {
43 if (msg.effective_kind == .@"error" and msg.kind != .@"error") {44 if (msg.effective_kind == .@"error" and msg.kind != .@"error") {
...@@ -55,17 +56,17 @@ pub const Message = struct {...@@ -55,17 +56,17 @@ pub const Message = struct {
5556
56 if (!details or msg.location == null) {57 if (!details or msg.location == null) {
57 try w.writeAll("\n");58 try w.writeAll("\n");
58 try config.setColor(w, .reset);59 try t.setColor(.reset);
59 } else {60 } else {
60 const loc = msg.location.?;61 const loc = msg.location.?;
61 const trailer = if (loc.end_with_splice) "\\ " else "";62 const trailer = if (loc.end_with_splice) "\\ " else "";
62 try config.setColor(w, .reset);63 try t.setColor(.reset);
63 try w.print("\n{s}{s}\n", .{ loc.line, trailer });64 try w.print("\n{s}{s}\n", .{ loc.line, trailer });
64 try w.splatByteAll(' ', loc.width);65 try w.splatByteAll(' ', loc.width);
65 try config.setColor(w, .bold);66 try t.setColor(.bold);
66 try config.setColor(w, .bright_green);67 try t.setColor(.bright_green);
67 try w.writeAll("^\n");68 try w.writeAll("^\n");
68 try config.setColor(w, .reset);69 try t.setColor(.reset);
69 }70 }
70 try w.flush();71 try w.flush();
71 }72 }
...@@ -290,10 +291,7 @@ pub const State = struct {...@@ -290,10 +291,7 @@ pub const State = struct {
290const Diagnostics = @This();291const Diagnostics = @This();
291292
292output: union(enum) {293output: union(enum) {
293 to_writer: struct {294 to_writer: std.Io.Terminal,
294 writer: *std.Io.Writer,
295 color: std.Io.File.Writer.Mode,
296 },
297 to_list: struct {295 to_list: struct {
298 messages: std.ArrayList(Message) = .empty,296 messages: std.ArrayList(Message) = .empty,
299 arena: std.heap.ArenaAllocator,297 arena: std.heap.ArenaAllocator,
lib/compiler/build_runner.zig+169-169
...@@ -286,8 +286,8 @@ pub fn main() !void {...@@ -286,8 +286,8 @@ pub fn main() !void {
286 const next_arg = nextArg(args, &arg_idx) orelse286 const next_arg = nextArg(args, &arg_idx) orelse
287 fatalWithHint("expected u16 after '{s}'", .{arg});287 fatalWithHint("expected u16 after '{s}'", .{arg});
288 debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| {288 debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| {
289 fatal("unable to parse debounce interval '{s}' as unsigned 16-bit integer: {s}\n", .{289 fatal("unable to parse debounce interval '{s}' as unsigned 16-bit integer: {t}\n", .{
290 next_arg, @errorName(err),290 next_arg, err,
291 });291 });
292 };292 };
293 } else if (mem.eql(u8, arg, "--webui")) {293 } else if (mem.eql(u8, arg, "--webui")) {
...@@ -429,6 +429,12 @@ pub fn main() !void {...@@ -429,6 +429,12 @@ pub fn main() !void {
429 }429 }
430 }430 }
431431
432 graph.stderr_mode = switch (color) {
433 .auto => try .detect(io, .stderr()),
434 .on => .escape_codes,
435 .off => .no_color,
436 };
437
432 if (webui_listen != null) {438 if (webui_listen != null) {
433 if (watch) fatal("using '--webui' and '--watch' together is not yet supported; consider omitting '--watch' in favour of the web UI \"Rebuild\" button", .{});439 if (watch) fatal("using '--webui' and '--watch' together is not yet supported; consider omitting '--watch' in favour of the web UI \"Rebuild\" button", .{});
434 if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{});440 if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{});
...@@ -522,7 +528,7 @@ pub fn main() !void {...@@ -522,7 +528,7 @@ pub fn main() !void {
522 // Perhaps in the future there could be an Advanced Options flag528 // Perhaps in the future there could be an Advanced Options flag
523 // such as --debug-build-runner-leaks which would make this code529 // such as --debug-build-runner-leaks which would make this code
524 // return instead of calling exit.530 // return instead of calling exit.
525 _ = io.lockStderrWriter(&.{}) catch {};531 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
526 process.exit(1);532 process.exit(1);
527 },533 },
528 else => |e| return e,534 else => |e| return e,
...@@ -554,9 +560,9 @@ pub fn main() !void {...@@ -554,9 +560,9 @@ pub fn main() !void {
554 }560 }
555561
556 rebuild: while (true) : (if (run.error_style.clearOnUpdate()) {562 rebuild: while (true) : (if (run.error_style.clearOnUpdate()) {
557 const stderr = try io.lockStderrWriter(&stdio_buffer_allocation);563 const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode);
558 defer io.unlockStderrWriter();564 defer io.unlockStderr();
559 try stderr.writeAllUnescaped("\x1B[2J\x1B[3J\x1B[H");565 try stderr.file_writer.interface.writeAll("\x1B[2J\x1B[3J\x1B[H");
560 }) {566 }) {
561 if (run.web_server) |*ws| ws.startBuild();567 if (run.web_server) |*ws| ws.startBuild();
562568
...@@ -730,7 +736,8 @@ fn runStepNames(...@@ -730,7 +736,8 @@ fn runStepNames(
730 fuzz: ?std.Build.Fuzz.Mode,736 fuzz: ?std.Build.Fuzz.Mode,
731) !void {737) !void {
732 const gpa = run.gpa;738 const gpa = run.gpa;
733 const io = b.graph.io;739 const graph = b.graph;
740 const io = graph.io;
734 const step_stack = &run.step_stack;741 const step_stack = &run.step_stack;
735742
736 {743 {
...@@ -856,20 +863,19 @@ fn runStepNames(...@@ -856,20 +863,19 @@ fn runStepNames(
856 .none => break :summary,863 .none => break :summary,
857 }864 }
858865
859 const stderr = try io.lockStderrWriter(&stdio_buffer_allocation);866 const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode);
860 defer io.unlockStderrWriter();867 defer io.unlockStderr();
861868 const t = stderr.terminal();
862 const w = &stderr.interface;869 const w = &stderr.file_writer.interface;
863 const fwm = stderr.mode;
864870
865 const total_count = success_count + failure_count + pending_count + skipped_count;871 const total_count = success_count + failure_count + pending_count + skipped_count;
866 fwm.setColor(w, .cyan) catch {};872 t.setColor(.cyan) catch {};
867 fwm.setColor(w, .bold) catch {};873 t.setColor(.bold) catch {};
868 w.writeAll("Build Summary: ") catch {};874 w.writeAll("Build Summary: ") catch {};
869 fwm.setColor(w, .reset) catch {};875 t.setColor(.reset) catch {};
870 w.print("{d}/{d} steps succeeded", .{ success_count, total_count }) catch {};876 w.print("{d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
871 {877 {
872 fwm.setColor(w, .dim) catch {};878 t.setColor(.dim) catch {};
873 var first = true;879 var first = true;
874 if (skipped_count > 0) {880 if (skipped_count > 0) {
875 w.print("{s}{d} skipped", .{ if (first) " (" else ", ", skipped_count }) catch {};881 w.print("{s}{d} skipped", .{ if (first) " (" else ", ", skipped_count }) catch {};
...@@ -880,12 +886,12 @@ fn runStepNames(...@@ -880,12 +886,12 @@ fn runStepNames(
880 first = false;886 first = false;
881 }887 }
882 if (!first) w.writeByte(')') catch {};888 if (!first) w.writeByte(')') catch {};
883 fwm.setColor(w, .reset) catch {};889 t.setColor(.reset) catch {};
884 }890 }
885891
886 if (test_count > 0) {892 if (test_count > 0) {
887 w.print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {};893 w.print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {};
888 fwm.setColor(w, .dim) catch {};894 t.setColor(.dim) catch {};
889 var first = true;895 var first = true;
890 if (test_skip_count > 0) {896 if (test_skip_count > 0) {
891 w.print("{s}{d} skipped", .{ if (first) " (" else ", ", test_skip_count }) catch {};897 w.print("{s}{d} skipped", .{ if (first) " (" else ", ", test_skip_count }) catch {};
...@@ -904,7 +910,7 @@ fn runStepNames(...@@ -904,7 +910,7 @@ fn runStepNames(
904 first = false;910 first = false;
905 }911 }
906 if (!first) w.writeByte(')') catch {};912 if (!first) w.writeByte(')') catch {};
907 fwm.setColor(w, .reset) catch {};913 t.setColor(.reset) catch {};
908 }914 }
909915
910 w.writeAll("\n") catch {};916 w.writeAll("\n") catch {};
...@@ -918,7 +924,7 @@ fn runStepNames(...@@ -918,7 +924,7 @@ fn runStepNames(
918 var print_node: PrintNode = .{ .parent = null };924 var print_node: PrintNode = .{ .parent = null };
919 if (step_names.len == 0) {925 if (step_names.len == 0) {
920 print_node.last = true;926 print_node.last = true;
921 printTreeStep(b, b.default_step, run, w, fwm, &print_node, &step_stack_copy) catch {};927 printTreeStep(b, b.default_step, run, t, &print_node, &step_stack_copy) catch {};
922 } else {928 } else {
923 const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: {929 const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: {
924 var i: usize = step_names.len;930 var i: usize = step_names.len;
...@@ -937,7 +943,7 @@ fn runStepNames(...@@ -937,7 +943,7 @@ fn runStepNames(
937 for (step_names, 0..) |step_name, i| {943 for (step_names, 0..) |step_name, i| {
938 const tls = b.top_level_steps.get(step_name).?;944 const tls = b.top_level_steps.get(step_name).?;
939 print_node.last = i + 1 == last_index;945 print_node.last = i + 1 == last_index;
940 printTreeStep(b, &tls.step, run, w, fwm, &print_node, &step_stack_copy) catch {};946 printTreeStep(b, &tls.step, run, t, &print_node, &step_stack_copy) catch {};
941 }947 }
942 }948 }
943 w.writeByte('\n') catch {};949 w.writeByte('\n') catch {};
...@@ -954,7 +960,7 @@ fn runStepNames(...@@ -954,7 +960,7 @@ fn runStepNames(
954 if (run.error_style.verboseContext()) break :code 1; // failure; print build command960 if (run.error_style.verboseContext()) break :code 1; // failure; print build command
955 break :code 2; // failure; do not print build command961 break :code 2; // failure; do not print build command
956 };962 };
957 _ = io.lockStderrWriter(&.{}) catch {};963 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
958 process.exit(code);964 process.exit(code);
959}965}
960966
...@@ -963,33 +969,30 @@ const PrintNode = struct {...@@ -963,33 +969,30 @@ const PrintNode = struct {
963 last: bool = false,969 last: bool = false,
964};970};
965971
966fn printPrefix(node: *PrintNode, w: *Writer, fwm: File.Writer.Mode) !void {972fn printPrefix(node: *PrintNode, stderr: Io.Terminal) !void {
967 const parent = node.parent orelse return;973 const parent = node.parent orelse return;
974 const writer = stderr.writer;
968 if (parent.parent == null) return;975 if (parent.parent == null) return;
969 try printPrefix(parent, w, fwm);976 try printPrefix(parent, stderr);
970 if (parent.last) {977 if (parent.last) {
971 try w.writeAll(" ");978 try writer.writeAll(" ");
972 } else {979 } else {
973 try w.writeAll(switch (fwm) {980 try writer.writeAll(switch (stderr.mode) {
974 .terminal_escaped => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │981 .escape_codes => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │
975 else => "| ",982 else => "| ",
976 });983 });
977 }984 }
978}985}
979986
980fn printChildNodePrefix(w: *Writer, fwm: File.Writer.Mode) !void {987fn printChildNodePrefix(stderr: Io.Terminal) !void {
981 try w.writeAll(switch (fwm) {988 try stderr.writer.writeAll(switch (stderr.mode) {
982 .terminal_escaped => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─989 .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─
983 else => "+- ",990 else => "+- ",
984 });991 });
985}992}
986993
987fn printStepStatus(994fn printStepStatus(s: *Step, stderr: Io.Terminal, run: *const Run) !void {
988 s: *Step,995 const writer = stderr.writer;
989 stderr: *Writer,
990 fwm: File.Writer.Mode,
991 run: *const Run,
992) !void {
993 switch (s.state) {996 switch (s.state) {
994 .precheck_unstarted => unreachable,997 .precheck_unstarted => unreachable,
995 .precheck_started => unreachable,998 .precheck_started => unreachable,
...@@ -997,139 +1000,135 @@ fn printStepStatus(...@@ -997,139 +1000,135 @@ fn printStepStatus(
997 .running => unreachable,1000 .running => unreachable,
9981001
999 .dependency_failure => {1002 .dependency_failure => {
1000 try fwm.setColor(stderr, .dim);1003 try stderr.setColor(.dim);
1001 try stderr.writeAll(" transitive failure\n");1004 try writer.writeAll(" transitive failure\n");
1002 try fwm.setColor(stderr, .reset);1005 try stderr.setColor(.reset);
1003 },1006 },
10041007
1005 .success => {1008 .success => {
1006 try fwm.setColor(stderr, .green);1009 try stderr.setColor(.green);
1007 if (s.result_cached) {1010 if (s.result_cached) {
1008 try stderr.writeAll(" cached");1011 try writer.writeAll(" cached");
1009 } else if (s.test_results.test_count > 0) {1012 } else if (s.test_results.test_count > 0) {
1010 const pass_count = s.test_results.passCount();1013 const pass_count = s.test_results.passCount();
1011 assert(s.test_results.test_count == pass_count + s.test_results.skip_count);1014 assert(s.test_results.test_count == pass_count + s.test_results.skip_count);
1012 try stderr.print(" {d} pass", .{pass_count});1015 try writer.print(" {d} pass", .{pass_count});
1013 if (s.test_results.skip_count > 0) {1016 if (s.test_results.skip_count > 0) {
1014 try fwm.setColor(stderr, .reset);1017 try stderr.setColor(.reset);
1015 try stderr.writeAll(", ");1018 try writer.writeAll(", ");
1016 try fwm.setColor(stderr, .yellow);1019 try stderr.setColor(.yellow);
1017 try stderr.print("{d} skip", .{s.test_results.skip_count});1020 try writer.print("{d} skip", .{s.test_results.skip_count});
1018 }1021 }
1019 try fwm.setColor(stderr, .reset);1022 try stderr.setColor(.reset);
1020 try stderr.print(" ({d} total)", .{s.test_results.test_count});1023 try writer.print(" ({d} total)", .{s.test_results.test_count});
1021 } else {1024 } else {
1022 try stderr.writeAll(" success");1025 try writer.writeAll(" success");
1023 }1026 }
1024 try fwm.setColor(stderr, .reset);1027 try stderr.setColor(.reset);
1025 if (s.result_duration_ns) |ns| {1028 if (s.result_duration_ns) |ns| {
1026 try fwm.setColor(stderr, .dim);1029 try stderr.setColor(.dim);
1027 if (ns >= std.time.ns_per_min) {1030 if (ns >= std.time.ns_per_min) {
1028 try stderr.print(" {d}m", .{ns / std.time.ns_per_min});1031 try writer.print(" {d}m", .{ns / std.time.ns_per_min});
1029 } else if (ns >= std.time.ns_per_s) {1032 } else if (ns >= std.time.ns_per_s) {
1030 try stderr.print(" {d}s", .{ns / std.time.ns_per_s});1033 try writer.print(" {d}s", .{ns / std.time.ns_per_s});
1031 } else if (ns >= std.time.ns_per_ms) {1034 } else if (ns >= std.time.ns_per_ms) {
1032 try stderr.print(" {d}ms", .{ns / std.time.ns_per_ms});1035 try writer.print(" {d}ms", .{ns / std.time.ns_per_ms});
1033 } else if (ns >= std.time.ns_per_us) {1036 } else if (ns >= std.time.ns_per_us) {
1034 try stderr.print(" {d}us", .{ns / std.time.ns_per_us});1037 try writer.print(" {d}us", .{ns / std.time.ns_per_us});
1035 } else {1038 } else {
1036 try stderr.print(" {d}ns", .{ns});1039 try writer.print(" {d}ns", .{ns});
1037 }1040 }
1038 try fwm.setColor(stderr, .reset);1041 try stderr.setColor(.reset);
1039 }1042 }
1040 if (s.result_peak_rss != 0) {1043 if (s.result_peak_rss != 0) {
1041 const rss = s.result_peak_rss;1044 const rss = s.result_peak_rss;
1042 try fwm.setColor(stderr, .dim);1045 try stderr.setColor(.dim);
1043 if (rss >= 1000_000_000) {1046 if (rss >= 1000_000_000) {
1044 try stderr.print(" MaxRSS:{d}G", .{rss / 1000_000_000});1047 try writer.print(" MaxRSS:{d}G", .{rss / 1000_000_000});
1045 } else if (rss >= 1000_000) {1048 } else if (rss >= 1000_000) {
1046 try stderr.print(" MaxRSS:{d}M", .{rss / 1000_000});1049 try writer.print(" MaxRSS:{d}M", .{rss / 1000_000});
1047 } else if (rss >= 1000) {1050 } else if (rss >= 1000) {
1048 try stderr.print(" MaxRSS:{d}K", .{rss / 1000});1051 try writer.print(" MaxRSS:{d}K", .{rss / 1000});
1049 } else {1052 } else {
1050 try stderr.print(" MaxRSS:{d}B", .{rss});1053 try writer.print(" MaxRSS:{d}B", .{rss});
1051 }1054 }
1052 try fwm.setColor(stderr, .reset);1055 try stderr.setColor(.reset);
1053 }1056 }
1054 try stderr.writeAll("\n");1057 try writer.writeAll("\n");
1055 },1058 },
1056 .skipped, .skipped_oom => |skip| {1059 .skipped, .skipped_oom => |skip| {
1057 try fwm.setColor(stderr, .yellow);1060 try stderr.setColor(.yellow);
1058 try stderr.writeAll(" skipped");1061 try writer.writeAll(" skipped");
1059 if (skip == .skipped_oom) {1062 if (skip == .skipped_oom) {
1060 try stderr.writeAll(" (not enough memory)");1063 try writer.writeAll(" (not enough memory)");
1061 try fwm.setColor(stderr, .dim);1064 try stderr.setColor(.dim);
1062 try stderr.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });1065 try writer.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });
1063 try fwm.setColor(stderr, .yellow);1066 try stderr.setColor(.yellow);
1064 }1067 }
1065 try stderr.writeAll("\n");1068 try writer.writeAll("\n");
1066 try fwm.setColor(stderr, .reset);1069 try stderr.setColor(.reset);
1067 },1070 },
1068 .failure => {1071 .failure => {
1069 try printStepFailure(s, stderr, fwm, false);1072 try printStepFailure(s, stderr, false);
1070 try fwm.setColor(stderr, .reset);1073 try stderr.setColor(.reset);
1071 },1074 },
1072 }1075 }
1073}1076}
10741077
1075fn printStepFailure(1078fn printStepFailure(s: *Step, stderr: Io.Terminal, dim: bool) !void {
1076 s: *Step,1079 const w = stderr.writer;
1077 stderr: *Writer,
1078 fwm: File.Writer.Mode,
1079 dim: bool,
1080) !void {
1081 if (s.result_error_bundle.errorMessageCount() > 0) {1080 if (s.result_error_bundle.errorMessageCount() > 0) {
1082 try fwm.setColor(stderr, .red);1081 try stderr.setColor(.red);
1083 try stderr.print(" {d} errors\n", .{1082 try w.print(" {d} errors\n", .{
1084 s.result_error_bundle.errorMessageCount(),1083 s.result_error_bundle.errorMessageCount(),
1085 });1084 });
1086 } else if (!s.test_results.isSuccess()) {1085 } else if (!s.test_results.isSuccess()) {
1087 // These first values include all of the test "statuses". Every test is either passsed,1086 // These first values include all of the test "statuses". Every test is either passsed,
1088 // skipped, failed, crashed, or timed out.1087 // skipped, failed, crashed, or timed out.
1089 try fwm.setColor(stderr, .green);1088 try stderr.setColor(.green);
1090 try stderr.print(" {d} pass", .{s.test_results.passCount()});1089 try w.print(" {d} pass", .{s.test_results.passCount()});
1091 try fwm.setColor(stderr, .reset);1090 try stderr.setColor(.reset);
1092 if (dim) try fwm.setColor(stderr, .dim);1091 if (dim) try stderr.setColor(.dim);
1093 if (s.test_results.skip_count > 0) {1092 if (s.test_results.skip_count > 0) {
1094 try stderr.writeAll(", ");1093 try w.writeAll(", ");
1095 try fwm.setColor(stderr, .yellow);1094 try stderr.setColor(.yellow);
1096 try stderr.print("{d} skip", .{s.test_results.skip_count});1095 try w.print("{d} skip", .{s.test_results.skip_count});
1097 try fwm.setColor(stderr, .reset);1096 try stderr.setColor(.reset);
1098 if (dim) try fwm.setColor(stderr, .dim);1097 if (dim) try stderr.setColor(.dim);
1099 }1098 }
1100 if (s.test_results.fail_count > 0) {1099 if (s.test_results.fail_count > 0) {
1101 try stderr.writeAll(", ");1100 try w.writeAll(", ");
1102 try fwm.setColor(stderr, .red);1101 try stderr.setColor(.red);
1103 try stderr.print("{d} fail", .{s.test_results.fail_count});1102 try w.print("{d} fail", .{s.test_results.fail_count});
1104 try fwm.setColor(stderr, .reset);1103 try stderr.setColor(.reset);
1105 if (dim) try fwm.setColor(stderr, .dim);1104 if (dim) try stderr.setColor(.dim);
1106 }1105 }
1107 if (s.test_results.crash_count > 0) {1106 if (s.test_results.crash_count > 0) {
1108 try stderr.writeAll(", ");1107 try w.writeAll(", ");
1109 try fwm.setColor(stderr, .red);1108 try stderr.setColor(.red);
1110 try stderr.print("{d} crash", .{s.test_results.crash_count});1109 try w.print("{d} crash", .{s.test_results.crash_count});
1111 try fwm.setColor(stderr, .reset);1110 try stderr.setColor(.reset);
1112 if (dim) try fwm.setColor(stderr, .dim);1111 if (dim) try stderr.setColor(.dim);
1113 }1112 }
1114 if (s.test_results.timeout_count > 0) {1113 if (s.test_results.timeout_count > 0) {
1115 try stderr.writeAll(", ");1114 try w.writeAll(", ");
1116 try fwm.setColor(stderr, .red);1115 try stderr.setColor(.red);
1117 try stderr.print("{d} timeout", .{s.test_results.timeout_count});1116 try w.print("{d} timeout", .{s.test_results.timeout_count});
1118 try fwm.setColor(stderr, .reset);1117 try stderr.setColor(.reset);
1119 if (dim) try fwm.setColor(stderr, .dim);1118 if (dim) try stderr.setColor(.dim);
1120 }1119 }
1121 try stderr.print(" ({d} total)", .{s.test_results.test_count});1120 try w.print(" ({d} total)", .{s.test_results.test_count});
11221121
1123 // Memory leaks are intentionally written after the total, because is isn't a test *status*,1122 // Memory leaks are intentionally written after the total, because is isn't a test *status*,
1124 // but just a flag that any tests -- even passed ones -- can have. We also use a different1123 // but just a flag that any tests -- even passed ones -- can have. We also use a different
1125 // separator, so it looks like:1124 // separator, so it looks like:
1126 // 2 pass, 1 skip, 2 fail (5 total); 2 leaks1125 // 2 pass, 1 skip, 2 fail (5 total); 2 leaks
1127 if (s.test_results.leak_count > 0) {1126 if (s.test_results.leak_count > 0) {
1128 try stderr.writeAll("; ");1127 try w.writeAll("; ");
1129 try fwm.setColor(stderr, .red);1128 try stderr.setColor(.red);
1130 try stderr.print("{d} leaks", .{s.test_results.leak_count});1129 try w.print("{d} leaks", .{s.test_results.leak_count});
1131 try fwm.setColor(stderr, .reset);1130 try stderr.setColor(.reset);
1132 if (dim) try fwm.setColor(stderr, .dim);1131 if (dim) try stderr.setColor(.dim);
1133 }1132 }
11341133
1135 // It's usually not helpful to know how many error logs there were because they tend to1134 // It's usually not helpful to know how many error logs there were because they tend to
...@@ -1142,21 +1141,21 @@ fn printStepFailure(...@@ -1142,21 +1141,21 @@ fn printStepFailure(
1142 break :show alt_results.isSuccess();1141 break :show alt_results.isSuccess();
1143 };1142 };
1144 if (show_err_logs) {1143 if (show_err_logs) {
1145 try stderr.writeAll("; ");1144 try w.writeAll("; ");
1146 try fwm.setColor(stderr, .red);1145 try stderr.setColor(.red);
1147 try stderr.print("{d} error logs", .{s.test_results.log_err_count});1146 try w.print("{d} error logs", .{s.test_results.log_err_count});
1148 try fwm.setColor(stderr, .reset);1147 try stderr.setColor(.reset);
1149 if (dim) try fwm.setColor(stderr, .dim);1148 if (dim) try stderr.setColor(.dim);
1150 }1149 }
11511150
1152 try stderr.writeAll("\n");1151 try w.writeAll("\n");
1153 } else if (s.result_error_msgs.items.len > 0) {1152 } else if (s.result_error_msgs.items.len > 0) {
1154 try fwm.setColor(stderr, .red);1153 try stderr.setColor(.red);
1155 try stderr.writeAll(" failure\n");1154 try w.writeAll(" failure\n");
1156 } else {1155 } else {
1157 assert(s.result_stderr.len > 0);1156 assert(s.result_stderr.len > 0);
1158 try fwm.setColor(stderr, .red);1157 try stderr.setColor(.red);
1159 try stderr.writeAll(" stderr\n");1158 try w.writeAll(" w\n");
1160 }1159 }
1161}1160}
11621161
...@@ -1164,11 +1163,11 @@ fn printTreeStep(...@@ -1164,11 +1163,11 @@ fn printTreeStep(
1164 b: *std.Build,1163 b: *std.Build,
1165 s: *Step,1164 s: *Step,
1166 run: *const Run,1165 run: *const Run,
1167 stderr: *Writer,1166 stderr: Io.Terminal,
1168 fwm: File.Writer.Mode,
1169 parent_node: *PrintNode,1167 parent_node: *PrintNode,
1170 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),1168 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),
1171) !void {1169) !void {
1170 const writer = stderr.writer;
1172 const first = step_stack.swapRemove(s);1171 const first = step_stack.swapRemove(s);
1173 const summary = run.summary;1172 const summary = run.summary;
1174 const skip = switch (summary) {1173 const skip = switch (summary) {
...@@ -1178,26 +1177,26 @@ fn printTreeStep(...@@ -1178,26 +1177,26 @@ fn printTreeStep(
1178 .failures => s.state == .success,1177 .failures => s.state == .success,
1179 };1178 };
1180 if (skip) return;1179 if (skip) return;
1181 try printPrefix(parent_node, stderr, fwm);1180 try printPrefix(parent_node, stderr);
11821181
1183 if (parent_node.parent != null) {1182 if (parent_node.parent != null) {
1184 if (parent_node.last) {1183 if (parent_node.last) {
1185 try printChildNodePrefix(stderr, fwm);1184 try printChildNodePrefix(stderr);
1186 } else {1185 } else {
1187 try stderr.writeAll(switch (fwm) {1186 try writer.writeAll(switch (stderr.mode) {
1188 .terminal_escaped => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─1187 .escape_codes => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─
1189 else => "+- ",1188 else => "+- ",
1190 });1189 });
1191 }1190 }
1192 }1191 }
11931192
1194 if (!first) try fwm.setColor(stderr, .dim);1193 if (!first) try stderr.setColor(.dim);
11951194
1196 // dep_prefix omitted here because it is redundant with the tree.1195 // dep_prefix omitted here because it is redundant with the tree.
1197 try stderr.writeAll(s.name);1196 try writer.writeAll(s.name);
11981197
1199 if (first) {1198 if (first) {
1200 try printStepStatus(s, stderr, fwm, run);1199 try printStepStatus(s, stderr, run);
12011200
1202 const last_index = if (summary == .all) s.dependencies.items.len -| 1 else blk: {1201 const last_index = if (summary == .all) s.dependencies.items.len -| 1 else blk: {
1203 var i: usize = s.dependencies.items.len;1202 var i: usize = s.dependencies.items.len;
...@@ -1219,17 +1218,17 @@ fn printTreeStep(...@@ -1219,17 +1218,17 @@ fn printTreeStep(
1219 .parent = parent_node,1218 .parent = parent_node,
1220 .last = i == last_index,1219 .last = i == last_index,
1221 };1220 };
1222 try printTreeStep(b, dep, run, stderr, fwm, &print_node, step_stack);1221 try printTreeStep(b, dep, run, stderr, &print_node, step_stack);
1223 }1222 }
1224 } else {1223 } else {
1225 if (s.dependencies.items.len == 0) {1224 if (s.dependencies.items.len == 0) {
1226 try stderr.writeAll(" (reused)\n");1225 try writer.writeAll(" (reused)\n");
1227 } else {1226 } else {
1228 try stderr.print(" (+{d} more reused dependencies)\n", .{1227 try writer.print(" (+{d} more reused dependencies)\n", .{
1229 s.dependencies.items.len,1228 s.dependencies.items.len,
1230 });1229 });
1231 }1230 }
1232 try fwm.setColor(stderr, .reset);1231 try stderr.setColor(.reset);
1233 }1232 }
1234}1233}
12351234
...@@ -1300,7 +1299,8 @@ fn workerMakeOneStep(...@@ -1300,7 +1299,8 @@ fn workerMakeOneStep(
1300 prog_node: std.Progress.Node,1299 prog_node: std.Progress.Node,
1301 run: *Run,1300 run: *Run,
1302) void {1301) void {
1303 const io = b.graph.io;1302 const graph = b.graph;
1303 const io = graph.io;
1304 const gpa = run.gpa;1304 const gpa = run.gpa;
13051305
1306 // First, check the conditions for running this step. If they are not met,1306 // First, check the conditions for running this step. If they are not met,
...@@ -1369,11 +1369,11 @@ fn workerMakeOneStep(...@@ -1369,11 +1369,11 @@ fn workerMakeOneStep(
1369 const show_error_msgs = s.result_error_msgs.items.len > 0;1369 const show_error_msgs = s.result_error_msgs.items.len > 0;
1370 const show_stderr = s.result_stderr.len > 0;1370 const show_stderr = s.result_stderr.len > 0;
1371 if (show_error_msgs or show_compile_errors or show_stderr) {1371 if (show_error_msgs or show_compile_errors or show_stderr) {
1372 const stderr = io.lockStderrWriter(&stdio_buffer_allocation) catch |err| switch (err) {1372 const stderr = io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode) catch |err| switch (err) {
1373 error.Canceled => return,1373 error.Canceled => return,
1374 };1374 };
1375 defer io.unlockStderrWriter();1375 defer io.unlockStderr();
1376 printErrorMessages(gpa, s, .{}, &stderr.interface, stderr.mode, run.error_style, run.multiline_errors) catch {};1376 printErrorMessages(gpa, s, .{}, stderr.terminal(), run.error_style, run.multiline_errors) catch {};
1377 }1377 }
13781378
1379 handle_result: {1379 handle_result: {
...@@ -1440,11 +1440,11 @@ pub fn printErrorMessages(...@@ -1440,11 +1440,11 @@ pub fn printErrorMessages(
1440 gpa: Allocator,1440 gpa: Allocator,
1441 failing_step: *Step,1441 failing_step: *Step,
1442 options: std.zig.ErrorBundle.RenderOptions,1442 options: std.zig.ErrorBundle.RenderOptions,
1443 stderr: *Writer,1443 stderr: Io.Terminal,
1444 fwm: File.Writer.Mode,
1445 error_style: ErrorStyle,1444 error_style: ErrorStyle,
1446 multiline_errors: MultilineErrors,1445 multiline_errors: MultilineErrors,
1447) !void {1446) !void {
1447 const writer = stderr.writer;
1448 if (error_style.verboseContext()) {1448 if (error_style.verboseContext()) {
1449 // Provide context for where these error messages are coming from by1449 // Provide context for where these error messages are coming from by
1450 // printing the corresponding Step subtree.1450 // printing the corresponding Step subtree.
...@@ -1456,70 +1456,70 @@ pub fn printErrorMessages(...@@ -1456,70 +1456,70 @@ pub fn printErrorMessages(
1456 }1456 }
14571457
1458 // Now, `step_stack` has the subtree that we want to print, in reverse order.1458 // Now, `step_stack` has the subtree that we want to print, in reverse order.
1459 try fwm.setColor(stderr, .dim);1459 try stderr.setColor(.dim);
1460 var indent: usize = 0;1460 var indent: usize = 0;
1461 while (step_stack.pop()) |s| : (indent += 1) {1461 while (step_stack.pop()) |s| : (indent += 1) {
1462 if (indent > 0) {1462 if (indent > 0) {
1463 try stderr.splatByteAll(' ', (indent - 1) * 3);1463 try writer.splatByteAll(' ', (indent - 1) * 3);
1464 try printChildNodePrefix(stderr, fwm);1464 try printChildNodePrefix(stderr);
1465 }1465 }
14661466
1467 try stderr.writeAll(s.name);1467 try writer.writeAll(s.name);
14681468
1469 if (s == failing_step) {1469 if (s == failing_step) {
1470 try printStepFailure(s, stderr, fwm, true);1470 try printStepFailure(s, stderr, true);
1471 } else {1471 } else {
1472 try stderr.writeAll("\n");1472 try writer.writeAll("\n");
1473 }1473 }
1474 }1474 }
1475 try fwm.setColor(stderr, .reset);1475 try stderr.setColor(.reset);
1476 } else {1476 } else {
1477 // Just print the failing step itself.1477 // Just print the failing step itself.
1478 try fwm.setColor(stderr, .dim);1478 try stderr.setColor(.dim);
1479 try stderr.writeAll(failing_step.name);1479 try writer.writeAll(failing_step.name);
1480 try printStepFailure(failing_step, stderr, fwm, true);1480 try printStepFailure(failing_step, stderr, true);
1481 try fwm.setColor(stderr, .reset);1481 try stderr.setColor(.reset);
1482 }1482 }
14831483
1484 if (failing_step.result_stderr.len > 0) {1484 if (failing_step.result_stderr.len > 0) {
1485 try stderr.writeAll(failing_step.result_stderr);1485 try writer.writeAll(failing_step.result_stderr);
1486 if (!mem.endsWith(u8, failing_step.result_stderr, "\n")) {1486 if (!mem.endsWith(u8, failing_step.result_stderr, "\n")) {
1487 try stderr.writeAll("\n");1487 try writer.writeAll("\n");
1488 }1488 }
1489 }1489 }
14901490
1491 try failing_step.result_error_bundle.renderToWriter(options, stderr, fwm);1491 try failing_step.result_error_bundle.renderToTerminal(options, stderr);
14921492
1493 for (failing_step.result_error_msgs.items) |msg| {1493 for (failing_step.result_error_msgs.items) |msg| {
1494 try fwm.setColor(stderr, .red);1494 try stderr.setColor(.red);
1495 try stderr.writeAll("error:");1495 try writer.writeAll("error:");
1496 try fwm.setColor(stderr, .reset);1496 try stderr.setColor(.reset);
1497 if (std.mem.indexOfScalar(u8, msg, '\n') == null) {1497 if (std.mem.indexOfScalar(u8, msg, '\n') == null) {
1498 try stderr.print(" {s}\n", .{msg});1498 try writer.print(" {s}\n", .{msg});
1499 } else switch (multiline_errors) {1499 } else switch (multiline_errors) {
1500 .indent => {1500 .indent => {
1501 var it = std.mem.splitScalar(u8, msg, '\n');1501 var it = std.mem.splitScalar(u8, msg, '\n');
1502 try stderr.print(" {s}\n", .{it.first()});1502 try writer.print(" {s}\n", .{it.first()});
1503 while (it.next()) |line| {1503 while (it.next()) |line| {
1504 try stderr.print(" {s}\n", .{line});1504 try writer.print(" {s}\n", .{line});
1505 }1505 }
1506 },1506 },
1507 .newline => try stderr.print("\n{s}\n", .{msg}),1507 .newline => try writer.print("\n{s}\n", .{msg}),
1508 .none => try stderr.print(" {s}\n", .{msg}),1508 .none => try writer.print(" {s}\n", .{msg}),
1509 }1509 }
1510 }1510 }
15111511
1512 if (error_style.verboseContext()) {1512 if (error_style.verboseContext()) {
1513 if (failing_step.result_failed_command) |cmd_str| {1513 if (failing_step.result_failed_command) |cmd_str| {
1514 try fwm.setColor(stderr, .red);1514 try stderr.setColor(.red);
1515 try stderr.writeAll("failed command: ");1515 try writer.writeAll("failed command: ");
1516 try fwm.setColor(stderr, .reset);1516 try stderr.setColor(.reset);
1517 try stderr.writeAll(cmd_str);1517 try writer.writeAll(cmd_str);
1518 try stderr.writeByte('\n');1518 try writer.writeByte('\n');
1519 }1519 }
1520 }1520 }
15211521
1522 try stderr.writeByte('\n');1522 try writer.writeByte('\n');
1523}1523}
15241524
1525fn printSteps(builder: *std.Build, w: *Writer) !void {1525fn printSteps(builder: *std.Build, w: *Writer) !void {
lib/compiler/resinator/cli.zig+5-5
...@@ -126,14 +126,14 @@ pub const Diagnostics = struct {...@@ -126,14 +126,14 @@ pub const Diagnostics = struct {
126 }126 }
127127
128 pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) void {128 pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) void {
129 const stderr = io.lockStderrWriter(&.{});129 const stderr = io.lockStderr(&.{}, null);
130 defer io.unlockStderrWriter();130 defer io.unlockStderr();
131 self.renderToWriter(args, &stderr.interface, stderr.mode) catch return;131 self.renderToWriter(args, stderr.terminal()) catch return;
132 }132 }
133133
134 pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.Io.Writer, config: std.Io.tty.Config) !void {134 pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, t: Io.Terminal) !void {
135 for (self.errors.items) |err_details| {135 for (self.errors.items) |err_details| {
136 try renderErrorMessage(writer, config, err_details, args);136 try renderErrorMessage(t, err_details, args);
137 }137 }
138 }138 }
139139
lib/compiler/resinator/errors.zig+3-3
...@@ -69,10 +69,10 @@ pub const Diagnostics = struct {...@@ -69,10 +69,10 @@ pub const Diagnostics = struct {
6969
70 pub fn renderToStderr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) void {70 pub fn renderToStderr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) void {
71 const io = self.io;71 const io = self.io;
72 const stderr = io.lockStderrWriter(&.{});72 const stderr = io.lockStderr(&.{}, null);
73 defer io.unlockStderrWriter();73 defer io.unlockStderr();
74 for (self.errors.items) |err_details| {74 for (self.errors.items) |err_details| {
75 renderErrorMessage(io, &stderr.interface, stderr.mode, cwd, err_details, source, self.strings.items, source_mappings) catch return;75 renderErrorMessage(io, stderr.terminal(), cwd, err_details, source, self.strings.items, source_mappings) catch return;
76 }76 }
77 }77 }
7878
lib/compiler/resinator/main.zig+14-17
...@@ -35,8 +35,8 @@ pub fn main() !void {...@@ -35,8 +35,8 @@ pub fn main() !void {
35 const args = try std.process.argsAlloc(arena);35 const args = try std.process.argsAlloc(arena);
3636
37 if (args.len < 2) {37 if (args.len < 2) {
38 const stderr = io.lockStderrWriter(&.{});38 const stderr = try io.lockStderr(&.{}, null);
39 try renderErrorMessage(&stderr.interface, stderr.mode, .err, "expected zig lib dir as first argument", .{});39 try renderErrorMessage(stderr.terminal(), .err, "expected zig lib dir as first argument", .{});
40 std.process.exit(1);40 std.process.exit(1);
41 }41 }
42 const zig_lib_dir = args[1];42 const zig_lib_dir = args[1];
...@@ -80,9 +80,9 @@ pub fn main() !void {...@@ -80,9 +80,9 @@ pub fn main() !void {
80 // so that there is a clear separation between the cli diagnostics and whatever80 // so that there is a clear separation between the cli diagnostics and whatever
81 // gets printed after81 // gets printed after
82 if (cli_diagnostics.errors.items.len > 0) {82 if (cli_diagnostics.errors.items.len > 0) {
83 const stderr = io.lockStderrWriter(&.{});83 const stderr = try io.lockStderr(&.{}, null);
84 defer io.unlockStderrWriter();84 defer io.unlockStderr();
85 try stderr.interface.writeByte('\n');85 try stderr.file_writer.interface.writeByte('\n');
86 }86 }
87 }87 }
88 break :options options;88 break :options options;
...@@ -130,15 +130,12 @@ pub fn main() !void {...@@ -130,15 +130,12 @@ pub fn main() !void {
130 var stderr_buf: [512]u8 = undefined;130 var stderr_buf: [512]u8 = undefined;
131 var diagnostics: aro.Diagnostics = .{ .output = output: {131 var diagnostics: aro.Diagnostics = .{ .output = output: {
132 if (zig_integration) break :output .{ .to_list = .{ .arena = .init(gpa) } };132 if (zig_integration) break :output .{ .to_list = .{ .arena = .init(gpa) } };
133 const stderr = io.lockStderrWriter(&stderr_buf);133 const stderr = try io.lockStderr(&stderr_buf, null);
134 break :output .{ .to_writer = .{134 break :output .{ .to_writer = stderr.terminal() };
135 .writer = &stderr.interface,
136 .color = stderr.mode,
137 } };
138 } };135 } };
139 defer {136 defer {
140 diagnostics.deinit();137 diagnostics.deinit();
141 if (!zig_integration) std.debug.unlockStderrWriter();138 if (!zig_integration) std.debug.unlockStderr();
142 }139 }
143140
144 var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, Io.Dir.cwd());141 var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, Io.Dir.cwd());
...@@ -699,9 +696,9 @@ const ErrorHandler = union(enum) {...@@ -699,9 +696,9 @@ const ErrorHandler = union(enum) {
699 },696 },
700 .stderr => {697 .stderr => {
701 // aro errors have already been emitted698 // aro errors have already been emitted
702 const stderr = io.lockStderrWriter(&.{});699 const stderr = io.lockStderr(&.{}, null);
703 defer io.unlockStderrWriter();700 defer io.unlockStderr();
704 try renderErrorMessage(&stderr.interface, stderr.mode, .err, "{s}", .{fail_msg});701 try renderErrorMessage(stderr.terminal(), .err, "{s}", .{fail_msg});
705 },702 },
706 }703 }
707 }704 }
...@@ -745,9 +742,9 @@ const ErrorHandler = union(enum) {...@@ -745,9 +742,9 @@ const ErrorHandler = union(enum) {
745 try server.serveErrorBundle(error_bundle);742 try server.serveErrorBundle(error_bundle);
746 },743 },
747 .stderr => {744 .stderr => {
748 const stderr = io.lockStderrWriter(&.{});745 const stderr = try io.lockStderr(&.{}, null);
749 defer io.unlockStderrWriter();746 defer io.unlockStderr();
750 try renderErrorMessage(&stderr.interface, stderr.mode, msg_type, format, args);747 try renderErrorMessage(stderr.terminal(), msg_type, format, args);
751 },748 },
752 }749 }
753 }750 }
lib/compiler/test_runner.zig+4-4
...@@ -405,18 +405,18 @@ pub fn fuzz(...@@ -405,18 +405,18 @@ pub fn fuzz(
405 testOne(ctx, input.toSlice()) catch |err| switch (err) {405 testOne(ctx, input.toSlice()) catch |err| switch (err) {
406 error.SkipZigTest => return,406 error.SkipZigTest => return,
407 else => {407 else => {
408 const stderr = std.debug.lockStderrWriter(&.{});408 const stderr = std.debug.lockStderr(&.{}, null).terminal();
409 p: {409 p: {
410 if (@errorReturnTrace()) |trace| {410 if (@errorReturnTrace()) |trace| {
411 std.debug.writeStackTrace(trace, &stderr.interface, stderr.mode) catch break :p;411 std.debug.writeStackTrace(trace, stderr) catch break :p;
412 }412 }
413 stderr.interface.print("failed with error.{t}\n", .{err}) catch break :p;413 stderr.writer.print("failed with error.{t}\n", .{err}) catch break :p;
414 }414 }
415 std.process.exit(1);415 std.process.exit(1);
416 },416 },
417 };417 };
418 if (log_err_count != 0) {418 if (log_err_count != 0) {
419 const stderr = std.debug.lockStderrWriter(&.{});419 const stderr = std.debug.lockStderr(&.{}, .no_color);
420 stderr.interface.print("error logs detected\n", .{}) catch {};420 stderr.interface.print("error logs detected\n", .{}) catch {};
421 std.process.exit(1);421 std.process.exit(1);
422 }422 }
lib/std/Build.zig+36-37
...@@ -129,6 +129,9 @@ pub const Graph = struct {...@@ -129,6 +129,9 @@ pub const Graph = struct {
129 dependency_cache: InitializedDepMap = .empty,129 dependency_cache: InitializedDepMap = .empty,
130 allow_so_scripts: ?bool = null,130 allow_so_scripts: ?bool = null,
131 time_report: bool,131 time_report: bool,
132 /// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also
133 /// respects the '--color' flag.
134 stderr_mode: ?Io.Terminal.Mode = null,
132};135};
133136
134const AvailableDeps = []const struct { []const u8, []const u8 };137const AvailableDeps = []const struct { []const u8, []const u8 };
...@@ -2255,9 +2258,10 @@ pub const GeneratedFile = struct {...@@ -2255,9 +2258,10 @@ pub const GeneratedFile = struct {
22552258
2256 pub fn getPath3(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) Io.Cancelable![]const u8 {2259 pub fn getPath3(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) Io.Cancelable![]const u8 {
2257 return gen.path orelse {2260 return gen.path orelse {
2258 const io = gen.step.owner.graph.io;2261 const graph = gen.step.owner.graph;
2259 const stderr = try io.lockStderrWriter(&.{});2262 const io = graph.io;
2260 dumpBadGetPathHelp(gen.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {};2263 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
2264 dumpBadGetPathHelp(gen.step, stderr.terminal(), src_builder, asking_step) catch {};
2261 @panic("misconfigured build script");2265 @panic("misconfigured build script");
2262 };2266 };
2263 }2267 }
...@@ -2468,13 +2472,15 @@ pub const LazyPath = union(enum) {...@@ -2468,13 +2472,15 @@ pub const LazyPath = union(enum) {
2468 // TODO make gen.file.path not be absolute and use that as the2472 // TODO make gen.file.path not be absolute and use that as the
2469 // basis for not traversing up too many directories.2473 // basis for not traversing up too many directories.
24702474
2475 const graph = src_builder.graph;
2476
2471 var file_path: Cache.Path = .{2477 var file_path: Cache.Path = .{
2472 .root_dir = Cache.Directory.cwd(),2478 .root_dir = Cache.Directory.cwd(),
2473 .sub_path = gen.file.path orelse {2479 .sub_path = gen.file.path orelse {
2474 const io = src_builder.graph.io;2480 const io = graph.io;
2475 const stderr = try io.lockStderrWriter(&.{});2481 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
2476 dumpBadGetPathHelp(gen.file.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {};2482 dumpBadGetPathHelp(gen.file.step, stderr.terminal(), src_builder, asking_step) catch {};
2477 io.unlockStderrWriter();2483 io.unlockStderr();
2478 @panic("misconfigured build script");2484 @panic("misconfigured build script");
2479 },2485 },
2480 };2486 };
...@@ -2564,43 +2570,36 @@ fn dumpBadDirnameHelp(...@@ -2564,43 +2570,36 @@ fn dumpBadDirnameHelp(
2564 comptime msg: []const u8,2570 comptime msg: []const u8,
2565 args: anytype,2571 args: anytype,
2566) anyerror!void {2572) anyerror!void {
2567 const stderr = std.debug.lockStderrWriter(&.{});2573 const stderr = std.debug.lockStderr(&.{}).terminal();
2568 defer std.debug.unlockStderrWriter();2574 defer std.debug.unlockStderr();
25692575 const w = stderr.writer;
2570 const w = &stderr.interface;
2571 const fwm = stderr.mode;
25722576
2573 try w.print(msg, args);2577 try w.print(msg, args);
25742578
2575 if (fail_step) |s| {2579 if (fail_step) |s| {
2576 fwm.setColor(w, .red) catch {};2580 stderr.setColor(.red) catch {};
2577 try w.writeAll(" The step was created by this stack trace:\n");2581 try w.writeAll(" The step was created by this stack trace:\n");
2578 fwm.setColor(w, .reset) catch {};2582 stderr.setColor(.reset) catch {};
25792583
2580 s.dump(w, fwm);2584 s.dump(stderr);
2581 }2585 }
25822586
2583 if (asking_step) |as| {2587 if (asking_step) |as| {
2584 fwm.setColor(w, .red) catch {};2588 stderr.setColor(.red) catch {};
2585 try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});2589 try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
2586 fwm.setColor(w, .reset) catch {};2590 stderr.setColor(.reset) catch {};
25872591
2588 as.dump(w, fwm);2592 as.dump(stderr);
2589 }2593 }
25902594
2591 fwm.setColor(w, .red) catch {};2595 stderr.setColor(.red) catch {};
2592 try w.writeAll(" Hope that helps. Proceeding to panic.\n");2596 try w.writeAll(" Proceeding to panic.\n");
2593 fwm.setColor(w, .reset) catch {};2597 stderr.setColor(.reset) catch {};
2594}2598}
25952599
2596/// In this function the stderr mutex has already been locked.2600/// In this function the stderr mutex has already been locked.
2597pub fn dumpBadGetPathHelp(2601pub fn dumpBadGetPathHelp(s: *Step, t: Io.Terminal, src_builder: *Build, asking_step: ?*Step) anyerror!void {
2598 s: *Step,2602 const w = t.writer;
2599 w: *Io.Writer,
2600 fwm: File.Writer.Mode,
2601 src_builder: *Build,
2602 asking_step: ?*Step,
2603) anyerror!void {
2604 try w.print(2603 try w.print(
2605 \\getPath() was called on a GeneratedFile that wasn't built yet.2604 \\getPath() was called on a GeneratedFile that wasn't built yet.
2606 \\ source package path: {s}2605 \\ source package path: {s}
...@@ -2611,21 +2610,21 @@ pub fn dumpBadGetPathHelp(...@@ -2611,21 +2610,21 @@ pub fn dumpBadGetPathHelp(
2611 s.name,2610 s.name,
2612 });2611 });
26132612
2614 fwm.setColor(w, .red) catch {};2613 t.setColor(.red) catch {};
2615 try w.writeAll(" The step was created by this stack trace:\n");2614 try w.writeAll(" The step was created by this stack trace:\n");
2616 fwm.setColor(w, .reset) catch {};2615 t.setColor(.reset) catch {};
26172616
2618 s.dump(w, fwm);2617 s.dump(t);
2619 if (asking_step) |as| {2618 if (asking_step) |as| {
2620 fwm.setColor(w, .red) catch {};2619 t.setColor(.red) catch {};
2621 try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});2620 try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
2622 fwm.setColor(w, .reset) catch {};2621 t.setColor(.reset) catch {};
26232622
2624 as.dump(w, fwm);2623 as.dump(t);
2625 }2624 }
2626 fwm.setColor(w, .red) catch {};2625 t.setColor(.red) catch {};
2627 try w.writeAll(" Hope that helps. Proceeding to panic.\n");2626 try w.writeAll(" Proceeding to panic.\n");
2628 fwm.setColor(w, .reset) catch {};2627 t.setColor(.reset) catch {};
2629}2628}
26302629
2631pub const InstallDir = union(enum) {2630pub const InstallDir = union(enum) {
lib/std/Build/Fuzz.zig+10-8
...@@ -158,7 +158,8 @@ fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, parent_prog_node: std.P...@@ -158,7 +158,8 @@ fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, parent_prog_node: std.P
158}158}
159159
160fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) !void {160fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) !void {
161 const io = run.step.owner.graph.io;161 const graph = run.step.owner.graph;
162 const io = graph.io;
162 const compile = run.producer.?;163 const compile = run.producer.?;
163 const prog_node = parent_prog_node.start(compile.step.name, 0);164 const prog_node = parent_prog_node.start(compile.step.name, 0);
164 defer prog_node.end();165 defer prog_node.end();
...@@ -171,9 +172,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod...@@ -171,9 +172,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod
171172
172 if (show_error_msgs or show_compile_errors or show_stderr) {173 if (show_error_msgs or show_compile_errors or show_stderr) {
173 var buf: [256]u8 = undefined;174 var buf: [256]u8 = undefined;
174 const stderr = try io.lockStderrWriter(&buf);175 const stderr = try io.lockStderr(&buf, graph.stderr_mode);
175 defer io.unlockStderrWriter();176 defer io.unlockStderr();
176 build_runner.printErrorMessages(gpa, &compile.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {};177 build_runner.printErrorMessages(gpa, &compile.step, .{}, stderr.terminal(), .verbose, .indent) catch {};
177 }178 }
178179
179 const rebuilt_bin_path = result catch |err| switch (err) {180 const rebuilt_bin_path = result catch |err| switch (err) {
...@@ -186,7 +187,8 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod...@@ -186,7 +187,8 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod
186fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void {187fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void {
187 const owner = run.step.owner;188 const owner = run.step.owner;
188 const gpa = owner.allocator;189 const gpa = owner.allocator;
189 const io = owner.graph.io;190 const graph = owner.graph;
191 const io = graph.io;
190 const test_name = run.cached_test_metadata.?.testName(unit_test_index);192 const test_name = run.cached_test_metadata.?.testName(unit_test_index);
191193
192 const prog_node = fuzz.prog_node.start(test_name, 0);194 const prog_node = fuzz.prog_node.start(test_name, 0);
...@@ -195,11 +197,11 @@ fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void {...@@ -195,11 +197,11 @@ fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void {
195 run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) {197 run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) {
196 error.MakeFailed => {198 error.MakeFailed => {
197 var buf: [256]u8 = undefined;199 var buf: [256]u8 = undefined;
198 const stderr = io.lockStderrWriter(&buf) catch |e| switch (e) {200 const stderr = io.lockStderr(&buf, graph.stderr_mode) catch |e| switch (e) {
199 error.Canceled => return,201 error.Canceled => return,
200 };202 };
201 defer io.unlockStderrWriter();203 defer io.unlockStderr();
202 build_runner.printErrorMessages(gpa, &run.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {};204 build_runner.printErrorMessages(gpa, &run.step, .{}, stderr.terminal(), .verbose, .indent) catch {};
203 return;205 return;
204 },206 },
205 else => {207 else => {
lib/std/Build/Step.zig+5-4
...@@ -328,16 +328,17 @@ pub fn cast(step: *Step, comptime T: type) ?*T {...@@ -328,16 +328,17 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
328}328}
329329
330/// For debugging purposes, prints identifying information about this Step.330/// For debugging purposes, prints identifying information about this Step.
331pub fn dump(step: *Step, w: *Io.Writer, fwm: Io.File.Writer.Mode) void {331pub fn dump(step: *Step, t: Io.Terminal) void {
332 const w = t.writer;
332 if (step.debug_stack_trace.instruction_addresses.len > 0) {333 if (step.debug_stack_trace.instruction_addresses.len > 0) {
333 w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};334 w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
334 std.debug.writeStackTrace(&step.debug_stack_trace, w, fwm) catch {};335 std.debug.writeStackTrace(&step.debug_stack_trace, t) catch {};
335 } else {336 } else {
336 const field = "debug_stack_frames_count";337 const field = "debug_stack_frames_count";
337 comptime assert(@hasField(Build, field));338 comptime assert(@hasField(Build, field));
338 fwm.setColor(w, .yellow) catch {};339 t.setColor(.yellow) catch {};
339 w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};340 w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};
340 fwm.setColor(w, .reset) catch {};341 t.setColor(.reset) catch {};
341 }342 }
342}343}
343344
lib/std/Build/Step/Compile.zig+9-8
...@@ -925,20 +925,21 @@ const CliNamedModules = struct {...@@ -925,20 +925,21 @@ const CliNamedModules = struct {
925fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 {925fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 {
926 const step = &compile.step;926 const step = &compile.step;
927 const b = step.owner;927 const b = step.owner;
928 const io = b.graph.io;928 const graph = b.graph;
929 const io = graph.io;
929 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);930 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);
930931
931 const generated_file = maybe_path orelse {932 const generated_file = maybe_path orelse {
932 const stderr = try io.lockStderrWriter(&.{});933 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
933 std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {};934 std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {};
934 io.unlockStderrWriter();935 io.unlockStderr();
935 @panic("missing emit option for " ++ tag_name);936 @panic("missing emit option for " ++ tag_name);
936 };937 };
937938
938 const path = generated_file.path orelse {939 const path = generated_file.path orelse {
939 const stderr = try io.lockStderrWriter(&.{});940 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
940 std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {};941 std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {};
941 io.unlockStderrWriter();942 io.unlockStderr();
942 @panic(tag_name ++ " is null. Is there a missing step dependency?");943 @panic(tag_name ++ " is null. Is there a missing step dependency?");
943 };944 };
944945
...@@ -1907,7 +1908,7 @@ fn checkCompileErrors(compile: *Compile) !void {...@@ -1907,7 +1908,7 @@ fn checkCompileErrors(compile: *Compile) !void {
1907 try actual_eb.renderToWriter(.{1908 try actual_eb.renderToWriter(.{
1908 .include_reference_trace = false,1909 .include_reference_trace = false,
1909 .include_source_line = false,1910 .include_source_line = false,
1910 }, &aw.writer, .streaming);1911 }, &aw.writer);
1911 break :ae try aw.toOwnedSlice();1912 break :ae try aw.toOwnedSlice();
1912 };1913 };
19131914
lib/std/Build/Step/Run.zig+12-10
...@@ -1559,7 +1559,8 @@ fn spawnChildAndCollect(...@@ -1559,7 +1559,8 @@ fn spawnChildAndCollect(
1559) !?EvalGenericResult {1559) !?EvalGenericResult {
1560 const b = run.step.owner;1560 const b = run.step.owner;
1561 const arena = b.allocator;1561 const arena = b.allocator;
1562 const io = b.graph.io;1562 const graph = b.graph;
1563 const io = graph.io;
15631564
1564 if (fuzz_context != null) {1565 if (fuzz_context != null) {
1565 assert(!has_side_effects);1566 assert(!has_side_effects);
...@@ -1625,11 +1626,12 @@ fn spawnChildAndCollect(...@@ -1625,11 +1626,12 @@ fn spawnChildAndCollect(
1625 if (!run.disable_zig_progress and !inherit) {1626 if (!run.disable_zig_progress and !inherit) {
1626 child.progress_node = options.progress_node;1627 child.progress_node = options.progress_node;
1627 }1628 }
1628 if (inherit) {1629 const terminal_mode: Io.Terminal.Mode = if (inherit) m: {
1629 const stderr = try io.lockStderrWriter(&.{});1630 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
1630 try setColorEnvironmentVariables(run, env_map, stderr.mode);1631 break :m stderr.terminal_mode;
1631 }1632 } else .no_color;
1632 defer if (inherit) io.unlockStderrWriter();1633 defer if (inherit) io.unlockStderr();
1634 try setColorEnvironmentVariables(run, env_map, terminal_mode);
1633 var timer = try std.time.Timer.start();1635 var timer = try std.time.Timer.start();
1634 const res = try evalGeneric(run, &child);1636 const res = try evalGeneric(run, &child);
1635 run.step.result_duration_ns = timer.read();1637 run.step.result_duration_ns = timer.read();
...@@ -1637,7 +1639,7 @@ fn spawnChildAndCollect(...@@ -1637,7 +1639,7 @@ fn spawnChildAndCollect(
1637 }1639 }
1638}1640}
16391641
1640fn setColorEnvironmentVariables(run: *Run, env_map: *EnvMap, fwm: Io.File.Writer.Mode) !void {1642fn setColorEnvironmentVariables(run: *Run, env_map: *EnvMap, terminal_mode: Io.Terminal.Mode) !void {
1641 color: switch (run.color) {1643 color: switch (run.color) {
1642 .manual => {},1644 .manual => {},
1643 .enable => {1645 .enable => {
...@@ -1648,9 +1650,9 @@ fn setColorEnvironmentVariables(run: *Run, env_map: *EnvMap, fwm: Io.File.Writer...@@ -1648,9 +1650,9 @@ fn setColorEnvironmentVariables(run: *Run, env_map: *EnvMap, fwm: Io.File.Writer
1648 try env_map.put("NO_COLOR", "1");1650 try env_map.put("NO_COLOR", "1");
1649 env_map.remove("CLICOLOR_FORCE");1651 env_map.remove("CLICOLOR_FORCE");
1650 },1652 },
1651 .inherit => switch (fwm) {1653 .inherit => switch (terminal_mode) {
1652 .terminal_escaped => continue :color .enable,1654 .no_color, .windows_api => continue :color .disable,
1653 else => continue :color .disable,1655 .escape_codes => continue :color .enable,
1654 },1656 },
1655 .auto => {1657 .auto => {
1656 const capture_stderr = run.captured_stderr != null or switch (run.stdio) {1658 const capture_stderr = run.captured_stderr != null or switch (run.stdio) {
lib/std/Io.zig+1-1
...@@ -713,7 +713,7 @@ pub const VTable = struct {...@@ -713,7 +713,7 @@ pub const VTable = struct {
713 processExecutableOpen: *const fn (?*anyopaque, File.OpenFlags) std.process.OpenExecutableError!File,713 processExecutableOpen: *const fn (?*anyopaque, File.OpenFlags) std.process.OpenExecutableError!File,
714 processExecutablePath: *const fn (?*anyopaque, buffer: []u8) std.process.ExecutablePathError!usize,714 processExecutablePath: *const fn (?*anyopaque, buffer: []u8) std.process.ExecutablePathError!usize,
715 lockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!LockedStderr,715 lockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!LockedStderr,
716 tryLockStderr: *const fn (?*anyopaque, buffer: []u8) Cancelable!?LockedStderr,716 tryLockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!?LockedStderr,
717 unlockStderr: *const fn (?*anyopaque) void,717 unlockStderr: *const fn (?*anyopaque) void,
718718
719 now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,719 now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,
lib/std/Io/File/Writer.zig+1-1
...@@ -229,7 +229,7 @@ pub fn seekToUnbuffered(w: *Writer, offset: u64) SeekError!void {...@@ -229,7 +229,7 @@ pub fn seekToUnbuffered(w: *Writer, offset: u64) SeekError!void {
229 .positional, .positional_simple => {229 .positional, .positional_simple => {
230 w.pos = offset;230 w.pos = offset;
231 },231 },
232 .streaming, .streaming_simple, .terminal_escaped, .terminal_winapi => {232 .streaming, .streaming_simple => {
233 if (w.seek_err) |err| return err;233 if (w.seek_err) |err| return err;
234 io.vtable.fileSeekTo(io.userdata, w.file, offset) catch |err| {234 io.vtable.fileSeekTo(io.userdata, w.file, offset) catch |err| {
235 w.seek_err = err;235 w.seek_err = err;
lib/std/Io/Terminal.zig-22
...@@ -130,25 +130,3 @@ pub fn setColor(t: Terminal, color: Color) Io.Writer.Error!void {...@@ -130,25 +130,3 @@ pub fn setColor(t: Terminal, color: Color) Io.Writer.Error!void {
130 },130 },
131 }131 }
132}132}
133
134pub fn disableEscape(t: *Terminal) Mode {
135 const prev = t.mode;
136 t.mode = t.mode.toUnescaped();
137 return prev;
138}
139
140pub fn restoreEscape(t: *Terminal, mode: Mode) void {
141 t.mode = mode;
142}
143
144pub fn writeAllUnescaped(t: *Terminal, bytes: []const u8) Io.Writer.Error!void {
145 const prev_mode = t.disableEscape();
146 defer t.restoreEscape(prev_mode);
147 return t.interface.writeAll(bytes);
148}
149
150pub fn printUnescaped(t: *Terminal, comptime fmt: []const u8, args: anytype) Io.Writer.Error!void {
151 const prev_mode = t.disableEscape();
152 defer t.restoreEscape(prev_mode);
153 return t.interface.print(fmt, args);
154}
lib/std/Io/Threaded.zig+3-3
...@@ -7178,7 +7178,7 @@ fn fileWriteFileStreaming(...@@ -7178,7 +7178,7 @@ fn fileWriteFileStreaming(
7178 break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) };7178 break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) };
7179 },7179 },
7180 .streaming => .{ null, limit.minInt(max_count) },7180 .streaming => .{ null, limit.minInt(max_count) },
7181 .streaming_reading, .positional_reading => break :sf,7181 .streaming_simple, .positional_simple => break :sf,
7182 .failure => return error.ReadFailed,7182 .failure => return error.ReadFailed,
7183 };7183 };
7184 const current_thread = Thread.getCurrent(t);7184 const current_thread = Thread.getCurrent(t);
...@@ -7251,7 +7251,7 @@ fn fileWriteFileStreaming(...@@ -7251,7 +7251,7 @@ fn fileWriteFileStreaming(
7251 }7251 }
7252 var off_in: i64 = undefined;7252 var off_in: i64 = undefined;
7253 const off_in_ptr: ?*i64 = switch (file_reader.mode) {7253 const off_in_ptr: ?*i64 = switch (file_reader.mode) {
7254 .positional_reading, .streaming_reading => return error.Unimplemented,7254 .positional_simple, .streaming_simple => return error.Unimplemented,
7255 .positional => p: {7255 .positional => p: {
7256 off_in = @intCast(file_reader.pos);7256 off_in = @intCast(file_reader.pos);
7257 break :p &off_in;7257 break :p &off_in;
...@@ -7427,7 +7427,7 @@ fn fileWriteFilePositional(...@@ -7427,7 +7427,7 @@ fn fileWriteFilePositional(
7427 }7427 }
7428 var off_in: i64 = undefined;7428 var off_in: i64 = undefined;
7429 const off_in_ptr: ?*i64 = switch (file_reader.mode) {7429 const off_in_ptr: ?*i64 = switch (file_reader.mode) {
7430 .positional_reading, .streaming_reading => return error.Unimplemented,7430 .positional_simple, .streaming_simple => return error.Unimplemented,
7431 .positional => p: {7431 .positional => p: {
7432 off_in = @intCast(file_reader.pos);7432 off_in = @intCast(file_reader.pos);
7433 break :p &off_in;7433 break :p &off_in;
lib/std/debug.zig+12-12
...@@ -283,12 +283,12 @@ var static_single_threaded_io: Io.Threaded = .init_single_threaded;...@@ -283,12 +283,12 @@ var static_single_threaded_io: Io.Threaded = .init_single_threaded;
283///283///
284/// Alternatively, use the higher-level `Io.lockStderr` to integrate with the284/// Alternatively, use the higher-level `Io.lockStderr` to integrate with the
285/// application's chosen `Io` implementation.285/// application's chosen `Io` implementation.
286pub fn lockStderr(buffer: []u8) Io.Terminal {286pub fn lockStderr(buffer: []u8) Io.LockedStderr {
287 return (static_single_threaded_io.ioBasic().lockStderr(buffer, null) catch |err| switch (err) {287 return static_single_threaded_io.ioBasic().lockStderr(buffer, null) catch |err| switch (err) {
288 // Impossible to cancel because no calls to cancel using288 // Impossible to cancel because no calls to cancel using
289 // `static_single_threaded_io` exist.289 // `static_single_threaded_io` exist.
290 error.Canceled => unreachable,290 error.Canceled => unreachable,
291 }).terminal();291 };
292}292}
293293
294pub fn unlockStderr() void {294pub fn unlockStderr() void {
...@@ -311,7 +311,7 @@ pub fn print(comptime fmt: []const u8, args: anytype) void {...@@ -311,7 +311,7 @@ pub fn print(comptime fmt: []const u8, args: anytype) void {
311 var buffer: [64]u8 = undefined;311 var buffer: [64]u8 = undefined;
312 const stderr = lockStderr(&buffer);312 const stderr = lockStderr(&buffer);
313 defer unlockStderr();313 defer unlockStderr();
314 stderr.writer.print(fmt, args) catch return;314 stderr.file_writer.interface.print(fmt, args) catch return;
315 }315 }
316}316}
317317
...@@ -327,7 +327,7 @@ pub inline fn getSelfDebugInfo() !*SelfInfo {...@@ -327,7 +327,7 @@ pub inline fn getSelfDebugInfo() !*SelfInfo {
327/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.327/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.
328/// Obtains the stderr mutex while dumping.328/// Obtains the stderr mutex while dumping.
329pub fn dumpHex(bytes: []const u8) void {329pub fn dumpHex(bytes: []const u8) void {
330 const stderr = lockStderr(&.{});330 const stderr = lockStderr(&.{}).terminal();
331 defer unlockStderr();331 defer unlockStderr();
332 dumpHexFallible(stderr, bytes) catch {};332 dumpHexFallible(stderr, bytes) catch {};
333}333}
...@@ -551,7 +551,7 @@ pub fn defaultPanic(...@@ -551,7 +551,7 @@ pub fn defaultPanic(
551 _ = panicking.fetchAdd(1, .seq_cst);551 _ = panicking.fetchAdd(1, .seq_cst);
552552
553 trace: {553 trace: {
554 const stderr = lockStderr(&.{});554 const stderr = lockStderr(&.{}).terminal();
555 defer unlockStderr();555 defer unlockStderr();
556 const writer = stderr.writer;556 const writer = stderr.writer;
557557
...@@ -581,7 +581,7 @@ pub fn defaultPanic(...@@ -581,7 +581,7 @@ pub fn defaultPanic(
581 // A panic happened while trying to print a previous panic message.581 // A panic happened while trying to print a previous panic message.
582 // We're still holding the mutex but that's fine as we're going to582 // We're still holding the mutex but that's fine as we're going to
583 // call abort().583 // call abort().
584 const stderr = lockStderr(&.{});584 const stderr = lockStderr(&.{}).terminal();
585 stderr.writer.writeAll("aborting due to recursive panic\n") catch {};585 stderr.writer.writeAll("aborting due to recursive panic\n") catch {};
586 },586 },
587 else => {}, // Panicked while printing the recursive panic message.587 else => {}, // Panicked while printing the recursive panic message.
...@@ -751,7 +751,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Termin...@@ -751,7 +751,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Termin
751}751}
752/// A thin wrapper around `writeCurrentStackTrace` which writes to stderr and ignores write errors.752/// A thin wrapper around `writeCurrentStackTrace` which writes to stderr and ignores write errors.
753pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void {753pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void {
754 const stderr = lockStderr(&.{});754 const stderr = lockStderr(&.{}).terminal();
755 defer unlockStderr();755 defer unlockStderr();
756 writeCurrentStackTrace(.{756 writeCurrentStackTrace(.{
757 .first_address = a: {757 .first_address = a: {
...@@ -814,7 +814,7 @@ pub fn writeStackTrace(st: *const StackTrace, t: Io.Terminal) Writer.Error!void...@@ -814,7 +814,7 @@ pub fn writeStackTrace(st: *const StackTrace, t: Io.Terminal) Writer.Error!void
814}814}
815/// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors.815/// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors.
816pub fn dumpStackTrace(st: *const StackTrace) void {816pub fn dumpStackTrace(st: *const StackTrace) void {
817 const stderr = lockStderr(&.{});817 const stderr = lockStderr(&.{}).terminal();
818 defer unlockStderr();818 defer unlockStderr();
819 writeStackTrace(st, stderr) catch |err| switch (err) {819 writeStackTrace(st, stderr) catch |err| switch (err) {
820 error.WriteFailed => {},820 error.WriteFailed => {},
...@@ -1550,7 +1550,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex...@@ -1550,7 +1550,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex
1550 _ = panicking.fetchAdd(1, .seq_cst);1550 _ = panicking.fetchAdd(1, .seq_cst);
15511551
1552 trace: {1552 trace: {
1553 const stderr = lockStderr(&.{});1553 const stderr = lockStderr(&.{}).terminal();
1554 defer unlockStderr();1554 defer unlockStderr();
15551555
1556 if (addr) |a| {1556 if (addr) |a| {
...@@ -1571,7 +1571,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex...@@ -1571,7 +1571,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex
1571 // A segfault happened while trying to print a previous panic message.1571 // A segfault happened while trying to print a previous panic message.
1572 // We're still holding the mutex but that's fine as we're going to1572 // We're still holding the mutex but that's fine as we're going to
1573 // call abort().1573 // call abort().
1574 const stderr = lockStderr(&.{});1574 const stderr = lockStderr(&.{}).terminal();
1575 stderr.writer.writeAll("aborting due to recursive panic\n") catch {};1575 stderr.writer.writeAll("aborting due to recursive panic\n") catch {};
1576 },1576 },
1577 else => {}, // Panicked while printing the recursive panic message.1577 else => {}, // Panicked while printing the recursive panic message.
...@@ -1678,7 +1678,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize...@@ -1678,7 +1678,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1678 pub fn dump(t: @This()) void {1678 pub fn dump(t: @This()) void {
1679 if (!enabled) return;1679 if (!enabled) return;
16801680
1681 const stderr = lockStderr(&.{});1681 const stderr = lockStderr(&.{}).terminal();
1682 defer unlockStderr();1682 defer unlockStderr();
1683 const end = @min(t.index, size);1683 const end = @min(t.index, size);
1684 for (t.addrs[0..end], 0..) |frames_array, i| {1684 for (t.addrs[0..end], 0..) |frames_array, i| {
lib/std/debug/simple_panic.zig+3-3
...@@ -14,9 +14,9 @@ const std = @import("../std.zig");...@@ -14,9 +14,9 @@ const std = @import("../std.zig");
14pub fn call(msg: []const u8, ra: ?usize) noreturn {14pub fn call(msg: []const u8, ra: ?usize) noreturn {
15 @branchHint(.cold);15 @branchHint(.cold);
16 _ = ra;16 _ = ra;
17 const stderr = std.debug.lockStderrWriter(&.{});17 const stderr_writer = std.debug.lockStderr(&.{}, null).terminal().writer;
18 stderr.interface.writeAll(msg) catch {};18 stderr_writer.writeAll(msg) catch {};
19 stderr.interface.flush(msg) catch {};19 stderr_writer.flush(msg) catch {};
20 @trap();20 @trap();
21}21}
2222
lib/std/json/dynamic.zig+3-3
...@@ -47,9 +47,9 @@ pub const Value = union(enum) {...@@ -47,9 +47,9 @@ pub const Value = union(enum) {
47 }47 }
4848
49 pub fn dump(v: Value) void {49 pub fn dump(v: Value) void {
50 const stderr = std.debug.lockStderrWriter(&.{});50 const stderr = std.debug.lockStderr(&.{}, null);
51 defer std.debug.unlockStderrWriter();51 defer std.debug.unlockStderr();
52 json.Stringify.value(v, .{}, &stderr.interface) catch return;52 json.Stringify.value(v, .{}, &stderr.file_writer.interface) catch return;
53 }53 }
5454
55 pub fn jsonStringify(value: @This(), jws: anytype) !void {55 pub fn jsonStringify(value: @This(), jws: anytype) !void {
lib/std/log.zig+1-1
...@@ -92,7 +92,7 @@ pub fn defaultLog(...@@ -92,7 +92,7 @@ pub fn defaultLog(
92 args: anytype,92 args: anytype,
93) void {93) void {
94 var buffer: [64]u8 = undefined;94 var buffer: [64]u8 = undefined;
95 const stderr = std.debug.lockStderr(&buffer);95 const stderr = std.debug.lockStderr(&buffer).terminal();
96 defer std.debug.unlockStderr();96 defer std.debug.unlockStderr();
97 return defaultLogFileTerminal(level, scope, format, args, stderr) catch {};97 return defaultLogFileTerminal(level, scope, format, args, stderr) catch {};
98}98}
lib/std/process.zig+1-1
...@@ -1856,7 +1856,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {...@@ -1856,7 +1856,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
1856/// and does not return.1856/// and does not return.
1857pub fn cleanExit(io: Io) void {1857pub fn cleanExit(io: Io) void {
1858 if (builtin.mode == .Debug) return;1858 if (builtin.mode == .Debug) return;
1859 _ = io.lockStderrWriter(&.{}) catch {};1859 _ = io.lockStderr(&.{}, .no_color) catch {};
1860 exit(0);1860 exit(0);
1861}1861}
18621862
lib/std/testing.zig+11-10
...@@ -368,8 +368,8 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -368,8 +368,8 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
368 break :diff_index if (expected.len == actual.len) return else shortest;368 break :diff_index if (expected.len == actual.len) return else shortest;
369 };369 };
370 if (!backend_can_print) return error.TestExpectedEqual;370 if (!backend_can_print) return error.TestExpectedEqual;
371 if (io.lockStderrWriter(&.{})) |stderr| {371 if (io.lockStderr(&.{}, null)) |stderr| {
372 defer io.unlockStderrWriter();372 defer io.unlockStderr();
373 failEqualSlices(T, expected, actual, diff_index, &stderr.interface, stderr.mode) catch {};373 failEqualSlices(T, expected, actual, diff_index, &stderr.interface, stderr.mode) catch {};
374 } else |_| {}374 } else |_| {}
375 return error.TestExpectedEqual;375 return error.TestExpectedEqual;
...@@ -381,7 +381,7 @@ fn failEqualSlices(...@@ -381,7 +381,7 @@ fn failEqualSlices(
381 actual: []const T,381 actual: []const T,
382 diff_index: usize,382 diff_index: usize,
383 w: *Io.Writer,383 w: *Io.Writer,
384 fwm: Io.File.Writer.Mode,384 terminal_mode: Io.Terminal.Mode,
385) !void {385) !void {
386 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });386 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });
387387
...@@ -404,12 +404,12 @@ fn failEqualSlices(...@@ -404,12 +404,12 @@ fn failEqualSlices(
404 var differ = if (T == u8) BytesDiffer{404 var differ = if (T == u8) BytesDiffer{
405 .expected = expected_window,405 .expected = expected_window,
406 .actual = actual_window,406 .actual = actual_window,
407 .file_writer_mode = fwm,407 .terminal_mode = terminal_mode,
408 } else SliceDiffer(T){408 } else SliceDiffer(T){
409 .start_index = window_start,409 .start_index = window_start,
410 .expected = expected_window,410 .expected = expected_window,
411 .actual = actual_window,411 .actual = actual_window,
412 .file_writer_mode = fwm,412 .terminal_mode = terminal_mode,
413 };413 };
414414
415 // Print indexes as hex for slices of u8 since it's more likely to be binary data where415 // Print indexes as hex for slices of u8 since it's more likely to be binary data where
...@@ -466,21 +466,22 @@ fn SliceDiffer(comptime T: type) type {...@@ -466,21 +466,22 @@ fn SliceDiffer(comptime T: type) type {
466 start_index: usize,466 start_index: usize,
467 expected: []const T,467 expected: []const T,
468 actual: []const T,468 actual: []const T,
469 file_writer_mode: Io.File.Writer.Mode,469 terminal_mode: Io.Terminal.Mode,
470470
471 const Self = @This();471 const Self = @This();
472472
473 pub fn write(self: Self, writer: *Io.Writer) !void {473 pub fn write(self: Self, writer: *Io.Writer) !void {
474 const t: Io.Terminal = .{ .writer = writer, .mode = self.terminal_mode };
474 for (self.expected, 0..) |value, i| {475 for (self.expected, 0..) |value, i| {
475 const full_index = self.start_index + i;476 const full_index = self.start_index + i;
476 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;477 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;
477 if (diff) try self.file_writer_mode.setColor(writer, .red);478 if (diff) try t.setColor(writer, .red);
478 if (@typeInfo(T) == .pointer) {479 if (@typeInfo(T) == .pointer) {
479 try writer.print("[{}]{*}: {any}\n", .{ full_index, value, value });480 try writer.print("[{}]{*}: {any}\n", .{ full_index, value, value });
480 } else {481 } else {
481 try writer.print("[{}]: {any}\n", .{ full_index, value });482 try writer.print("[{}]: {any}\n", .{ full_index, value });
482 }483 }
483 if (diff) try self.file_writer_mode.setColor(writer, .reset);484 if (diff) try t.setColor(writer, .reset);
484 }485 }
485 }486 }
486 };487 };
...@@ -489,7 +490,7 @@ fn SliceDiffer(comptime T: type) type {...@@ -489,7 +490,7 @@ fn SliceDiffer(comptime T: type) type {
489const BytesDiffer = struct {490const BytesDiffer = struct {
490 expected: []const u8,491 expected: []const u8,
491 actual: []const u8,492 actual: []const u8,
492 file_writer_mode: Io.File.Writer.Mode,493 terminal_mode: Io.Terminal.Mode,
493494
494 pub fn write(self: BytesDiffer, writer: *Io.Writer) !void {495 pub fn write(self: BytesDiffer, writer: *Io.Writer) !void {
495 var expected_iterator = std.mem.window(u8, self.expected, 16, 16);496 var expected_iterator = std.mem.window(u8, self.expected, 16, 16);
...@@ -516,7 +517,7 @@ const BytesDiffer = struct {...@@ -516,7 +517,7 @@ const BytesDiffer = struct {
516 try self.writeDiff(writer, "{c}", .{byte}, diff);517 try self.writeDiff(writer, "{c}", .{byte}, diff);
517 } else {518 } else {
518 // TODO: remove this `if` when https://github.com/ziglang/zig/issues/7600 is fixed519 // TODO: remove this `if` when https://github.com/ziglang/zig/issues/7600 is fixed
519 if (self.file_writer_mode == .terminal_winapi) {520 if (self.terminal_mode == .windows_api) {
520 try self.writeDiff(writer, ".", .{}, diff);521 try self.writeDiff(writer, ".", .{}, diff);
521 continue;522 continue;
522 }523 }
lib/std/zig.zig+7-14
...@@ -46,25 +46,18 @@ pub const SrcHasher = std.crypto.hash.Blake3;...@@ -46,25 +46,18 @@ pub const SrcHasher = std.crypto.hash.Blake3;
46pub const SrcHash = [16]u8;46pub const SrcHash = [16]u8;
4747
48pub const Color = enum {48pub const Color = enum {
49 /// Determine whether stderr is a terminal or not automatically.49 /// Auto-detect whether stream supports terminal colors.
50 auto,50 auto,
51 /// Assume stderr is not a terminal.51 /// Force-enable colors.
52 off,52 off,
53 /// Assume stderr is a terminal.53 /// Suppress colors.
54 on,54 on,
5555
56 pub fn getTtyConf(color: Color, detected: Io.File.Writer.Mode) Io.File.Writer.Mode {56 pub fn terminalMode(color: Color) ?Io.Terminal.Mode {
57 return switch (color) {57 return switch (color) {
58 .auto => detected,58 .auto => null,
59 .on => .terminal_escaped,59 .on => .escape_codes,
60 .off => .streaming,60 .off => .no_color,
61 };
62 }
63 pub fn detectTtyConf(color: Color, io: Io) Io.File.Writer.Mode {
64 return switch (color) {
65 .auto => .detect(io, .stderr()),
66 .on => .terminal_escaped,
67 .off => .streaming,
68 };61 };
69 }62 }
70};63};
lib/std/zig/ErrorBundle.zig+37-35
...@@ -166,51 +166,53 @@ pub const RenderToStderrError = Io.Cancelable || Io.File.Writer.Error;...@@ -166,51 +166,53 @@ pub const RenderToStderrError = Io.Cancelable || Io.File.Writer.Error;
166166
167pub fn renderToStderr(eb: ErrorBundle, io: Io, options: RenderOptions, color: std.zig.Color) RenderToStderrError!void {167pub fn renderToStderr(eb: ErrorBundle, io: Io, options: RenderOptions, color: std.zig.Color) RenderToStderrError!void {
168 var buffer: [256]u8 = undefined;168 var buffer: [256]u8 = undefined;
169 const stderr = try io.lockStderrWriter(&buffer);169 const stderr = try io.lockStderr(&buffer, color.terminalMode());
170 defer io.unlockStderrWriter();170 defer io.unlockStderr();
171 renderToWriter(eb, options, &stderr.interface, color.getTtyConf(stderr.mode)) catch |err| switch (err) {171 renderToTerminal(eb, options, stderr.terminal()) catch |err| switch (err) {
172 error.WriteFailed => return stderr.err.?,172 error.WriteFailed => return stderr.file_writer.err.?,
173 else => |e| return e,173 else => |e| return e,
174 };174 };
175}175}
176176
177pub fn renderToWriter(177pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer) Writer.Error!void {
178 eb: ErrorBundle,178 return renderToTerminal(eb, options, .{ .writer = w, .mode = .no_color }) catch |err| switch (err) {
179 options: RenderOptions,179 error.WriteFailed => |e| return e,
180 w: *Writer,180 else => unreachable,
181 fwm: Io.File.Writer.Mode,181 };
182) Io.File.Writer.Mode.SetColorError!void {182}
183
184pub fn renderToTerminal(eb: ErrorBundle, options: RenderOptions, t: Io.Terminal) Io.Terminal.SetColorError!void {
183 if (eb.extra.len == 0) return;185 if (eb.extra.len == 0) return;
184 for (eb.getMessages()) |err_msg| {186 for (eb.getMessages()) |err_msg| {
185 try renderErrorMessageToWriter(eb, options, err_msg, w, fwm, "error", .red, 0);187 try renderErrorMessage(eb, options, err_msg, t, "error", .red, 0);
186 }188 }
187189
188 if (options.include_log_text) {190 if (options.include_log_text) {
189 const log_text = eb.getCompileLogOutput();191 const log_text = eb.getCompileLogOutput();
190 if (log_text.len != 0) {192 if (log_text.len != 0) {
191 try w.writeAll("\nCompile Log Output:\n");193 try t.writer.writeAll("\nCompile Log Output:\n");
192 try w.writeAll(log_text);194 try t.writer.writeAll(log_text);
193 }195 }
194 }196 }
195}197}
196198
197fn renderErrorMessageToWriter(199fn renderErrorMessage(
198 eb: ErrorBundle,200 eb: ErrorBundle,
199 options: RenderOptions,201 options: RenderOptions,
200 err_msg_index: MessageIndex,202 err_msg_index: MessageIndex,
201 w: *Writer,203 t: Io.Terminal,
202 fwm: Io.File.Writer.Mode,
203 kind: []const u8,204 kind: []const u8,
204 color: Io.File.Writer.Color,205 color: Io.Terminal.Color,
205 indent: usize,206 indent: usize,
206) Io.File.Writer.Mode.SetColorError!void {207) Io.Terminal.SetColorError!void {
208 const w = t.writer;
207 const err_msg = eb.getErrorMessage(err_msg_index);209 const err_msg = eb.getErrorMessage(err_msg_index);
208 if (err_msg.src_loc != .none) {210 if (err_msg.src_loc != .none) {
209 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));211 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));
210 var prefix: Writer.Discarding = .init(&.{});212 var prefix: Writer.Discarding = .init(&.{});
211 try w.splatByteAll(' ', indent);213 try w.splatByteAll(' ', indent);
212 prefix.count += indent;214 prefix.count += indent;
213 try fwm.setColor(w, .bold);215 try t.setColor(.bold);
214 try w.print("{s}:{d}:{d}: ", .{216 try w.print("{s}:{d}:{d}: ", .{
215 eb.nullTerminatedString(src.data.src_path),217 eb.nullTerminatedString(src.data.src_path),
216 src.data.line + 1,218 src.data.line + 1,
...@@ -221,7 +223,7 @@ fn renderErrorMessageToWriter(...@@ -221,7 +223,7 @@ fn renderErrorMessageToWriter(
221 src.data.line + 1,223 src.data.line + 1,
222 src.data.column + 1,224 src.data.column + 1,
223 });225 });
224 try fwm.setColor(w, color);226 try t.setColor(color);
225 try w.writeAll(kind);227 try w.writeAll(kind);
226 prefix.count += kind.len;228 prefix.count += kind.len;
227 try w.writeAll(": ");229 try w.writeAll(": ");
...@@ -229,17 +231,17 @@ fn renderErrorMessageToWriter(...@@ -229,17 +231,17 @@ fn renderErrorMessageToWriter(
229 // This is the length of the part before the error message:231 // This is the length of the part before the error message:
230 // e.g. "file.zig:4:5: error: "232 // e.g. "file.zig:4:5: error: "
231 const prefix_len: usize = @intCast(prefix.count);233 const prefix_len: usize = @intCast(prefix.count);
232 try fwm.setColor(w, .reset);234 try t.setColor(.reset);
233 try fwm.setColor(w, .bold);235 try t.setColor(.bold);
234 if (err_msg.count == 1) {236 if (err_msg.count == 1) {
235 try writeMsg(eb, err_msg, w, prefix_len);237 try writeMsg(eb, err_msg, w, prefix_len);
236 try w.writeByte('\n');238 try w.writeByte('\n');
237 } else {239 } else {
238 try writeMsg(eb, err_msg, w, prefix_len);240 try writeMsg(eb, err_msg, w, prefix_len);
239 try fwm.setColor(w, .dim);241 try t.setColor(.dim);
240 try w.print(" ({d} times)\n", .{err_msg.count});242 try w.print(" ({d} times)\n", .{err_msg.count});
241 }243 }
242 try fwm.setColor(w, .reset);244 try t.setColor(.reset);
243 if (src.data.source_line != 0 and options.include_source_line) {245 if (src.data.source_line != 0 and options.include_source_line) {
244 const line = eb.nullTerminatedString(src.data.source_line);246 const line = eb.nullTerminatedString(src.data.source_line);
245 for (line) |b| switch (b) {247 for (line) |b| switch (b) {
...@@ -252,19 +254,19 @@ fn renderErrorMessageToWriter(...@@ -252,19 +254,19 @@ fn renderErrorMessageToWriter(
252 // -1 since span.main includes the caret254 // -1 since span.main includes the caret
253 const after_caret = src.data.span_end -| src.data.span_main -| 1;255 const after_caret = src.data.span_end -| src.data.span_main -| 1;
254 try w.splatByteAll(' ', src.data.column - before_caret);256 try w.splatByteAll(' ', src.data.column - before_caret);
255 try fwm.setColor(w, .green);257 try t.setColor(.green);
256 try w.splatByteAll('~', before_caret);258 try w.splatByteAll('~', before_caret);
257 try w.writeByte('^');259 try w.writeByte('^');
258 try w.splatByteAll('~', after_caret);260 try w.splatByteAll('~', after_caret);
259 try w.writeByte('\n');261 try w.writeByte('\n');
260 try fwm.setColor(w, .reset);262 try t.setColor(.reset);
261 }263 }
262 for (eb.getNotes(err_msg_index)) |note| {264 for (eb.getNotes(err_msg_index)) |note| {
263 try renderErrorMessageToWriter(eb, options, note, w, fwm, "note", .cyan, indent);265 try renderErrorMessage(eb, options, note, t, "note", .cyan, indent);
264 }266 }
265 if (src.data.reference_trace_len > 0 and options.include_reference_trace) {267 if (src.data.reference_trace_len > 0 and options.include_reference_trace) {
266 try fwm.setColor(w, .reset);268 try t.setColor(.reset);
267 try fwm.setColor(w, .dim);269 try t.setColor(.dim);
268 try w.print("referenced by:\n", .{});270 try w.print("referenced by:\n", .{});
269 var ref_index = src.end;271 var ref_index = src.end;
270 for (0..src.data.reference_trace_len) |_| {272 for (0..src.data.reference_trace_len) |_| {
...@@ -291,25 +293,25 @@ fn renderErrorMessageToWriter(...@@ -291,25 +293,25 @@ fn renderErrorMessageToWriter(
291 );293 );
292 }294 }
293 }295 }
294 try fwm.setColor(w, .reset);296 try t.setColor(.reset);
295 }297 }
296 } else {298 } else {
297 try fwm.setColor(w, color);299 try t.setColor(color);
298 try w.splatByteAll(' ', indent);300 try w.splatByteAll(' ', indent);
299 try w.writeAll(kind);301 try w.writeAll(kind);
300 try w.writeAll(": ");302 try w.writeAll(": ");
301 try fwm.setColor(w, .reset);303 try t.setColor(.reset);
302 const msg = eb.nullTerminatedString(err_msg.msg);304 const msg = eb.nullTerminatedString(err_msg.msg);
303 if (err_msg.count == 1) {305 if (err_msg.count == 1) {
304 try w.print("{s}\n", .{msg});306 try w.print("{s}\n", .{msg});
305 } else {307 } else {
306 try w.print("{s}", .{msg});308 try w.print("{s}", .{msg});
307 try fwm.setColor(w, .dim);309 try t.setColor(.dim);
308 try w.print(" ({d} times)\n", .{err_msg.count});310 try w.print(" ({d} times)\n", .{err_msg.count});
309 }311 }
310 try fwm.setColor(w, .reset);312 try t.setColor(.reset);
311 for (eb.getNotes(err_msg_index)) |note| {313 for (eb.getNotes(err_msg_index)) |note| {
312 try renderErrorMessageToWriter(eb, options, note, w, fwm, "note", .cyan, indent + 4);314 try renderErrorMessage(eb, options, note, t, "note", .cyan, indent + 4);
313 }315 }
314 }316 }
315}317}
lib/std/zig/parser_test.zig+8-8
...@@ -6333,25 +6333,25 @@ var fixed_buffer_mem: [100 * 1024]u8 = undefined;...@@ -6333,25 +6333,25 @@ var fixed_buffer_mem: [100 * 1024]u8 = undefined;
63336333
6334fn testParse(io: Io, source: [:0]const u8, allocator: Allocator, anything_changed: *bool) ![]u8 {6334fn testParse(io: Io, source: [:0]const u8, allocator: Allocator, anything_changed: *bool) ![]u8 {
6335 var buffer: [64]u8 = undefined;6335 var buffer: [64]u8 = undefined;
6336 const stderr = try io.lockStderrWriter(&buffer);6336 const stderr = try io.lockStderr(&buffer, null);
6337 defer io.unlockStderrWriter();6337 defer io.unlockStderr();
63386338
6339 var tree = try std.zig.Ast.parse(allocator, source, .zig);6339 var tree = try std.zig.Ast.parse(allocator, source, .zig);
6340 defer tree.deinit(allocator);6340 defer tree.deinit(allocator);
63416341
6342 for (tree.errors) |parse_error| {6342 for (tree.errors) |parse_error| {
6343 const loc = tree.tokenLocation(0, parse_error.token);6343 const loc = tree.tokenLocation(0, parse_error.token);
6344 try stderr.printUnescaped("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 });6344 try stderr.writer.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 });
6345 try tree.renderError(parse_error, &stderr.interface);6345 try tree.renderError(parse_error, stderr.writer);
6346 try stderr.interface.print("\n{s}\n", .{source[loc.line_start..loc.line_end]});6346 try stderr.writer.print("\n{s}\n", .{source[loc.line_start..loc.line_end]});
6347 {6347 {
6348 var i: usize = 0;6348 var i: usize = 0;
6349 while (i < loc.column) : (i += 1) {6349 while (i < loc.column) : (i += 1) {
6350 try stderr.writeAllUnescaped(" ");6350 try stderr.writer.writeAll(" ");
6351 }6351 }
6352 try stderr.writeAllUnescaped("^");6352 try stderr.writer.writeAll("^");
6353 }6353 }
6354 try stderr.writeAllUnescaped("\n");6354 try stderr.writer.writeAll("\n");
6355 }6355 }
6356 if (tree.errors.len != 0) {6356 if (tree.errors.len != 0) {
6357 return error.ParseError;6357 return error.ParseError;
src/Air/print.zig+6-6
...@@ -76,9 +76,9 @@ pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {...@@ -76,9 +76,9 @@ pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
76 const comp = pt.zcu.comp;76 const comp = pt.zcu.comp;
77 const io = comp.io;77 const io = comp.io;
78 var buffer: [512]u8 = undefined;78 var buffer: [512]u8 = undefined;
79 const stderr = try io.lockStderrWriter(&buffer);79 const stderr = try io.lockStderr(&buffer, null);
80 defer io.unlockStderrWriter();80 defer io.unlockStderr();
81 const w = &stderr.interface;81 const w = &stderr.file_writer.interface;
82 air.write(w, pt, liveness);82 air.write(w, pt, liveness);
83}83}
8484
...@@ -86,9 +86,9 @@ pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Ai...@@ -86,9 +86,9 @@ pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Ai
86 const comp = pt.zcu.comp;86 const comp = pt.zcu.comp;
87 const io = comp.io;87 const io = comp.io;
88 var buffer: [512]u8 = undefined;88 var buffer: [512]u8 = undefined;
89 const stderr = try io.lockStderrWriter(&buffer);89 const stderr = try io.lockStderr(&buffer, null);
90 defer io.unlockStderrWriter();90 defer io.unlockStderr();
91 const w = &stderr.interface;91 const w = &stderr.file_writer.interface;
92 air.writeInst(w, inst, pt, liveness);92 air.writeInst(w, inst, pt, liveness);
93}93}
9494
src/Compilation.zig+30-15
...@@ -2092,14 +2092,16 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2092,14 +2092,16 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2092 }2092 }
20932093
2094 if (options.verbose_llvm_cpu_features) {2094 if (options.verbose_llvm_cpu_features) {
2095 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {2095 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| {
2096 const stderr = try io.lockStderrWriter(&.{});2096 const stderr = try io.lockStderr(&.{}, null);
2097 defer io.unlockStderrWriter();2097 defer io.unlockStderr();
2098 const w = &stderr.interface;2098 const w = &stderr.file_writer.interface;
2099 w.print("compilation: {s}\n", .{options.root_name}) catch break :print;2099 printVerboseLlvmCpuFeatures(w, arena, options.root_name, target, cf) catch |err| switch (err) {
2100 w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;2100 error.WriteFailed => switch (stderr.file_writer.err.?) {
2101 w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print;2101 error.Canceled => |e| return e,
2102 w.print(" features: {s}\n", .{cf}) catch {};2102 else => {},
2103 },
2104 };
2103 }2105 }
2104 }2106 }
21052107
...@@ -2700,6 +2702,19 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2700,6 +2702,19 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2700 return comp;2702 return comp;
2701}2703}
27022704
2705fn printVerboseLlvmCpuFeatures(
2706 w: *Writer,
2707 arena: Allocator,
2708 root_name: []const u8,
2709 target: *const std.Target,
2710 cf: [*:0]const u8,
2711) Writer.Error!void {
2712 try w.print("compilation: {s}\n", .{root_name});
2713 try w.print(" target: {s}\n", .{try target.zigTriple(arena)});
2714 try w.print(" cpu: {s}\n", .{target.cpu.model.name});
2715 try w.print(" features: {s}\n", .{cf});
2716}
2717
2703pub fn destroy(comp: *Compilation) void {2718pub fn destroy(comp: *Compilation) void {
2704 const gpa = comp.gpa;2719 const gpa = comp.gpa;
2705 const io = comp.io;2720 const io = comp.io;
...@@ -4259,9 +4274,9 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {...@@ -4259,9 +4274,9 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
4259 // However, we haven't reported any such error.4274 // However, we haven't reported any such error.
4260 // This is a compiler bug.4275 // This is a compiler bug.
4261 print_ctx: {4276 print_ctx: {
4262 const stderr = std.debug.lockStderrWriter(&.{});4277 const stderr = std.debug.lockStderr(&.{}).terminal();
4263 defer std.debug.unlockStderrWriter();4278 defer std.debug.unlockStderr();
4264 const w = &stderr.interface;4279 const w = stderr.writer;
4265 w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx;4280 w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx;
4266 w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx;4281 w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx;
4267 while (ref) |r| {4282 while (ref) |r| {
...@@ -7772,11 +7787,11 @@ pub fn lockAndSetMiscFailure(...@@ -7772,11 +7787,11 @@ pub fn lockAndSetMiscFailure(
77727787
7773pub fn dumpArgv(io: Io, argv: []const []const u8) Io.Cancelable!void {7788pub fn dumpArgv(io: Io, argv: []const []const u8) Io.Cancelable!void {
7774 var buffer: [64]u8 = undefined;7789 var buffer: [64]u8 = undefined;
7775 const stderr = try io.lockStderrWriter(&buffer);7790 const stderr = try io.lockStderr(&buffer);
7776 defer io.unlockStderrWriter();7791 defer io.unlockStderr();
7777 const w = &stderr.interface;7792 const w = &stderr.file_writer.interface;
7778 return dumpArgvWriter(w, argv) catch |err| switch (err) {7793 return dumpArgvWriter(w, argv) catch |err| switch (err) {
7779 error.WriteFailed => switch (stderr.err.?) {7794 error.WriteFailed => switch (stderr.file_writer.err.?) {
7780 error.Canceled => return error.Canceled,7795 error.Canceled => return error.Canceled,
7781 else => return,7796 else => return,
7782 },7797 },
src/InternPool.zig+5-5
...@@ -11169,9 +11169,9 @@ pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) v...@@ -11169,9 +11169,9 @@ pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) v
1116911169
11170pub fn dump(ip: *const InternPool, io: Io) Io.Cancelable!void {11170pub fn dump(ip: *const InternPool, io: Io) Io.Cancelable!void {
11171 var buffer: [4096]u8 = undefined;11171 var buffer: [4096]u8 = undefined;
11172 const stderr_writer = try io.lockStderrWriter(&buffer);11172 const stderr = try io.lockStderr(&buffer, null);
11173 defer io.unlockStderrWriter();11173 defer io.unlockStderr();
11174 const w = &stderr_writer.interface;11174 const w = &stderr.file_writer.interface;
11175 try dumpStatsFallible(ip, w, std.heap.page_allocator);11175 try dumpStatsFallible(ip, w, std.heap.page_allocator);
11176 try dumpAllFallible(ip, w);11176 try dumpAllFallible(ip, w);
11177}11177}
...@@ -11536,8 +11536,8 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {...@@ -11536,8 +11536,8 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
1153611536
11537pub fn dumpGenericInstances(ip: *const InternPool, io: Io, allocator: Allocator) Io.Cancelable!void {11537pub fn dumpGenericInstances(ip: *const InternPool, io: Io, allocator: Allocator) Io.Cancelable!void {
11538 var buffer: [4096]u8 = undefined;11538 var buffer: [4096]u8 = undefined;
11539 const stderr_writer = try io.lockStderrWriter(&buffer);11539 const stderr_writer = try io.lockStderr(&buffer, null);
11540 defer io.unlockStderrWriter();11540 defer io.unlockStderr();
11541 const w = &stderr_writer.interface;11541 const w = &stderr_writer.interface;
11542 try ip.dumpGenericInstancesFallible(allocator, w);11542 try ip.dumpGenericInstancesFallible(allocator, w);
11543}11543}
src/Zcu/PerThread.zig+4-4
...@@ -4560,10 +4560,10 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4560,10 +4560,10 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
45604560
4561 if (build_options.enable_debug_extensions and comp.verbose_air) p: {4561 if (build_options.enable_debug_extensions and comp.verbose_air) p: {
4562 const io = comp.io;4562 const io = comp.io;
4563 const stderr = try io.lockStderrWriter(&.{});4563 const stderr = try io.lockStderr(&.{}, null);
4564 defer io.unlockStderrWriter();4564 defer io.unlockStderr();
4565 printVerboseAir(pt, liveness, fqn, air, &stderr.interface) catch |err| switch (err) {4565 printVerboseAir(pt, liveness, fqn, air, &stderr.file_writer.interface) catch |err| switch (err) {
4566 error.WriteFailed => switch (stderr.err.?) {4566 error.WriteFailed => switch (stderr.file_writer.err.?) {
4567 error.Canceled => |e| return e,4567 error.Canceled => |e| return e,
4568 else => break :p,4568 else => break :p,
4569 },4569 },
src/codegen/aarch64/Select.zig+3-4
...@@ -11274,16 +11274,15 @@ fn initValueAdvanced(...@@ -11274,16 +11274,15 @@ fn initValueAdvanced(
11274}11274}
11275pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void {11275pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void {
11276 const zcu = isel.pt.zcu;11276 const zcu = isel.pt.zcu;
11277 const io = zcu.comp.io;
11278 const gpa = zcu.gpa;11277 const gpa = zcu.gpa;
11279 const ip = &zcu.intern_pool;11278 const ip = &zcu.intern_pool;
11280 const nav = ip.getNav(isel.nav_index);11279 const nav = ip.getNav(isel.nav_index);
1128111280
11282 errdefer |err| @panic(@errorName(err));11281 errdefer |err| @panic(@errorName(err));
1128311282
11284 const stderr_writer = io.lockStderrWriter(&.{}) catch return;11283 const locked_stderr = std.debug.lockStderr(&.{}, null);
11285 defer io.unlockStderrWriter();11284 defer std.debug.unlockStderr();
11286 const stderr = &stderr_writer.interface;11285 const stderr = &locked_stderr.file_writer.interface;
1128711286
11288 var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty;11287 var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty;
11289 defer {11288 defer {
src/crash_report.zig+3-3
...@@ -95,9 +95,9 @@ fn dumpCrashContext() Io.Writer.Error!void {...@@ -95,9 +95,9 @@ fn dumpCrashContext() Io.Writer.Error!void {
9595
96 // TODO: this does mean that a different thread could grab the stderr mutex between the context96 // TODO: this does mean that a different thread could grab the stderr mutex between the context
97 // and the actual panic printing, which would be quite confusing.97 // and the actual panic printing, which would be quite confusing.
98 const stderr = std.debug.lockStderrWriter(&.{});98 const stderr = std.debug.lockStderr(&.{});
99 defer std.debug.unlockStderrWriter();99 defer std.debug.unlockStderr();
100 const w = &stderr.interface;100 const w = &stderr.file_writer.interface;
101101
102 try w.writeAll("Compiler crash context:\n");102 try w.writeAll("Compiler crash context:\n");
103103
src/libs/mingw.zig+12-12
...@@ -314,14 +314,14 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -314,14 +314,14 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
314314
315 if (comp.verbose_cc) {315 if (comp.verbose_cc) {
316 var buffer: [256]u8 = undefined;316 var buffer: [256]u8 = undefined;
317 const stderr = try io.lockStderrWriter(&buffer);317 const stderr = try io.lockStderr(&buffer, null);
318 defer io.unlockStderrWriter();318 defer io.unlockStderr();
319 const w = &stderr.interface;319 const w = &stderr.file_writer.interface;
320 w.print("def file: {s}\n", .{def_file_path}) catch |err| switch (err) {320 w.print("def file: {s}\n", .{def_file_path}) catch |err| switch (err) {
321 error.WriteFailed => return stderr.err.?,321 error.WriteFailed => return stderr.file_writer.err.?,
322 };322 };
323 w.print("include dir: {s}\n", .{include_dir}) catch |err| switch (err) {323 w.print("include dir: {s}\n", .{include_dir}) catch |err| switch (err) {
324 error.WriteFailed => return stderr.err.?,324 error.WriteFailed => return stderr.file_writer.err.?,
325 };325 };
326 }326 }
327327
...@@ -339,12 +339,12 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -339,12 +339,12 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
339339
340 if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {340 if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {
341 var buffer: [64]u8 = undefined;341 var buffer: [64]u8 = undefined;
342 const stderr = try io.lockStderrWriter(&buffer);342 const stderr = try io.lockStderr(&buffer, null);
343 defer io.unlockStderrWriter();343 defer io.unlockStderr();
344 for (aro_comp.diagnostics.output.to_list.messages.items) |msg| {344 for (aro_comp.diagnostics.output.to_list.messages.items) |msg| {
345 if (msg.kind == .@"fatal error" or msg.kind == .@"error") {345 if (msg.kind == .@"fatal error" or msg.kind == .@"error") {
346 msg.write(&stderr.interface, stderr.mode, true) catch |err| switch (err) {346 msg.write(stderr.terminal(), true) catch |err| switch (err) {
347 error.WriteFailed => return stderr.err.?,347 error.WriteFailed => return stderr.file_writer.err.?,
348 };348 };
349 return error.AroPreprocessorFailed;349 return error.AroPreprocessorFailed;
350 }350 }
...@@ -365,9 +365,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -365,9 +365,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
365 error.OutOfMemory => |e| return e,365 error.OutOfMemory => |e| return e,
366 error.ParseError => {366 error.ParseError => {
367 var buffer: [64]u8 = undefined;367 var buffer: [64]u8 = undefined;
368 const stderr = try io.lockStderrWriter(&buffer);368 const stderr = try io.lockStderr(&buffer, null);
369 defer io.unlockStderrWriter();369 defer io.unlockStderr();
370 const w = &stderr.interface;370 const w = &stderr.file_writer.interface;
371 try w.writeAll("error: ");371 try w.writeAll("error: ");
372 try def_diagnostics.writeMsg(w, input);372 try def_diagnostics.writeMsg(w, input);
373 try w.writeByte('\n');373 try w.writeByte('\n');
src/libs/mingw/def.zig+3-3
...@@ -1039,9 +1039,9 @@ fn testParse(...@@ -1039,9 +1039,9 @@ fn testParse(
1039 const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) {1039 const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) {
1040 error.OutOfMemory => |e| return e,1040 error.OutOfMemory => |e| return e,
1041 error.ParseError => {1041 error.ParseError => {
1042 const stderr = try io.lockStderrWriter(&.{});1042 const stderr = try io.lockStderr(&.{}, null);
1043 defer io.unlockStderrWriter();1043 defer io.unlockStderr();
1044 const w = &stderr.interface;1044 const w = &stderr.file_writer.interface;
1045 try diagnostics.writeMsg(w, source);1045 try diagnostics.writeMsg(w, source);
1046 try w.writeByte('\n');1046 try w.writeByte('\n');
1047 return err;1047 return err;
src/link/Coff.zig+3-3
...@@ -2382,9 +2382,9 @@ pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {...@@ -2382,9 +2382,9 @@ pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {
2382 const comp = coff.base.comp;2382 const comp = coff.base.comp;
2383 const io = comp.io;2383 const io = comp.io;
2384 var buffer: [512]u8 = undefined;2384 var buffer: [512]u8 = undefined;
2385 const stderr = try io.lockStderrWriter(&buffer);2385 const stderr = try io.lockStderr(&buffer, null);
2386 defer io.unlockStderrWriter();2386 defer io.unlockStderr();
2387 const w = &stderr.interface;2387 const w = &stderr.file_writer.interface;
2388 coff.printNode(tid, w, .root, 0) catch |err| switch (err) {2388 coff.printNode(tid, w, .root, 0) catch |err| switch (err) {
2389 error.WriteFailed => return stderr.err.?,2389 error.WriteFailed => return stderr.err.?,
2390 };2390 };
src/link/Elf2.zig+3-3
...@@ -3733,9 +3733,9 @@ pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {...@@ -3733,9 +3733,9 @@ pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {
3733 const comp = elf.base.comp;3733 const comp = elf.base.comp;
3734 const io = comp.io;3734 const io = comp.io;
3735 var buffer: [512]u8 = undefined;3735 var buffer: [512]u8 = undefined;
3736 const stderr = try io.lockStderrWriter(&buffer);3736 const stderr = try io.lockStderr(&buffer, null);
3737 defer io.unlockStderrWriter();3737 defer io.lockStderr();
3738 const w = &stderr.interface;3738 const w = &stderr.file_writer.interface;
3739 elf.printNode(tid, w, .root, 0) catch |err| switch (err) {3739 elf.printNode(tid, w, .root, 0) catch |err| switch (err) {
3740 error.WriteFailed => return stderr.err.?,3740 error.WriteFailed => return stderr.err.?,
3741 };3741 };
src/main.zig+6-6
...@@ -4429,9 +4429,9 @@ fn runOrTest(...@@ -4429,9 +4429,9 @@ fn runOrTest(
4429 // the error message and invocation below.4429 // the error message and invocation below.
4430 if (process.can_execv and arg_mode == .run) {4430 if (process.can_execv and arg_mode == .run) {
4431 // execv releases the locks; no need to destroy the Compilation here.4431 // execv releases the locks; no need to destroy the Compilation here.
4432 _ = try io.lockStderrWriter(&.{});4432 _ = try io.lockStderr(&.{}, .no_color);
4433 const err = process.execve(gpa, argv.items, &env_map);4433 const err = process.execve(gpa, argv.items, &env_map);
4434 io.unlockStderrWriter();4434 io.unlockStderr();
4435 try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc);4435 try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc);
4436 const cmd = try std.mem.join(arena, " ", argv.items);4436 const cmd = try std.mem.join(arena, " ", argv.items);
4437 fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd });4437 fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd });
...@@ -4448,8 +4448,8 @@ fn runOrTest(...@@ -4448,8 +4448,8 @@ fn runOrTest(
4448 comp_destroyed.* = true;4448 comp_destroyed.* = true;
44494449
4450 const term_result = t: {4450 const term_result = t: {
4451 _ = try io.lockStderrWriter(&.{});4451 _ = try io.lockStderr(&.{}, .no_color);
4452 defer io.unlockStderrWriter();4452 defer io.unlockStderr();
4453 break :t child.spawnAndWait(io);4453 break :t child.spawnAndWait(io);
4454 };4454 };
4455 const term = term_result catch |err| {4455 const term = term_result catch |err| {
...@@ -5418,8 +5418,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)...@@ -5418,8 +5418,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
5418 child.stderr_behavior = .Inherit;5418 child.stderr_behavior = .Inherit;
54195419
5420 const term = t: {5420 const term = t: {
5421 _ = try io.lockStderrWriter(&.{});5421 _ = try io.lockStderr(&.{}, .no_color);
5422 defer io.unlockStderrWriter();5422 defer io.unlockStderr();
5423 break :t child.spawnAndWait(io) catch |err|5423 break :t child.spawnAndWait(io) catch |err|
5424 fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err });5424 fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err });
5425 };5425 };