authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-06-09 19:15:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-16 15:17:59-07:00
log0f5aff34414bcb024443540fe905039f3783803a
treebbdb0dd69fd60c68703ac313c26e2f4ed00da5d3
parent537104fd9d84d94abad3e36d3cd781be4397e299

zig build: add option to only print failed steps

The motivating case for this is that currently when a test fails the CI log will include ~5k lines of listing steps that succeeded.

2 files changed, 67 insertions(+), 38 deletions(-)

lib/build_runner.zig+45-18
...@@ -90,7 +90,7 @@ pub fn main() !void {...@@ -90,7 +90,7 @@ pub fn main() !void {
9090
91 var install_prefix: ?[]const u8 = null;91 var install_prefix: ?[]const u8 = null;
92 var dir_list = std.Build.DirList{};92 var dir_list = std.Build.DirList{};
93 var enable_summary: ?bool = null;93 var summary: ?Summary = null;
94 var max_rss: usize = 0;94 var max_rss: usize = 0;
95 var color: Color = .auto;95 var color: Color = .auto;
9696
...@@ -178,6 +178,15 @@ pub fn main() !void {...@@ -178,6 +178,15 @@ pub fn main() !void {
178 std.debug.print("Expected [auto|on|off] after {s}, found '{s}'\n\n", .{ arg, next_arg });178 std.debug.print("Expected [auto|on|off] after {s}, found '{s}'\n\n", .{ arg, next_arg });
179 usageAndErr(builder, false, stderr_stream);179 usageAndErr(builder, false, stderr_stream);
180 };180 };
181 } else if (mem.eql(u8, arg, "--summary")) {
182 const next_arg = nextArg(args, &arg_idx) orelse {
183 std.debug.print("Expected [all|failures|none] after {s}\n\n", .{arg});
184 usageAndErr(builder, false, stderr_stream);
185 };
186 summary = std.meta.stringToEnum(Summary, next_arg) orelse {
187 std.debug.print("Expected [all|failures|none] after {s}, found '{s}'\n\n", .{ arg, next_arg });
188 usageAndErr(builder, false, stderr_stream);
189 };
181 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {190 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
182 builder.zig_lib_dir = nextArg(args, &arg_idx) orelse {191 builder.zig_lib_dir = nextArg(args, &arg_idx) orelse {
183 std.debug.print("Expected argument after {s}\n\n", .{arg});192 std.debug.print("Expected argument after {s}\n\n", .{arg});
...@@ -234,10 +243,6 @@ pub fn main() !void {...@@ -234,10 +243,6 @@ pub fn main() !void {
234 builder.enable_darling = true;243 builder.enable_darling = true;
235 } else if (mem.eql(u8, arg, "-fno-darling")) {244 } else if (mem.eql(u8, arg, "-fno-darling")) {
236 builder.enable_darling = false;245 builder.enable_darling = false;
237 } else if (mem.eql(u8, arg, "-fsummary")) {
238 enable_summary = true;
239 } else if (mem.eql(u8, arg, "-fno-summary")) {
240 enable_summary = false;
241 } else if (mem.eql(u8, arg, "-freference-trace")) {246 } else if (mem.eql(u8, arg, "-freference-trace")) {
242 builder.reference_trace = 256;247 builder.reference_trace = 256;
243 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {248 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
...@@ -302,7 +307,7 @@ pub fn main() !void {...@@ -302,7 +307,7 @@ pub fn main() !void {
302 .memory_blocked_steps = std.ArrayList(*Step).init(arena),307 .memory_blocked_steps = std.ArrayList(*Step).init(arena),
303308
304 .claimed_rss = 0,309 .claimed_rss = 0,
305 .enable_summary = enable_summary,310 .summary = summary,
306 .ttyconf = ttyconf,311 .ttyconf = ttyconf,
307 .stderr = stderr,312 .stderr = stderr,
308 };313 };
...@@ -332,7 +337,7 @@ const Run = struct {...@@ -332,7 +337,7 @@ const Run = struct {
332 memory_blocked_steps: std.ArrayList(*Step),337 memory_blocked_steps: std.ArrayList(*Step),
333338
334 claimed_rss: usize,339 claimed_rss: usize,
335 enable_summary: ?bool,340 summary: ?Summary,
336 ttyconf: std.io.tty.Config,341 ttyconf: std.io.tty.Config,
337 stderr: std.fs.File,342 stderr: std.fs.File,
338};343};
...@@ -469,12 +474,12 @@ fn runStepNames(...@@ -469,12 +474,12 @@ fn runStepNames(
469474
470 // A proper command line application defaults to silently succeeding.475 // A proper command line application defaults to silently succeeding.
471 // The user may request verbose mode if they have a different preference.476 // The user may request verbose mode if they have a different preference.
472 if (failure_count == 0 and run.enable_summary != true) return cleanExit();477 if (failure_count == 0 and run.summary != Summary.all) return cleanExit();
473478
474 const ttyconf = run.ttyconf;479 const ttyconf = run.ttyconf;
475 const stderr = run.stderr;480 const stderr = run.stderr;
476481
477 if (run.enable_summary != false) {482 if (run.summary != Summary.none) {
478 const total_count = success_count + failure_count + pending_count + skipped_count;483 const total_count = success_count + failure_count + pending_count + skipped_count;
479 ttyconf.setColor(stderr, .cyan) catch {};484 ttyconf.setColor(stderr, .cyan) catch {};
480 stderr.writeAll("Build Summary:") catch {};485 stderr.writeAll("Build Summary:") catch {};
...@@ -488,23 +493,32 @@ fn runStepNames(...@@ -488,23 +493,32 @@ fn runStepNames(
488 if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {};493 if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {};
489 if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {};494 if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {};
490495
491 if (run.enable_summary == null) {496 if (run.summary == null) {
492 ttyconf.setColor(stderr, .dim) catch {};497 ttyconf.setColor(stderr, .dim) catch {};
493 stderr.writeAll(" (disable with -fno-summary)") catch {};498 stderr.writeAll(" (disable with --summary none)") catch {};
494 ttyconf.setColor(stderr, .reset) catch {};499 ttyconf.setColor(stderr, .reset) catch {};
495 }500 }
496 stderr.writeAll("\n") catch {};501 stderr.writeAll("\n") catch {};
502 const failures_only = run.summary != Summary.all;
497503
498 // Print a fancy tree with build results.504 // Print a fancy tree with build results.
499 var print_node: PrintNode = .{ .parent = null };505 var print_node: PrintNode = .{ .parent = null };
500 if (step_names.len == 0) {506 if (step_names.len == 0) {
501 print_node.last = true;507 print_node.last = true;
502 printTreeStep(b, b.default_step, stderr, ttyconf, &print_node, &step_stack) catch {};508 printTreeStep(b, b.default_step, stderr, ttyconf, &print_node, &step_stack, failures_only) catch {};
503 } else {509 } else {
510 const last_index = if (!failures_only) b.top_level_steps.count() else blk: {
511 var i: usize = step_names.len;
512 while (i > 0) {
513 i -= 1;
514 if (b.top_level_steps.get(step_names[i]).?.step.state != .success) break :blk i;
515 }
516 break :blk b.top_level_steps.count();
517 };
504 for (step_names, 0..) |step_name, i| {518 for (step_names, 0..) |step_name, i| {
505 const tls = b.top_level_steps.get(step_name).?;519 const tls = b.top_level_steps.get(step_name).?;
506 print_node.last = i + 1 == b.top_level_steps.count();520 print_node.last = i + 1 == last_index;
507 printTreeStep(b, &tls.step, stderr, ttyconf, &print_node, &step_stack) catch {};521 printTreeStep(b, &tls.step, stderr, ttyconf, &print_node, &step_stack, failures_only) catch {};
508 }522 }
509 }523 }
510 }524 }
...@@ -556,8 +570,10 @@ fn printTreeStep(...@@ -556,8 +570,10 @@ fn printTreeStep(
556 ttyconf: std.io.tty.Config,570 ttyconf: std.io.tty.Config,
557 parent_node: *PrintNode,571 parent_node: *PrintNode,
558 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),572 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),
573 failures_only: bool,
559) !void {574) !void {
560 const first = step_stack.swapRemove(s);575 const first = step_stack.swapRemove(s);
576 if (failures_only and s.state == .success) return;
561 try printPrefix(parent_node, stderr, ttyconf);577 try printPrefix(parent_node, stderr, ttyconf);
562578
563 if (!first) try ttyconf.setColor(stderr, .dim);579 if (!first) try ttyconf.setColor(stderr, .dim);
...@@ -688,12 +704,20 @@ fn printTreeStep(...@@ -688,12 +704,20 @@ fn printTreeStep(
688 },704 },
689 }705 }
690706
707 const last_index = if (!failures_only) s.dependencies.items.len -| 1 else blk: {
708 var i: usize = s.dependencies.items.len;
709 while (i > 0) {
710 i -= 1;
711 if (s.dependencies.items[i].state != .success) break :blk i;
712 }
713 break :blk s.dependencies.items.len -| 1;
714 };
691 for (s.dependencies.items, 0..) |dep, i| {715 for (s.dependencies.items, 0..) |dep, i| {
692 var print_node: PrintNode = .{716 var print_node: PrintNode = .{
693 .parent = parent_node,717 .parent = parent_node,
694 .last = i == s.dependencies.items.len - 1,718 .last = i == last_index,
695 };719 };
696 try printTreeStep(b, dep, stderr, ttyconf, &print_node, step_stack);720 try printTreeStep(b, dep, stderr, ttyconf, &print_node, step_stack, failures_only);
697 }721 }
698 } else {722 } else {
699 if (s.dependencies.items.len == 0) {723 if (s.dependencies.items.len == 0) {
...@@ -948,8 +972,10 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi...@@ -948,8 +972,10 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
948 \\ -l, --list-steps Print available steps972 \\ -l, --list-steps Print available steps
949 \\ --verbose Print commands before executing them973 \\ --verbose Print commands before executing them
950 \\ --color [auto|off|on] Enable or disable colored error messages974 \\ --color [auto|off|on] Enable or disable colored error messages
951 \\ -fsummary Print the build summary, even on success975 \\ --summary [mode] Control the printing of the build summary
952 \\ -fno-summary Omit the build summary, even on failure976 \\ all Print the build summary in its entirety
977 \\ failures (Default) Only print failed steps
978 \\ none Do not print the build summary
953 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)979 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
954 \\ --maxrss <bytes> Limit memory usage (default is to use available memory)980 \\ --maxrss <bytes> Limit memory usage (default is to use available memory)
955 \\981 \\
...@@ -1025,6 +1051,7 @@ fn cleanExit() void {...@@ -1025,6 +1051,7 @@ fn cleanExit() void {
1025}1051}
10261052
1027const Color = enum { auto, off, on };1053const Color = enum { auto, off, on };
1054const Summary = enum { all, failures, none };
10281055
1029fn get_tty_conf(color: Color, stderr: std.fs.File) std.io.tty.Config {1056fn get_tty_conf(color: Color, stderr: std.fs.File) std.io.tty.Config {
1030 return switch (color) {1057 return switch (color) {
src/main.zig+22-20
...@@ -4000,8 +4000,8 @@ pub const usage_libc =...@@ -4000,8 +4000,8 @@ pub const usage_libc =
4000 \\ Parse a libc installation text file and validate it.4000 \\ Parse a libc installation text file and validate it.
4001 \\4001 \\
4002 \\Options:4002 \\Options:
4003 \\ -h, --help Print this help and exit4003 \\ -h, --help Print this help and exit
4004 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command4004 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
4005 \\4005 \\
4006;4006;
40074007
...@@ -4068,7 +4068,7 @@ pub const usage_init =...@@ -4068,7 +4068,7 @@ pub const usage_init =
4068 \\ directory.4068 \\ directory.
4069 \\4069 \\
4070 \\Options:4070 \\Options:
4071 \\ -h, --help Print this help and exit4071 \\ -h, --help Print this help and exit
4072 \\4072 \\
4073 \\4073 \\
4074;4074;
...@@ -4166,16 +4166,18 @@ pub const usage_build =...@@ -4166,16 +4166,18 @@ pub const usage_build =
4166 \\ Build a project from build.zig.4166 \\ Build a project from build.zig.
4167 \\4167 \\
4168 \\Options:4168 \\Options:
4169 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error4169 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
4170 \\ -fno-reference-trace Disable reference trace4170 \\ -fno-reference-trace Disable reference trace
4171 \\ -fsummary Print the build summary, even on success4171 \\ --summary [mode] Control the printing of the build summary
4172 \\ -fno-summary Omit the build summary, even on failure4172 \\ all Print the build summary in its entirety
4173 \\ --build-file [file] Override path to build.zig4173 \\ failures (Default) Only print failed steps
4174 \\ --cache-dir [path] Override path to local Zig cache directory4174 \\ none Do not print the build summary
4175 \\ --global-cache-dir [path] Override path to global Zig cache directory4175 \\ --build-file [file] Override path to build.zig
4176 \\ --zig-lib-dir [arg] Override path to Zig lib directory4176 \\ --cache-dir [path] Override path to local Zig cache directory
4177 \\ --build-runner [file] Override path to build runner4177 \\ --global-cache-dir [path] Override path to global Zig cache directory
4178 \\ -h, --help Print this help and exit4178 \\ --zig-lib-dir [arg] Override path to Zig lib directory
4179 \\ --build-runner [file] Override path to build runner
4180 \\ -h, --help Print this help and exit
4179 \\4181 \\
4180;4182;
41814183
...@@ -4576,13 +4578,13 @@ pub const usage_fmt =...@@ -4576,13 +4578,13 @@ pub const usage_fmt =
4576 \\ recursively.4578 \\ recursively.
4577 \\4579 \\
4578 \\Options:4580 \\Options:
4579 \\ -h, --help Print this help and exit4581 \\ -h, --help Print this help and exit
4580 \\ --color [auto|off|on] Enable or disable colored error messages4582 \\ --color [auto|off|on] Enable or disable colored error messages
4581 \\ --stdin Format code from stdin; output to stdout4583 \\ --stdin Format code from stdin; output to stdout
4582 \\ --check List non-conforming files and exit with an error4584 \\ --check List non-conforming files and exit with an error
4583 \\ if the list is non-empty4585 \\ if the list is non-empty
4584 \\ --ast-check Run zig ast-check on every file4586 \\ --ast-check Run zig ast-check on every file
4585 \\ --exclude [file] Exclude file or directory from formatting4587 \\ --exclude [file] Exclude file or directory from formatting
4586 \\4588 \\
4587 \\4589 \\
4588;4590;