| ... | @@ -90,7 +90,7 @@ pub fn main() !void { | ... | @@ -90,7 +90,7 @@ pub fn main() !void { |
| 90 | | 90 | |
| 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; |
| 96 | | 96 | |
| ... | @@ -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), |
| 303 | | 308 | |
| 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), |
| 333 | | 338 | |
| 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( |
| 469 | | 474 | |
| 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(); |
| 473 | | 478 | |
| 474 | const ttyconf = run.ttyconf; | 479 | const ttyconf = run.ttyconf; |
| 475 | const stderr = run.stderr; | 480 | const stderr = run.stderr; |
| 476 | | 481 | |
| 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 {}; |
| 490 | | 495 | |
| 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; |
| 497 | | 503 | |
| 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); |
| 562 | | 578 | |
| 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 | } |
| 690 | | 706 | |
| | 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 steps | 972 | \\ -l, --list-steps Print available steps |
| 949 | \\ --verbose Print commands before executing them | 973 | \\ --verbose Print commands before executing them |
| 950 | \\ --color [auto|off|on] Enable or disable colored error messages | 974 | \\ --color [auto|off|on] Enable or disable colored error messages |
| 951 | \\ -fsummary Print the build summary, even on success | 975 | \\ --summary [mode] Control the printing of the build summary |
| 952 | \\ -fno-summary Omit the build summary, even on failure | 976 | \\ 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 | } |
| 1026 | | 1052 | |
| 1027 | const Color = enum { auto, off, on }; | 1053 | const Color = enum { auto, off, on }; |
| | 1054 | const Summary = enum { all, failures, none }; |
| 1028 | | 1055 | |
| 1029 | fn get_tty_conf(color: Color, stderr: std.fs.File) std.io.tty.Config { | 1056 | fn get_tty_conf(color: Color, stderr: std.fs.File) std.io.tty.Config { |
| 1030 | return switch (color) { | 1057 | return switch (color) { |