| ... | ... | @@ -103,12 +103,13 @@ pub fn main() !void { |
| 103 | 103 | |
| 104 | 104 | var install_prefix: ?[]const u8 = null; |
| 105 | 105 | var dir_list = std.Build.DirList{}; |
| 106 | var error_style: ErrorStyle = .verbose; |
| 107 | var multiline_errors: MultilineErrors = .indent; |
| 106 | 108 | var summary: ?Summary = null; |
| 107 | 109 | var max_rss: u64 = 0; |
| 108 | 110 | var skip_oom_steps = false; |
| 109 | 111 | var test_timeout_ms: ?u64 = null; |
| 110 | 112 | var color: Color = .auto; |
| 111 | | var prominent_compile_errors = false; |
| 112 | 113 | var help_menu = false; |
| 113 | 114 | var steps_menu = false; |
| 114 | 115 | var output_tmp_nonce: ?[16]u8 = null; |
| ... | ... | @@ -117,6 +118,18 @@ pub fn main() !void { |
| 117 | 118 | var debounce_interval_ms: u16 = 50; |
| 118 | 119 | var webui_listen: ?std.net.Address = null; |
| 119 | 120 | |
| 121 | if (try std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(arena)) |str| { |
| 122 | if (std.meta.stringToEnum(ErrorStyle, str)) |style| { |
| 123 | error_style = style; |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | if (try std.zig.EnvVar.ZIG_BUILD_MULTILINE_ERRORS.get(arena)) |str| { |
| 128 | if (std.meta.stringToEnum(MultilineErrors, str)) |style| { |
| 129 | multiline_errors = style; |
| 130 | } |
| 131 | } |
| 132 | |
| 120 | 133 | while (nextArg(args, &arg_idx)) |arg| { |
| 121 | 134 | if (mem.startsWith(u8, arg, "-Z")) { |
| 122 | 135 | if (arg.len != 18) fatalWithHint("bad argument: '{s}'", .{arg}); |
| ... | ... | @@ -197,11 +210,23 @@ pub fn main() !void { |
| 197 | 210 | arg, next_arg, |
| 198 | 211 | }); |
| 199 | 212 | }; |
| 213 | } else if (mem.eql(u8, arg, "--error-style")) { |
| 214 | const next_arg = nextArg(args, &arg_idx) orelse |
| 215 | fatalWithHint("expected style after '{s}'", .{arg}); |
| 216 | error_style = std.meta.stringToEnum(ErrorStyle, next_arg) orelse { |
| 217 | fatalWithHint("expected style after '{s}', found '{s}'", .{ arg, next_arg }); |
| 218 | }; |
| 219 | } else if (mem.eql(u8, arg, "--multiline-errors")) { |
| 220 | const next_arg = nextArg(args, &arg_idx) orelse |
| 221 | fatalWithHint("expected style after '{s}'", .{arg}); |
| 222 | multiline_errors = std.meta.stringToEnum(MultilineErrors, next_arg) orelse { |
| 223 | fatalWithHint("expected style after '{s}', found '{s}'", .{ arg, next_arg }); |
| 224 | }; |
| 200 | 225 | } else if (mem.eql(u8, arg, "--summary")) { |
| 201 | 226 | const next_arg = nextArg(args, &arg_idx) orelse |
| 202 | | fatalWithHint("expected [all|new|failures|none] after '{s}'", .{arg}); |
| 227 | fatalWithHint("expected [all|new|failures|line|none] after '{s}'", .{arg}); |
| 203 | 228 | summary = std.meta.stringToEnum(Summary, next_arg) orelse { |
| 204 | | fatalWithHint("expected [all|new|failures|none] after '{s}', found '{s}'", .{ |
| 229 | fatalWithHint("expected [all|new|failures|line|none] after '{s}', found '{s}'", .{ |
| 205 | 230 | arg, next_arg, |
| 206 | 231 | }); |
| 207 | 232 | }; |
| ... | ... | @@ -273,8 +298,6 @@ pub fn main() !void { |
| 273 | 298 | builder.verbose_cc = true; |
| 274 | 299 | } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { |
| 275 | 300 | builder.verbose_llvm_cpu_features = true; |
| 276 | | } else if (mem.eql(u8, arg, "--prominent-compile-errors")) { |
| 277 | | prominent_compile_errors = true; |
| 278 | 301 | } else if (mem.eql(u8, arg, "--watch")) { |
| 279 | 302 | watch = true; |
| 280 | 303 | } else if (mem.eql(u8, arg, "--time-report")) { |
| ... | ... | @@ -466,10 +489,11 @@ pub fn main() !void { |
| 466 | 489 | .web_server = undefined, // set after `prepare` |
| 467 | 490 | .memory_blocked_steps = .empty, |
| 468 | 491 | .step_stack = .empty, |
| 469 | | .prominent_compile_errors = prominent_compile_errors, |
| 470 | 492 | |
| 471 | 493 | .claimed_rss = 0, |
| 472 | | .summary = summary orelse if (watch) .new else .failures, |
| 494 | .error_style = error_style, |
| 495 | .multiline_errors = multiline_errors, |
| 496 | .summary = summary orelse if (watch or webui_listen != null) .line else .failures, |
| 473 | 497 | .ttyconf = ttyconf, |
| 474 | 498 | .stderr = stderr, |
| 475 | 499 | .thread_pool = undefined, |
| ... | ... | @@ -485,8 +509,14 @@ pub fn main() !void { |
| 485 | 509 | } |
| 486 | 510 | |
| 487 | 511 | prepare(arena, builder, targets.items, &run, graph.random_seed) catch |err| switch (err) { |
| 488 | | error.UncleanExit => process.exit(1), |
| 489 | | else => return err, |
| 512 | error.DependencyLoopDetected => { |
| 513 | // Perhaps in the future there could be an Advanced Options flag such as |
| 514 | // --debug-build-runner-leaks which would make this code return instead of |
| 515 | // calling exit. |
| 516 | std.debug.lockStdErr(); |
| 517 | process.exit(1); |
| 518 | }, |
| 519 | else => |e| return e, |
| 490 | 520 | }; |
| 491 | 521 | |
| 492 | 522 | var w: Watch = w: { |
| ... | ... | @@ -516,22 +546,20 @@ pub fn main() !void { |
| 516 | 546 | ws.start() catch |err| fatal("failed to start web server: {s}", .{@errorName(err)}); |
| 517 | 547 | } |
| 518 | 548 | |
| 519 | | rebuild: while (true) { |
| 549 | rebuild: while (true) : (if (run.error_style.clearOnUpdate()) { |
| 550 | const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation); |
| 551 | defer std.debug.unlockStderrWriter(); |
| 552 | try bw.writeAll("\x1B[2J\x1B[3J\x1B[H"); |
| 553 | }) { |
| 520 | 554 | if (run.web_server) |*ws| ws.startBuild(); |
| 521 | 555 | |
| 522 | | runStepNames( |
| 556 | try runStepNames( |
| 523 | 557 | builder, |
| 524 | 558 | targets.items, |
| 525 | 559 | main_progress_node, |
| 526 | 560 | &run, |
| 527 | 561 | fuzz, |
| 528 | | ) catch |err| switch (err) { |
| 529 | | error.UncleanExit => { |
| 530 | | assert(!run.watch and run.web_server == null); |
| 531 | | process.exit(1); |
| 532 | | }, |
| 533 | | else => return err, |
| 534 | | }; |
| 562 | ); |
| 535 | 563 | |
| 536 | 564 | if (run.web_server) |*web_server| { |
| 537 | 565 | if (fuzz) |mode| if (mode != .forever) fatal( |
| ... | ... | @@ -542,10 +570,6 @@ pub fn main() !void { |
| 542 | 570 | web_server.finishBuild(.{ .fuzz = fuzz != null }); |
| 543 | 571 | } |
| 544 | 572 | |
| 545 | | if (!watch and run.web_server == null) { |
| 546 | | return cleanExit(); |
| 547 | | } |
| 548 | | |
| 549 | 573 | if (run.web_server) |*ws| { |
| 550 | 574 | assert(!watch); // fatal error after CLI parsing |
| 551 | 575 | while (true) switch (ws.wait()) { |
| ... | ... | @@ -626,18 +650,14 @@ const Run = struct { |
| 626 | 650 | memory_blocked_steps: std.ArrayListUnmanaged(*Step), |
| 627 | 651 | /// Allocated into `gpa`. |
| 628 | 652 | step_stack: std.AutoArrayHashMapUnmanaged(*Step, void), |
| 629 | | prominent_compile_errors: bool, |
| 630 | 653 | thread_pool: std.Thread.Pool, |
| 631 | 654 | |
| 632 | 655 | claimed_rss: usize, |
| 656 | error_style: ErrorStyle, |
| 657 | multiline_errors: MultilineErrors, |
| 633 | 658 | summary: Summary, |
| 634 | 659 | ttyconf: tty.Config, |
| 635 | 660 | stderr: File, |
| 636 | | |
| 637 | | fn cleanExit(run: Run) void { |
| 638 | | if (run.watch or run.web_server != null) return; |
| 639 | | return runner.cleanExit(); |
| 640 | | } |
| 641 | 661 | }; |
| 642 | 662 | |
| 643 | 663 | fn prepare( |
| ... | ... | @@ -671,10 +691,7 @@ fn prepare( |
| 671 | 691 | rand.shuffle(*Step, starting_steps); |
| 672 | 692 | |
| 673 | 693 | for (starting_steps) |s| { |
| 674 | | constructGraphAndCheckForDependencyLoop(gpa, b, s, &run.step_stack, rand) catch |err| switch (err) { |
| 675 | | error.DependencyLoopDetected => return uncleanExit(), |
| 676 | | else => |e| return e, |
| 677 | | }; |
| 694 | try constructGraphAndCheckForDependencyLoop(gpa, b, s, &run.step_stack, rand); |
| 678 | 695 | } |
| 679 | 696 | |
| 680 | 697 | { |
| ... | ... | @@ -827,26 +844,25 @@ fn runStepNames( |
| 827 | 844 | // Every test has a state |
| 828 | 845 | assert(test_pass_count + test_skip_count + test_fail_count + test_crash_count + test_timeout_count == test_count); |
| 829 | 846 | |
| 830 | | // A proper command line application defaults to silently succeeding. |
| 831 | | // The user may request verbose mode if they have a different preference. |
| 832 | | const failures_only = switch (run.summary) { |
| 833 | | .failures, .none => true, |
| 834 | | else => false, |
| 835 | | }; |
| 836 | 847 | if (failure_count == 0) { |
| 837 | 848 | std.Progress.setStatus(.success); |
| 838 | | if (failures_only) return run.cleanExit(); |
| 839 | 849 | } else { |
| 840 | 850 | std.Progress.setStatus(.failure); |
| 841 | 851 | } |
| 842 | 852 | |
| 843 | | if (run.summary != .none) { |
| 853 | summary: { |
| 854 | switch (run.summary) { |
| 855 | .all, .new, .line => {}, |
| 856 | .failures => if (failure_count == 0) break :summary, |
| 857 | .none => break :summary, |
| 858 | } |
| 859 | |
| 844 | 860 | const w = std.debug.lockStderrWriter(&stdio_buffer_allocation); |
| 845 | 861 | defer std.debug.unlockStderrWriter(); |
| 846 | 862 | |
| 847 | 863 | const total_count = success_count + failure_count + pending_count + skipped_count; |
| 848 | 864 | ttyconf.setColor(w, .cyan) catch {}; |
| 849 | | w.writeAll("\nBuild Summary:") catch {}; |
| 865 | w.writeAll("Build Summary:") catch {}; |
| 850 | 866 | ttyconf.setColor(w, .reset) catch {}; |
| 851 | 867 | w.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; |
| 852 | 868 | if (skipped_count > 0) w.print(", {d} skipped", .{skipped_count}) catch {}; |
| ... | ... | @@ -862,6 +878,8 @@ fn runStepNames( |
| 862 | 878 | |
| 863 | 879 | w.writeAll("\n") catch {}; |
| 864 | 880 | |
| 881 | if (run.summary == .line) break :summary; |
| 882 | |
| 865 | 883 | // Print a fancy tree with build results. |
| 866 | 884 | var step_stack_copy = try step_stack.clone(gpa); |
| 867 | 885 | defer step_stack_copy.deinit(gpa); |
| ... | ... | @@ -877,7 +895,7 @@ fn runStepNames( |
| 877 | 895 | i -= 1; |
| 878 | 896 | const step = b.top_level_steps.get(step_names[i]).?.step; |
| 879 | 897 | const found = switch (run.summary) { |
| 880 | | .all, .none => unreachable, |
| 898 | .all, .line, .none => unreachable, |
| 881 | 899 | .failures => step.state != .success, |
| 882 | 900 | .new => !step.result_cached, |
| 883 | 901 | }; |
| ... | ... | @@ -894,28 +912,19 @@ fn runStepNames( |
| 894 | 912 | w.writeByte('\n') catch {}; |
| 895 | 913 | } |
| 896 | 914 | |
| 897 | | if (failure_count == 0) { |
| 898 | | return run.cleanExit(); |
| 899 | | } |
| 900 | | |
| 901 | | // Finally, render compile errors at the bottom of the terminal. |
| 902 | | if (run.prominent_compile_errors and total_compile_errors > 0) { |
| 903 | | for (step_stack.keys()) |s| { |
| 904 | | if (s.result_error_bundle.errorMessageCount() > 0) { |
| 905 | | s.result_error_bundle.renderToStdErr(.{ .ttyconf = ttyconf }); |
| 906 | | } |
| 907 | | } |
| 915 | if (run.watch or run.web_server != null) return; |
| 908 | 916 | |
| 909 | | if (!run.watch and run.web_server == null) { |
| 910 | | // Signal to parent process that we have printed compile errors. The |
| 911 | | // parent process may choose to omit the "following command failed" |
| 912 | | // line in this case. |
| 913 | | std.debug.lockStdErr(); |
| 914 | | process.exit(2); |
| 915 | | } |
| 916 | | } |
| 917 | // Perhaps in the future there could be an Advanced Options flag such as |
| 918 | // --debug-build-runner-leaks which would make this code return instead of |
| 919 | // calling exit. |
| 917 | 920 | |
| 918 | | if (!run.watch and run.web_server == null) return uncleanExit(); |
| 921 | const code: u8 = code: { |
| 922 | if (failure_count == 0) break :code 0; // success |
| 923 | if (run.error_style.verboseContext()) break :code 1; // failure; print build command |
| 924 | break :code 2; // failure; do not print build command |
| 925 | }; |
| 926 | std.debug.lockStdErr(); |
| 927 | process.exit(code); |
| 919 | 928 | } |
| 920 | 929 | |
| 921 | 930 | const PrintNode = struct { |
| ... | ... | @@ -1124,7 +1133,7 @@ fn printTreeStep( |
| 1124 | 1133 | const first = step_stack.swapRemove(s); |
| 1125 | 1134 | const summary = run.summary; |
| 1126 | 1135 | const skip = switch (summary) { |
| 1127 | | .none => unreachable, |
| 1136 | .none, .line => unreachable, |
| 1128 | 1137 | .all => false, |
| 1129 | 1138 | .new => s.result_cached, |
| 1130 | 1139 | .failures => s.state == .success, |
| ... | ... | @@ -1157,7 +1166,7 @@ fn printTreeStep( |
| 1157 | 1166 | |
| 1158 | 1167 | const step = s.dependencies.items[i]; |
| 1159 | 1168 | const found = switch (summary) { |
| 1160 | | .all, .none => unreachable, |
| 1169 | .all, .line, .none => unreachable, |
| 1161 | 1170 | .failures => step.state != .success, |
| 1162 | 1171 | .new => !step.result_cached, |
| 1163 | 1172 | }; |
| ... | ... | @@ -1316,15 +1325,13 @@ fn workerMakeOneStep( |
| 1316 | 1325 | }); |
| 1317 | 1326 | |
| 1318 | 1327 | // No matter the result, we want to display error/warning messages. |
| 1319 | | const show_compile_errors = !run.prominent_compile_errors and |
| 1320 | | s.result_error_bundle.errorMessageCount() > 0; |
| 1328 | const show_compile_errors = s.result_error_bundle.errorMessageCount() > 0; |
| 1321 | 1329 | const show_error_msgs = s.result_error_msgs.items.len > 0; |
| 1322 | 1330 | const show_stderr = s.result_stderr.len > 0; |
| 1323 | | |
| 1324 | 1331 | if (show_error_msgs or show_compile_errors or show_stderr) { |
| 1325 | 1332 | const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation); |
| 1326 | 1333 | defer std.debug.unlockStderrWriter(); |
| 1327 | | printErrorMessages(run.gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.prominent_compile_errors) catch {}; |
| 1334 | printErrorMessages(run.gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.error_style, run.multiline_errors) catch {}; |
| 1328 | 1335 | } |
| 1329 | 1336 | |
| 1330 | 1337 | handle_result: { |
| ... | ... | @@ -1388,37 +1395,46 @@ pub fn printErrorMessages( |
| 1388 | 1395 | failing_step: *Step, |
| 1389 | 1396 | options: std.zig.ErrorBundle.RenderOptions, |
| 1390 | 1397 | stderr: *Writer, |
| 1391 | | prominent_compile_errors: bool, |
| 1398 | error_style: ErrorStyle, |
| 1399 | multiline_errors: MultilineErrors, |
| 1392 | 1400 | ) !void { |
| 1393 | | // Provide context for where these error messages are coming from by |
| 1394 | | // printing the corresponding Step subtree. |
| 1395 | | |
| 1396 | | var step_stack: std.ArrayListUnmanaged(*Step) = .empty; |
| 1397 | | defer step_stack.deinit(gpa); |
| 1398 | | try step_stack.append(gpa, failing_step); |
| 1399 | | while (step_stack.items[step_stack.items.len - 1].dependants.items.len != 0) { |
| 1400 | | try step_stack.append(gpa, step_stack.items[step_stack.items.len - 1].dependants.items[0]); |
| 1401 | | } |
| 1402 | | |
| 1403 | | // Now, `step_stack` has the subtree that we want to print, in reverse order. |
| 1404 | 1401 | const ttyconf = options.ttyconf; |
| 1405 | | try ttyconf.setColor(stderr, .dim); |
| 1406 | | var indent: usize = 0; |
| 1407 | | while (step_stack.pop()) |s| : (indent += 1) { |
| 1408 | | if (indent > 0) { |
| 1409 | | try stderr.splatByteAll(' ', (indent - 1) * 3); |
| 1410 | | try printChildNodePrefix(stderr, ttyconf); |
| 1402 | |
| 1403 | if (error_style.verboseContext()) { |
| 1404 | // Provide context for where these error messages are coming from by |
| 1405 | // printing the corresponding Step subtree. |
| 1406 | var step_stack: std.ArrayListUnmanaged(*Step) = .empty; |
| 1407 | defer step_stack.deinit(gpa); |
| 1408 | try step_stack.append(gpa, failing_step); |
| 1409 | while (step_stack.items[step_stack.items.len - 1].dependants.items.len != 0) { |
| 1410 | try step_stack.append(gpa, step_stack.items[step_stack.items.len - 1].dependants.items[0]); |
| 1411 | 1411 | } |
| 1412 | 1412 | |
| 1413 | | try stderr.writeAll(s.name); |
| 1413 | // Now, `step_stack` has the subtree that we want to print, in reverse order. |
| 1414 | try ttyconf.setColor(stderr, .dim); |
| 1415 | var indent: usize = 0; |
| 1416 | while (step_stack.pop()) |s| : (indent += 1) { |
| 1417 | if (indent > 0) { |
| 1418 | try stderr.splatByteAll(' ', (indent - 1) * 3); |
| 1419 | try printChildNodePrefix(stderr, ttyconf); |
| 1420 | } |
| 1414 | 1421 | |
| 1415 | | if (s == failing_step) { |
| 1416 | | try printStepFailure(s, stderr, ttyconf); |
| 1417 | | } else { |
| 1418 | | try stderr.writeAll("\n"); |
| 1422 | try stderr.writeAll(s.name); |
| 1423 | |
| 1424 | if (s == failing_step) { |
| 1425 | try printStepFailure(s, stderr, ttyconf); |
| 1426 | } else { |
| 1427 | try stderr.writeAll("\n"); |
| 1428 | } |
| 1419 | 1429 | } |
| 1430 | try ttyconf.setColor(stderr, .reset); |
| 1431 | } else { |
| 1432 | // Just print the failing step itself. |
| 1433 | try ttyconf.setColor(stderr, .dim); |
| 1434 | try stderr.writeAll(failing_step.name); |
| 1435 | try printStepFailure(failing_step, stderr, ttyconf); |
| 1436 | try ttyconf.setColor(stderr, .reset); |
| 1420 | 1437 | } |
| 1421 | | try ttyconf.setColor(stderr, .reset); |
| 1422 | 1438 | |
| 1423 | 1439 | if (failing_step.result_stderr.len > 0) { |
| 1424 | 1440 | try stderr.writeAll(failing_step.result_stderr); |
| ... | ... | @@ -1427,30 +1443,38 @@ pub fn printErrorMessages( |
| 1427 | 1443 | } |
| 1428 | 1444 | } |
| 1429 | 1445 | |
| 1430 | | if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) { |
| 1431 | | try failing_step.result_error_bundle.renderToWriter(options, stderr); |
| 1432 | | } |
| 1446 | try failing_step.result_error_bundle.renderToWriter(options, stderr); |
| 1433 | 1447 | |
| 1434 | 1448 | for (failing_step.result_error_msgs.items) |msg| { |
| 1435 | 1449 | try ttyconf.setColor(stderr, .red); |
| 1436 | | try stderr.writeAll("error: "); |
| 1450 | try stderr.writeAll("error:"); |
| 1437 | 1451 | try ttyconf.setColor(stderr, .reset); |
| 1438 | | // If the message has multiple lines, indent the non-initial ones to align them with the 'error:' text. |
| 1439 | | var it = std.mem.splitScalar(u8, msg, '\n'); |
| 1440 | | try stderr.writeAll(it.first()); |
| 1441 | | while (it.next()) |line| { |
| 1442 | | try stderr.print("\n {s}", .{line}); |
| 1452 | if (std.mem.indexOfScalar(u8, msg, '\n') == null) { |
| 1453 | try stderr.print(" {s}\n", .{msg}); |
| 1454 | } else switch (multiline_errors) { |
| 1455 | .indent => { |
| 1456 | var it = std.mem.splitScalar(u8, msg, '\n'); |
| 1457 | try stderr.print(" {s}\n", .{it.first()}); |
| 1458 | while (it.next()) |line| { |
| 1459 | try stderr.print(" {s}\n", .{line}); |
| 1460 | } |
| 1461 | }, |
| 1462 | .newline => try stderr.print("\n{s}\n", .{msg}), |
| 1463 | .none => try stderr.print(" {s}\n", .{msg}), |
| 1443 | 1464 | } |
| 1444 | | try stderr.writeAll("\n"); |
| 1445 | 1465 | } |
| 1446 | 1466 | |
| 1447 | | if (failing_step.result_failed_command) |cmd_str| { |
| 1448 | | try ttyconf.setColor(stderr, .red); |
| 1449 | | try stderr.writeAll("failed command: "); |
| 1450 | | try ttyconf.setColor(stderr, .reset); |
| 1451 | | try stderr.writeAll(cmd_str); |
| 1452 | | try stderr.writeByte('\n'); |
| 1467 | if (error_style.verboseContext()) { |
| 1468 | if (failing_step.result_failed_command) |cmd_str| { |
| 1469 | try ttyconf.setColor(stderr, .red); |
| 1470 | try stderr.writeAll("failed command: "); |
| 1471 | try ttyconf.setColor(stderr, .reset); |
| 1472 | try stderr.writeAll(cmd_str); |
| 1473 | try stderr.writeByte('\n'); |
| 1474 | } |
| 1453 | 1475 | } |
| 1476 | |
| 1477 | try stderr.writeByte('\n'); |
| 1454 | 1478 | } |
| 1455 | 1479 | |
| 1456 | 1480 | fn printSteps(builder: *std.Build, w: *Writer) !void { |
| ... | ... | @@ -1505,11 +1529,20 @@ fn printUsage(b: *std.Build, w: *Writer) !void { |
| 1505 | 1529 | \\ -l, --list-steps Print available steps |
| 1506 | 1530 | \\ --verbose Print commands before executing them |
| 1507 | 1531 | \\ --color [auto|off|on] Enable or disable colored error messages |
| 1508 | | \\ --prominent-compile-errors Buffer compile errors and display at end |
| 1532 | \\ --error-style [style] Control how build errors are printed |
| 1533 | \\ verbose (Default) Report errors with full context |
| 1534 | \\ minimal Report errors after summary, excluding context like command lines |
| 1535 | \\ verbose_clear Like 'verbose', but clear the terminal at the start of each update |
| 1536 | \\ minimal_clear Like 'minimal', but clear the terminal at the start of each update |
| 1537 | \\ --multiline-errors [style] Control how multi-line error messages are printed |
| 1538 | \\ indent (Default) Indent non-initial lines to align with initial line |
| 1539 | \\ newline Include a leading newline so that the error message is on its own lines |
| 1540 | \\ none Print as usual so the first line is misaligned |
| 1509 | 1541 | \\ --summary [mode] Control the printing of the build summary |
| 1510 | 1542 | \\ all Print the build summary in its entirety |
| 1511 | 1543 | \\ new Omit cached steps |
| 1512 | | \\ failures (Default) Only print failed steps |
| 1544 | \\ failures (Default if short-lived) Only print failed steps |
| 1545 | \\ line (Default if long-lived) Only print the single-line summary |
| 1513 | 1546 | \\ none Do not print the build summary |
| 1514 | 1547 | \\ -j<N> Limit concurrent jobs (default is to use all CPU cores) |
| 1515 | 1548 | \\ --maxrss <bytes> Limit memory usage (default is to use available memory) |
| ... | ... | @@ -1633,24 +1666,27 @@ fn argsRest(args: []const [:0]const u8, idx: usize) ?[]const [:0]const u8 { |
| 1633 | 1666 | return args[idx..]; |
| 1634 | 1667 | } |
| 1635 | 1668 | |
| 1636 | | /// Perhaps in the future there could be an Advanced Options flag such as |
| 1637 | | /// --debug-build-runner-leaks which would make this function return instead of |
| 1638 | | /// calling exit. |
| 1639 | | fn cleanExit() void { |
| 1640 | | std.debug.lockStdErr(); |
| 1641 | | process.exit(0); |
| 1642 | | } |
| 1643 | | |
| 1644 | | /// Perhaps in the future there could be an Advanced Options flag such as |
| 1645 | | /// --debug-build-runner-leaks which would make this function return instead of |
| 1646 | | /// calling exit. |
| 1647 | | fn uncleanExit() error{UncleanExit} { |
| 1648 | | std.debug.lockStdErr(); |
| 1649 | | process.exit(1); |
| 1650 | | } |
| 1651 | | |
| 1652 | 1669 | const Color = std.zig.Color; |
| 1653 | | const Summary = enum { all, new, failures, none }; |
| 1670 | const ErrorStyle = enum { |
| 1671 | verbose, |
| 1672 | minimal, |
| 1673 | verbose_clear, |
| 1674 | minimal_clear, |
| 1675 | fn verboseContext(s: ErrorStyle) bool { |
| 1676 | return switch (s) { |
| 1677 | .verbose, .verbose_clear => true, |
| 1678 | .minimal, .minimal_clear => false, |
| 1679 | }; |
| 1680 | } |
| 1681 | fn clearOnUpdate(s: ErrorStyle) bool { |
| 1682 | return switch (s) { |
| 1683 | .verbose, .minimal => false, |
| 1684 | .verbose_clear, .minimal_clear => true, |
| 1685 | }; |
| 1686 | } |
| 1687 | }; |
| 1688 | const MultilineErrors = enum { indent, newline, none }; |
| 1689 | const Summary = enum { all, new, failures, line, none }; |
| 1654 | 1690 | |
| 1655 | 1691 | fn get_tty_conf(color: Color, stderr: File) tty.Config { |
| 1656 | 1692 | return switch (color) { |