authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-09 18:13:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:14-07:00
log7cc4a6965c28e427cbfba57a985f837734d6257e
tree94c753ad16675b7cf2441b117f02282be20fae34
parent3186658e602b13a98c388872bbdc0b5cc1eb9267

build runner enhancements in preparation for test-cases

* std.zig.ErrorBundle: support rendering options for whether to include the reference trace, whether to include the source line, and TTY configuration. * build runner: don't print progress in dumb terminals * std.Build.CompileStep: - add a way to expect compilation errors via the new `expect_errors` field. This is an advanced setting that can change the intent of the CompileStep. If this slice has nonzero length, it means that the CompileStep exists to check for compile errors and return *success* if they match, and failure otherwise. - remove the object format parameter from `checkObject`. The object format is known based on the CompileStep's target. - Avoid passing -L and -I flags for nonexistent directories within search_prefixes. This prevents a warning, that should probably be upgraded to an error in Zig's CLI parsing code, when the linker sees an -L directory that does not exist. * std.Build.Step: - When spawning the zig compiler process, takes advantage of the new `std.Progress.Node.setName` API to avoid ticking up a meaningless number at every progress update.

6 files changed, 173 insertions(+), 49 deletions(-)

lib/build_runner.zig+21-9
...@@ -84,8 +84,6 @@ pub fn main() !void {...@@ -84,8 +84,6 @@ pub fn main() !void {
84 );84 );
85 defer builder.destroy();85 defer builder.destroy();
8686
87 const Color = enum { auto, off, on };
88
89 var targets = ArrayList([]const u8).init(arena);87 var targets = ArrayList([]const u8).init(arena);
90 var debug_log_scopes = ArrayList([]const u8).init(arena);88 var debug_log_scopes = ArrayList([]const u8).init(arena);
91 var thread_pool_options: std.Thread.Pool.Options = .{ .allocator = arena };89 var thread_pool_options: std.Thread.Pool.Options = .{ .allocator = arena };
...@@ -273,13 +271,9 @@ pub fn main() !void {...@@ -273,13 +271,9 @@ pub fn main() !void {
273 }271 }
274272
275 const stderr = std.io.getStdErr();273 const stderr = std.io.getStdErr();
276 const ttyconf: std.debug.TTY.Config = switch (color) {274 const ttyconf = get_tty_conf(color, stderr);
277 .auto => std.debug.detectTTYConfig(stderr),
278 .on => .escape_codes,
279 .off => .no_color,
280 };
281275
282 var progress: std.Progress = .{};276 var progress: std.Progress = .{ .dont_print_on_dumb = true };
283 const main_progress_node = progress.start("", 0);277 const main_progress_node = progress.start("", 0);
284278
285 builder.debug_log_scopes = debug_log_scopes.items;279 builder.debug_log_scopes = debug_log_scopes.items;
...@@ -498,7 +492,7 @@ fn runStepNames(...@@ -498,7 +492,7 @@ fn runStepNames(
498 if (total_compile_errors > 0) {492 if (total_compile_errors > 0) {
499 for (compile_error_steps.items) |s| {493 for (compile_error_steps.items) |s| {
500 if (s.result_error_bundle.errorMessageCount() > 0) {494 if (s.result_error_bundle.errorMessageCount() > 0) {
501 s.result_error_bundle.renderToStdErr(ttyconf);495 s.result_error_bundle.renderToStdErr(renderOptions(ttyconf));
502 }496 }
503 }497 }
504498
...@@ -961,3 +955,21 @@ fn cleanExit() void {...@@ -961,3 +955,21 @@ fn cleanExit() void {
961 // of calling exit.955 // of calling exit.
962 process.exit(0);956 process.exit(0);
963}957}
958
959const Color = enum { auto, off, on };
960
961fn get_tty_conf(color: Color, stderr: std.fs.File) std.debug.TTY.Config {
962 return switch (color) {
963 .auto => std.debug.detectTTYConfig(stderr),
964 .on => .escape_codes,
965 .off => .no_color,
966 };
967}
968
969fn renderOptions(ttyconf: std.debug.TTY.Config) std.zig.ErrorBundle.RenderOptions {
970 return .{
971 .ttyconf = ttyconf,
972 .include_source_line = ttyconf != .no_color,
973 .include_reference_trace = ttyconf != .no_color,
974 };
975}
lib/std/Build/CompileStep.zig+102-11
...@@ -207,6 +207,12 @@ want_lto: ?bool = null,...@@ -207,6 +207,12 @@ want_lto: ?bool = null,
207use_llvm: ?bool = null,207use_llvm: ?bool = null,
208use_lld: ?bool = null,208use_lld: ?bool = null,
209209
210/// This is an advanced setting that can change the intent of this CompileStep.
211/// If this slice has nonzero length, it means that this CompileStep exists to
212/// check for compile errors and return *success* if they match, and failure
213/// otherwise.
214expect_errors: []const []const u8 = &.{},
215
210output_path_source: GeneratedFile,216output_path_source: GeneratedFile,
211output_lib_path_source: GeneratedFile,217output_lib_path_source: GeneratedFile,
212output_h_path_source: GeneratedFile,218output_h_path_source: GeneratedFile,
...@@ -552,8 +558,8 @@ pub fn run(cs: *CompileStep) *RunStep {...@@ -552,8 +558,8 @@ pub fn run(cs: *CompileStep) *RunStep {
552 return cs.step.owner.addRunArtifact(cs);558 return cs.step.owner.addRunArtifact(cs);
553}559}
554560
555pub fn checkObject(self: *CompileStep, obj_format: std.Target.ObjectFormat) *CheckObjectStep {561pub fn checkObject(self: *CompileStep) *CheckObjectStep {
556 return CheckObjectStep.create(self.step.owner, self.getOutputSource(), obj_format);562 return CheckObjectStep.create(self.step.owner, self.getOutputSource(), self.target_info.target.ofmt);
557}563}
558564
559pub fn setLinkerScriptPath(self: *CompileStep, source: FileSource) void {565pub fn setLinkerScriptPath(self: *CompileStep, source: FileSource) void {
...@@ -1838,14 +1844,38 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1838,14 +1844,38 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1838 }1844 }
18391845
1840 for (b.search_prefixes.items) |search_prefix| {1846 for (b.search_prefixes.items) |search_prefix| {
1841 try zig_args.append("-L");1847 var prefix_dir = fs.cwd().openDir(search_prefix, .{}) catch |err| {
1842 try zig_args.append(b.pathJoin(&.{1848 return step.fail("unable to open prefix directory '{s}': {s}", .{
1843 search_prefix, "lib",1849 search_prefix, @errorName(err),
1844 }));1850 });
1845 try zig_args.append("-I");1851 };
1846 try zig_args.append(b.pathJoin(&.{1852 defer prefix_dir.close();
1847 search_prefix, "include",1853
1848 }));1854 // Avoid passing -L and -I flags for nonexistent directories.
1855 // This prevents a warning, that should probably be upgraded to an error in Zig's
1856 // CLI parsing code, when the linker sees an -L directory that does not exist.
1857
1858 if (prefix_dir.accessZ("lib", .{})) |_| {
1859 try zig_args.appendSlice(&.{
1860 "-L", try fs.path.join(b.allocator, &.{ search_prefix, "lib" }),
1861 });
1862 } else |err| switch (err) {
1863 error.FileNotFound => {},
1864 else => |e| return step.fail("unable to access '{s}/lib' directory: {s}", .{
1865 search_prefix, @errorName(e),
1866 }),
1867 }
1868
1869 if (prefix_dir.accessZ("include", .{})) |_| {
1870 try zig_args.appendSlice(&.{
1871 "-I", try fs.path.join(b.allocator, &.{ search_prefix, "include" }),
1872 });
1873 } else |err| switch (err) {
1874 error.FileNotFound => {},
1875 else => |e| return step.fail("unable to access '{s}/include' directory: {s}", .{
1876 search_prefix, @errorName(e),
1877 }),
1878 }
1849 }1879 }
18501880
1851 try addFlag(&zig_args, "valgrind", self.valgrind_support);1881 try addFlag(&zig_args, "valgrind", self.valgrind_support);
...@@ -1943,7 +1973,14 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1943,7 +1973,14 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1943 try zig_args.append(resolved_args_file);1973 try zig_args.append(resolved_args_file);
1944 }1974 }
19451975
1946 const output_bin_path = try step.evalZigProcess(zig_args.items, prog_node);1976 const output_bin_path = step.evalZigProcess(zig_args.items, prog_node) catch |err| switch (err) {
1977 error.NeedCompileErrorCheck => {
1978 assert(self.expect_errors.len != 0);
1979 try checkCompileErrors(self);
1980 return;
1981 },
1982 else => |e| return e,
1983 };
1947 const build_output_dir = fs.path.dirname(output_bin_path).?;1984 const build_output_dir = fs.path.dirname(output_bin_path).?;
19481985
1949 if (self.output_dir) |output_dir| {1986 if (self.output_dir) |output_dir| {
...@@ -2178,3 +2215,57 @@ const TransitiveDeps = struct {...@@ -2178,3 +2215,57 @@ const TransitiveDeps = struct {
2178 }2215 }
2179 }2216 }
2180};2217};
2218
2219fn checkCompileErrors(self: *CompileStep) !void {
2220 // Clear this field so that it does not get printed by the build runner.
2221 const actual_eb = self.step.result_error_bundle;
2222 self.step.result_error_bundle = std.zig.ErrorBundle.empty;
2223
2224 const arena = self.step.owner.allocator;
2225
2226 var actual_stderr_list = std.ArrayList(u8).init(arena);
2227 try actual_eb.renderToWriter(.{
2228 .ttyconf = .no_color,
2229 .include_reference_trace = false,
2230 .include_source_line = false,
2231 }, actual_stderr_list.writer());
2232 const actual_stderr = try actual_stderr_list.toOwnedSlice();
2233
2234 // Render the expected lines into a string that we can compare verbatim.
2235 var expected_generated = std.ArrayList(u8).init(arena);
2236
2237 var actual_line_it = mem.split(u8, actual_stderr, "\n");
2238 for (self.expect_errors) |expect_line| {
2239 const actual_line = actual_line_it.next() orelse {
2240 try expected_generated.appendSlice(expect_line);
2241 try expected_generated.append('\n');
2242 continue;
2243 };
2244 if (mem.endsWith(u8, actual_line, expect_line)) {
2245 try expected_generated.appendSlice(actual_line);
2246 try expected_generated.append('\n');
2247 continue;
2248 }
2249 if (mem.startsWith(u8, expect_line, ":?:?: ")) {
2250 if (mem.endsWith(u8, actual_line, expect_line[":?:?: ".len..])) {
2251 try expected_generated.appendSlice(actual_line);
2252 try expected_generated.append('\n');
2253 continue;
2254 }
2255 }
2256 try expected_generated.appendSlice(expect_line);
2257 try expected_generated.append('\n');
2258 }
2259
2260 if (mem.eql(u8, expected_generated.items, actual_stderr)) return;
2261
2262 // TODO merge this with the testing.expectEqualStrings logic, and also CheckFile
2263 return self.step.fail(
2264 \\
2265 \\========= expected: =====================
2266 \\{s}
2267 \\========= but found: ====================
2268 \\{s}
2269 \\=========================================
2270 , .{ expected_generated.items, actual_stderr });
2271}
lib/std/Build/Step.zig+15-5
...@@ -295,8 +295,8 @@ pub fn evalZigProcess(...@@ -295,8 +295,8 @@ pub fn evalZigProcess(
295295
296 var node_name: std.ArrayListUnmanaged(u8) = .{};296 var node_name: std.ArrayListUnmanaged(u8) = .{};
297 defer node_name.deinit(gpa);297 defer node_name.deinit(gpa);
298 var sub_prog_node: ?std.Progress.Node = null;298 var sub_prog_node = prog_node.start("", 0);
299 defer if (sub_prog_node) |*n| n.end();299 defer sub_prog_node.end();
300300
301 const stdout = poller.fifo(.stdout);301 const stdout = poller.fifo(.stdout);
302302
...@@ -336,11 +336,9 @@ pub fn evalZigProcess(...@@ -336,11 +336,9 @@ pub fn evalZigProcess(
336 };336 };
337 },337 },
338 .progress => {338 .progress => {
339 if (sub_prog_node) |*n| n.end();
340 node_name.clearRetainingCapacity();339 node_name.clearRetainingCapacity();
341 try node_name.appendSlice(gpa, body);340 try node_name.appendSlice(gpa, body);
342 sub_prog_node = prog_node.start(node_name.items, 0);341 sub_prog_node.setName(node_name.items);
343 sub_prog_node.?.activate();
344 },342 },
345 .emit_bin_path => {343 .emit_bin_path => {
346 const EbpHdr = std.zig.Server.Message.EmitBinPath;344 const EbpHdr = std.zig.Server.Message.EmitBinPath;
...@@ -371,6 +369,18 @@ pub fn evalZigProcess(...@@ -371,6 +369,18 @@ pub fn evalZigProcess(
371 s.result_duration_ns = timer.read();369 s.result_duration_ns = timer.read();
372 s.result_peak_rss = child.resource_usage_statistics.getMaxRss() orelse 0;370 s.result_peak_rss = child.resource_usage_statistics.getMaxRss() orelse 0;
373371
372 // Special handling for CompileStep that is expecting compile errors.
373 if (s.cast(Build.CompileStep)) |compile| switch (term) {
374 .Exited => {
375 // Note that the exit code may be 0 in this case due to the
376 // compiler server protocol.
377 if (compile.expect_errors.len != 0 and s.result_error_bundle.errorMessageCount() > 0) {
378 return error.NeedCompileErrorCheck;
379 }
380 },
381 else => {},
382 };
383
374 try handleChildProcessTerm(s, term, null, argv);384 try handleChildProcessTerm(s, term, null, argv);
375385
376 if (s.result_error_bundle.errorMessageCount() > 0) {386 if (s.result_error_bundle.errorMessageCount() > 0) {
lib/std/zig/ErrorBundle.zig+16-13
...@@ -141,32 +141,35 @@ pub fn nullTerminatedString(eb: ErrorBundle, index: usize) [:0]const u8 {...@@ -141,32 +141,35 @@ pub fn nullTerminatedString(eb: ErrorBundle, index: usize) [:0]const u8 {
141 return string_bytes[index..end :0];141 return string_bytes[index..end :0];
142}142}
143143
144pub fn renderToStdErr(eb: ErrorBundle, ttyconf: std.debug.TTY.Config) void {144pub const RenderOptions = struct {
145 ttyconf: std.debug.TTY.Config,
146 include_reference_trace: bool = true,
147 include_source_line: bool = true,
148};
149
150pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {
145 std.debug.getStderrMutex().lock();151 std.debug.getStderrMutex().lock();
146 defer std.debug.getStderrMutex().unlock();152 defer std.debug.getStderrMutex().unlock();
147 const stderr = std.io.getStdErr();153 const stderr = std.io.getStdErr();
148 return renderToWriter(eb, ttyconf, stderr.writer()) catch return;154 return renderToWriter(eb, options, stderr.writer()) catch return;
149}155}
150156
151pub fn renderToWriter(157pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, writer: anytype) anyerror!void {
152 eb: ErrorBundle,
153 ttyconf: std.debug.TTY.Config,
154 writer: anytype,
155) anyerror!void {
156 for (eb.getMessages()) |err_msg| {158 for (eb.getMessages()) |err_msg| {
157 try renderErrorMessageToWriter(eb, err_msg, ttyconf, writer, "error", .Red, 0);159 try renderErrorMessageToWriter(eb, options, err_msg, writer, "error", .Red, 0);
158 }160 }
159}161}
160162
161fn renderErrorMessageToWriter(163fn renderErrorMessageToWriter(
162 eb: ErrorBundle,164 eb: ErrorBundle,
165 options: RenderOptions,
163 err_msg_index: MessageIndex,166 err_msg_index: MessageIndex,
164 ttyconf: std.debug.TTY.Config,
165 stderr: anytype,167 stderr: anytype,
166 kind: []const u8,168 kind: []const u8,
167 color: std.debug.TTY.Color,169 color: std.debug.TTY.Color,
168 indent: usize,170 indent: usize,
169) anyerror!void {171) anyerror!void {
172 const ttyconf = options.ttyconf;
170 var counting_writer = std.io.countingWriter(stderr);173 var counting_writer = std.io.countingWriter(stderr);
171 const counting_stderr = counting_writer.writer();174 const counting_stderr = counting_writer.writer();
172 const err_msg = eb.getErrorMessage(err_msg_index);175 const err_msg = eb.getErrorMessage(err_msg_index);
...@@ -196,7 +199,7 @@ fn renderErrorMessageToWriter(...@@ -196,7 +199,7 @@ fn renderErrorMessageToWriter(
196 try stderr.print(" ({d} times)\n", .{err_msg.count});199 try stderr.print(" ({d} times)\n", .{err_msg.count});
197 }200 }
198 try ttyconf.setColor(stderr, .Reset);201 try ttyconf.setColor(stderr, .Reset);
199 if (src.data.source_line != 0) {202 if (src.data.source_line != 0 and options.include_source_line) {
200 const line = eb.nullTerminatedString(src.data.source_line);203 const line = eb.nullTerminatedString(src.data.source_line);
201 for (line) |b| switch (b) {204 for (line) |b| switch (b) {
202 '\t' => try stderr.writeByte(' '),205 '\t' => try stderr.writeByte(' '),
...@@ -216,9 +219,9 @@ fn renderErrorMessageToWriter(...@@ -216,9 +219,9 @@ fn renderErrorMessageToWriter(
216 try ttyconf.setColor(stderr, .Reset);219 try ttyconf.setColor(stderr, .Reset);
217 }220 }
218 for (eb.getNotes(err_msg_index)) |note| {221 for (eb.getNotes(err_msg_index)) |note| {
219 try renderErrorMessageToWriter(eb, note, ttyconf, stderr, "note", .Cyan, indent);222 try renderErrorMessageToWriter(eb, options, note, stderr, "note", .Cyan, indent);
220 }223 }
221 if (src.data.reference_trace_len > 0) {224 if (src.data.reference_trace_len > 0 and options.include_reference_trace) {
222 try ttyconf.setColor(stderr, .Reset);225 try ttyconf.setColor(stderr, .Reset);
223 try ttyconf.setColor(stderr, .Dim);226 try ttyconf.setColor(stderr, .Dim);
224 try stderr.print("referenced by:\n", .{});227 try stderr.print("referenced by:\n", .{});
...@@ -266,7 +269,7 @@ fn renderErrorMessageToWriter(...@@ -266,7 +269,7 @@ fn renderErrorMessageToWriter(
266 }269 }
267 try ttyconf.setColor(stderr, .Reset);270 try ttyconf.setColor(stderr, .Reset);
268 for (eb.getNotes(err_msg_index)) |note| {271 for (eb.getNotes(err_msg_index)) |note| {
269 try renderErrorMessageToWriter(eb, note, ttyconf, stderr, "note", .Cyan, indent + 4);272 try renderErrorMessageToWriter(eb, options, note, stderr, "note", .Cyan, indent + 4);
270 }273 }
271 }274 }
272}275}
src/Sema.zig+1-1
...@@ -2220,7 +2220,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2220,7 +2220,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2220 Compilation.addModuleErrorMsg(&wip_errors, err_msg.*) catch unreachable;2220 Compilation.addModuleErrorMsg(&wip_errors, err_msg.*) catch unreachable;
2221 std.debug.print("compile error during Sema:\n", .{});2221 std.debug.print("compile error during Sema:\n", .{});
2222 var error_bundle = wip_errors.toOwnedBundle() catch unreachable;2222 var error_bundle = wip_errors.toOwnedBundle() catch unreachable;
2223 error_bundle.renderToStdErr(.no_color);2223 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });
2224 crash_report.compilerPanic("unexpected compile error occurred", null, null);2224 crash_report.compilerPanic("unexpected compile error occurred", null, null);
2225 }2225 }
22262226
src/main.zig+18-10
...@@ -4082,7 +4082,7 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void...@@ -4082,7 +4082,7 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void
4082 defer errors.deinit(comp.gpa);4082 defer errors.deinit(comp.gpa);
40834083
4084 if (errors.errorMessageCount() > 0) {4084 if (errors.errorMessageCount() > 0) {
4085 errors.renderToStdErr(get_tty_conf(comp.color));4085 errors.renderToStdErr(renderOptions(comp.color));
4086 const log_text = comp.getCompileLogOutput();4086 const log_text = comp.getCompileLogOutput();
4087 if (log_text.len != 0) {4087 if (log_text.len != 0) {
4088 std.debug.print("\nCompile Log Output:\n{s}", .{log_text});4088 std.debug.print("\nCompile Log Output:\n{s}", .{log_text});
...@@ -4711,7 +4711,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -4711,7 +4711,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
4711 if (wip_errors.root_list.items.len > 0) {4711 if (wip_errors.root_list.items.len > 0) {
4712 var errors = try wip_errors.toOwnedBundle();4712 var errors = try wip_errors.toOwnedBundle();
4713 defer errors.deinit(gpa);4713 defer errors.deinit(gpa);
4714 errors.renderToStdErr(get_tty_conf(color));4714 errors.renderToStdErr(renderOptions(color));
4715 process.exit(1);4715 process.exit(1);
4716 }4716 }
4717 try fetch_result;4717 try fetch_result;
...@@ -4974,7 +4974,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void...@@ -4974,7 +4974,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void
4974 try Compilation.addZirErrorMessages(&wip_errors, &file);4974 try Compilation.addZirErrorMessages(&wip_errors, &file);
4975 var error_bundle = try wip_errors.toOwnedBundle();4975 var error_bundle = try wip_errors.toOwnedBundle();
4976 defer error_bundle.deinit(gpa);4976 defer error_bundle.deinit(gpa);
4977 error_bundle.renderToStdErr(get_tty_conf(color));4977 error_bundle.renderToStdErr(renderOptions(color));
4978 process.exit(2);4978 process.exit(2);
4979 }4979 }
4980 } else if (tree.errors.len != 0) {4980 } else if (tree.errors.len != 0) {
...@@ -5180,7 +5180,7 @@ fn fmtPathFile(...@@ -5180,7 +5180,7 @@ fn fmtPathFile(
5180 try Compilation.addZirErrorMessages(&wip_errors, &file);5180 try Compilation.addZirErrorMessages(&wip_errors, &file);
5181 var error_bundle = try wip_errors.toOwnedBundle();5181 var error_bundle = try wip_errors.toOwnedBundle();
5182 defer error_bundle.deinit(gpa);5182 defer error_bundle.deinit(gpa);
5183 error_bundle.renderToStdErr(get_tty_conf(fmt.color));5183 error_bundle.renderToStdErr(renderOptions(fmt.color));
5184 fmt.any_error = true;5184 fmt.any_error = true;
5185 }5185 }
5186 }5186 }
...@@ -5217,7 +5217,7 @@ fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Co...@@ -5217,7 +5217,7 @@ fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Co
52175217
5218 var error_bundle = try wip_errors.toOwnedBundle();5218 var error_bundle = try wip_errors.toOwnedBundle();
5219 defer error_bundle.deinit(gpa);5219 defer error_bundle.deinit(gpa);
5220 error_bundle.renderToStdErr(get_tty_conf(color));5220 error_bundle.renderToStdErr(renderOptions(color));
5221}5221}
52225222
5223pub fn putAstErrorsIntoBundle(5223pub fn putAstErrorsIntoBundle(
...@@ -5834,7 +5834,7 @@ pub fn cmdAstCheck(...@@ -5834,7 +5834,7 @@ pub fn cmdAstCheck(
5834 try Compilation.addZirErrorMessages(&wip_errors, &file);5834 try Compilation.addZirErrorMessages(&wip_errors, &file);
5835 var error_bundle = try wip_errors.toOwnedBundle();5835 var error_bundle = try wip_errors.toOwnedBundle();
5836 defer error_bundle.deinit(gpa);5836 defer error_bundle.deinit(gpa);
5837 error_bundle.renderToStdErr(get_tty_conf(color));5837 error_bundle.renderToStdErr(renderOptions(color));
5838 process.exit(1);5838 process.exit(1);
5839 }5839 }
58405840
...@@ -5892,6 +5892,7 @@ pub fn cmdChangelist(...@@ -5892,6 +5892,7 @@ pub fn cmdChangelist(
5892 arena: Allocator,5892 arena: Allocator,
5893 args: []const []const u8,5893 args: []const []const u8,
5894) !void {5894) !void {
5895 const color: Color = .auto;
5895 const Zir = @import("Zir.zig");5896 const Zir = @import("Zir.zig");
58965897
5897 const old_source_file = args[0];5898 const old_source_file = args[0];
...@@ -5948,10 +5949,9 @@ pub fn cmdChangelist(...@@ -5948,10 +5949,9 @@ pub fn cmdChangelist(
5948 try wip_errors.init(gpa);5949 try wip_errors.init(gpa);
5949 defer wip_errors.deinit();5950 defer wip_errors.deinit();
5950 try Compilation.addZirErrorMessages(&wip_errors, &file);5951 try Compilation.addZirErrorMessages(&wip_errors, &file);
5951 const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr());
5952 var error_bundle = try wip_errors.toOwnedBundle();5952 var error_bundle = try wip_errors.toOwnedBundle();
5953 defer error_bundle.deinit(gpa);5953 defer error_bundle.deinit(gpa);
5954 error_bundle.renderToStdErr(ttyconf);5954 error_bundle.renderToStdErr(renderOptions(color));
5955 process.exit(1);5955 process.exit(1);
5956 }5956 }
59575957
...@@ -5984,10 +5984,9 @@ pub fn cmdChangelist(...@@ -5984,10 +5984,9 @@ pub fn cmdChangelist(
5984 try wip_errors.init(gpa);5984 try wip_errors.init(gpa);
5985 defer wip_errors.deinit();5985 defer wip_errors.deinit();
5986 try Compilation.addZirErrorMessages(&wip_errors, &file);5986 try Compilation.addZirErrorMessages(&wip_errors, &file);
5987 const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr());
5988 var error_bundle = try wip_errors.toOwnedBundle();5987 var error_bundle = try wip_errors.toOwnedBundle();
5989 defer error_bundle.deinit(gpa);5988 defer error_bundle.deinit(gpa);
5990 error_bundle.renderToStdErr(ttyconf);5989 error_bundle.renderToStdErr(renderOptions(color));
5991 process.exit(1);5990 process.exit(1);
5992 }5991 }
59935992
...@@ -6256,3 +6255,12 @@ fn get_tty_conf(color: Color) std.debug.TTY.Config {...@@ -6256,3 +6255,12 @@ fn get_tty_conf(color: Color) std.debug.TTY.Config {
6256 .off => .no_color,6255 .off => .no_color,
6257 };6256 };
6258}6257}
6258
6259fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions {
6260 const ttyconf = get_tty_conf(color);
6261 return .{
6262 .ttyconf = ttyconf,
6263 .include_source_line = ttyconf != .no_color,
6264 .include_reference_trace = ttyconf != .no_color,
6265 };
6266}