mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
build runner: remove --prominent-compile-errors, introduce --error-style
The new `--error-style` option decides how build failures are printed. The default mode "verbose" prints all context including the step graph fragment and the failed command (if any). The alternative mode "minimal" prints only the failed step itself, and does not print the failed command. There are also "verbose_clear" and "minimal_clear" modes, which have the distinction that the output is cleared (through ANSI escape codes) between updates, preventing different updates from being confused in the output. If `--error-style` is not specified, the environment variable `ZIG_BUILD_ERROR_STYLE` is checked before falling back to the default of "verbose"; this means the value can effectively be chosen system-wide since it is generally a personal preference. Also introduced is a `--multiline-errors` option which decides how to print errors which span multiple lines. By default, non-initial lines are indented to align with the first. Alternatively, a leading newline can be printed to align everyting on the first column, or no special treatment can be applied, resulting in misaligned output. Again, there is an environment variable (`ZIG_BUILD_MULTILINE_ERRORS`) to specify a preferred default if the option is not explicitly provided. Resolves: #23472
This commit is contained in:
parent
a388a8e5a7
commit
75adbf40ca
@ -103,12 +103,13 @@ pub fn main() !void {
|
|||||||
|
|
||||||
var install_prefix: ?[]const u8 = null;
|
var install_prefix: ?[]const u8 = null;
|
||||||
var dir_list = std.Build.DirList{};
|
var dir_list = std.Build.DirList{};
|
||||||
|
var error_style: ErrorStyle = .verbose;
|
||||||
|
var multiline_errors: MultilineErrors = .indent;
|
||||||
var summary: ?Summary = null;
|
var summary: ?Summary = null;
|
||||||
var max_rss: u64 = 0;
|
var max_rss: u64 = 0;
|
||||||
var skip_oom_steps = false;
|
var skip_oom_steps = false;
|
||||||
var test_timeout_ms: ?u64 = null;
|
var test_timeout_ms: ?u64 = null;
|
||||||
var color: Color = .auto;
|
var color: Color = .auto;
|
||||||
var prominent_compile_errors = false;
|
|
||||||
var help_menu = false;
|
var help_menu = false;
|
||||||
var steps_menu = false;
|
var steps_menu = false;
|
||||||
var output_tmp_nonce: ?[16]u8 = null;
|
var output_tmp_nonce: ?[16]u8 = null;
|
||||||
@ -117,6 +118,18 @@ pub fn main() !void {
|
|||||||
var debounce_interval_ms: u16 = 50;
|
var debounce_interval_ms: u16 = 50;
|
||||||
var webui_listen: ?std.net.Address = null;
|
var webui_listen: ?std.net.Address = null;
|
||||||
|
|
||||||
|
if (try std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(arena)) |str| {
|
||||||
|
if (std.meta.stringToEnum(ErrorStyle, str)) |style| {
|
||||||
|
error_style = style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (try std.zig.EnvVar.ZIG_BUILD_MULTILINE_ERRORS.get(arena)) |str| {
|
||||||
|
if (std.meta.stringToEnum(MultilineErrors, str)) |style| {
|
||||||
|
multiline_errors = style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (nextArg(args, &arg_idx)) |arg| {
|
while (nextArg(args, &arg_idx)) |arg| {
|
||||||
if (mem.startsWith(u8, arg, "-Z")) {
|
if (mem.startsWith(u8, arg, "-Z")) {
|
||||||
if (arg.len != 18) fatalWithHint("bad argument: '{s}'", .{arg});
|
if (arg.len != 18) fatalWithHint("bad argument: '{s}'", .{arg});
|
||||||
@ -197,11 +210,23 @@ pub fn main() !void {
|
|||||||
arg, next_arg,
|
arg, next_arg,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
} else if (mem.eql(u8, arg, "--error-style")) {
|
||||||
|
const next_arg = nextArg(args, &arg_idx) orelse
|
||||||
|
fatalWithHint("expected style after '{s}'", .{arg});
|
||||||
|
error_style = std.meta.stringToEnum(ErrorStyle, next_arg) orelse {
|
||||||
|
fatalWithHint("expected style after '{s}', found '{s}'", .{ arg, next_arg });
|
||||||
|
};
|
||||||
|
} else if (mem.eql(u8, arg, "--multiline-errors")) {
|
||||||
|
const next_arg = nextArg(args, &arg_idx) orelse
|
||||||
|
fatalWithHint("expected style after '{s}'", .{arg});
|
||||||
|
multiline_errors = std.meta.stringToEnum(MultilineErrors, next_arg) orelse {
|
||||||
|
fatalWithHint("expected style after '{s}', found '{s}'", .{ arg, next_arg });
|
||||||
|
};
|
||||||
} else if (mem.eql(u8, arg, "--summary")) {
|
} else if (mem.eql(u8, arg, "--summary")) {
|
||||||
const next_arg = nextArg(args, &arg_idx) orelse
|
const next_arg = nextArg(args, &arg_idx) orelse
|
||||||
fatalWithHint("expected [all|new|failures|none] after '{s}'", .{arg});
|
fatalWithHint("expected [all|new|failures|line|none] after '{s}'", .{arg});
|
||||||
summary = std.meta.stringToEnum(Summary, next_arg) orelse {
|
summary = std.meta.stringToEnum(Summary, next_arg) orelse {
|
||||||
fatalWithHint("expected [all|new|failures|none] after '{s}', found '{s}'", .{
|
fatalWithHint("expected [all|new|failures|line|none] after '{s}', found '{s}'", .{
|
||||||
arg, next_arg,
|
arg, next_arg,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -273,8 +298,6 @@ pub fn main() !void {
|
|||||||
builder.verbose_cc = true;
|
builder.verbose_cc = true;
|
||||||
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
|
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
|
||||||
builder.verbose_llvm_cpu_features = true;
|
builder.verbose_llvm_cpu_features = true;
|
||||||
} else if (mem.eql(u8, arg, "--prominent-compile-errors")) {
|
|
||||||
prominent_compile_errors = true;
|
|
||||||
} else if (mem.eql(u8, arg, "--watch")) {
|
} else if (mem.eql(u8, arg, "--watch")) {
|
||||||
watch = true;
|
watch = true;
|
||||||
} else if (mem.eql(u8, arg, "--time-report")) {
|
} else if (mem.eql(u8, arg, "--time-report")) {
|
||||||
@ -466,10 +489,11 @@ pub fn main() !void {
|
|||||||
.web_server = undefined, // set after `prepare`
|
.web_server = undefined, // set after `prepare`
|
||||||
.memory_blocked_steps = .empty,
|
.memory_blocked_steps = .empty,
|
||||||
.step_stack = .empty,
|
.step_stack = .empty,
|
||||||
.prominent_compile_errors = prominent_compile_errors,
|
|
||||||
|
|
||||||
.claimed_rss = 0,
|
.claimed_rss = 0,
|
||||||
.summary = summary orelse if (watch) .new else .failures,
|
.error_style = error_style,
|
||||||
|
.multiline_errors = multiline_errors,
|
||||||
|
.summary = summary orelse if (watch or webui_listen != null) .line else .failures,
|
||||||
.ttyconf = ttyconf,
|
.ttyconf = ttyconf,
|
||||||
.stderr = stderr,
|
.stderr = stderr,
|
||||||
.thread_pool = undefined,
|
.thread_pool = undefined,
|
||||||
@ -485,8 +509,14 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prepare(arena, builder, targets.items, &run, graph.random_seed) catch |err| switch (err) {
|
prepare(arena, builder, targets.items, &run, graph.random_seed) catch |err| switch (err) {
|
||||||
error.UncleanExit => process.exit(1),
|
error.DependencyLoopDetected => {
|
||||||
else => return err,
|
// Perhaps in the future there could be an Advanced Options flag such as
|
||||||
|
// --debug-build-runner-leaks which would make this code return instead of
|
||||||
|
// calling exit.
|
||||||
|
std.debug.lockStdErr();
|
||||||
|
process.exit(1);
|
||||||
|
},
|
||||||
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
|
|
||||||
var w: Watch = w: {
|
var w: Watch = w: {
|
||||||
@ -516,22 +546,20 @@ pub fn main() !void {
|
|||||||
ws.start() catch |err| fatal("failed to start web server: {s}", .{@errorName(err)});
|
ws.start() catch |err| fatal("failed to start web server: {s}", .{@errorName(err)});
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild: while (true) {
|
rebuild: while (true) : (if (run.error_style.clearOnUpdate()) {
|
||||||
|
const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation);
|
||||||
|
defer std.debug.unlockStderrWriter();
|
||||||
|
try bw.writeAll("\x1B[2J\x1B[3J\x1B[H");
|
||||||
|
}) {
|
||||||
if (run.web_server) |*ws| ws.startBuild();
|
if (run.web_server) |*ws| ws.startBuild();
|
||||||
|
|
||||||
runStepNames(
|
try runStepNames(
|
||||||
builder,
|
builder,
|
||||||
targets.items,
|
targets.items,
|
||||||
main_progress_node,
|
main_progress_node,
|
||||||
&run,
|
&run,
|
||||||
fuzz,
|
fuzz,
|
||||||
) catch |err| switch (err) {
|
);
|
||||||
error.UncleanExit => {
|
|
||||||
assert(!run.watch and run.web_server == null);
|
|
||||||
process.exit(1);
|
|
||||||
},
|
|
||||||
else => return err,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (run.web_server) |*web_server| {
|
if (run.web_server) |*web_server| {
|
||||||
if (fuzz) |mode| if (mode != .forever) fatal(
|
if (fuzz) |mode| if (mode != .forever) fatal(
|
||||||
@ -542,10 +570,6 @@ pub fn main() !void {
|
|||||||
web_server.finishBuild(.{ .fuzz = fuzz != null });
|
web_server.finishBuild(.{ .fuzz = fuzz != null });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!watch and run.web_server == null) {
|
|
||||||
return cleanExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (run.web_server) |*ws| {
|
if (run.web_server) |*ws| {
|
||||||
assert(!watch); // fatal error after CLI parsing
|
assert(!watch); // fatal error after CLI parsing
|
||||||
while (true) switch (ws.wait()) {
|
while (true) switch (ws.wait()) {
|
||||||
@ -626,18 +650,14 @@ const Run = struct {
|
|||||||
memory_blocked_steps: std.ArrayListUnmanaged(*Step),
|
memory_blocked_steps: std.ArrayListUnmanaged(*Step),
|
||||||
/// Allocated into `gpa`.
|
/// Allocated into `gpa`.
|
||||||
step_stack: std.AutoArrayHashMapUnmanaged(*Step, void),
|
step_stack: std.AutoArrayHashMapUnmanaged(*Step, void),
|
||||||
prominent_compile_errors: bool,
|
|
||||||
thread_pool: std.Thread.Pool,
|
thread_pool: std.Thread.Pool,
|
||||||
|
|
||||||
claimed_rss: usize,
|
claimed_rss: usize,
|
||||||
|
error_style: ErrorStyle,
|
||||||
|
multiline_errors: MultilineErrors,
|
||||||
summary: Summary,
|
summary: Summary,
|
||||||
ttyconf: tty.Config,
|
ttyconf: tty.Config,
|
||||||
stderr: File,
|
stderr: File,
|
||||||
|
|
||||||
fn cleanExit(run: Run) void {
|
|
||||||
if (run.watch or run.web_server != null) return;
|
|
||||||
return runner.cleanExit();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn prepare(
|
fn prepare(
|
||||||
@ -671,10 +691,7 @@ fn prepare(
|
|||||||
rand.shuffle(*Step, starting_steps);
|
rand.shuffle(*Step, starting_steps);
|
||||||
|
|
||||||
for (starting_steps) |s| {
|
for (starting_steps) |s| {
|
||||||
constructGraphAndCheckForDependencyLoop(gpa, b, s, &run.step_stack, rand) catch |err| switch (err) {
|
try constructGraphAndCheckForDependencyLoop(gpa, b, s, &run.step_stack, rand);
|
||||||
error.DependencyLoopDetected => return uncleanExit(),
|
|
||||||
else => |e| return e,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -827,26 +844,25 @@ fn runStepNames(
|
|||||||
// Every test has a state
|
// Every test has a state
|
||||||
assert(test_pass_count + test_skip_count + test_fail_count + test_crash_count + test_timeout_count == test_count);
|
assert(test_pass_count + test_skip_count + test_fail_count + test_crash_count + test_timeout_count == test_count);
|
||||||
|
|
||||||
// A proper command line application defaults to silently succeeding.
|
|
||||||
// The user may request verbose mode if they have a different preference.
|
|
||||||
const failures_only = switch (run.summary) {
|
|
||||||
.failures, .none => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
if (failure_count == 0) {
|
if (failure_count == 0) {
|
||||||
std.Progress.setStatus(.success);
|
std.Progress.setStatus(.success);
|
||||||
if (failures_only) return run.cleanExit();
|
|
||||||
} else {
|
} else {
|
||||||
std.Progress.setStatus(.failure);
|
std.Progress.setStatus(.failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run.summary != .none) {
|
summary: {
|
||||||
|
switch (run.summary) {
|
||||||
|
.all, .new, .line => {},
|
||||||
|
.failures => if (failure_count == 0) break :summary,
|
||||||
|
.none => break :summary,
|
||||||
|
}
|
||||||
|
|
||||||
const w = std.debug.lockStderrWriter(&stdio_buffer_allocation);
|
const w = std.debug.lockStderrWriter(&stdio_buffer_allocation);
|
||||||
defer std.debug.unlockStderrWriter();
|
defer std.debug.unlockStderrWriter();
|
||||||
|
|
||||||
const total_count = success_count + failure_count + pending_count + skipped_count;
|
const total_count = success_count + failure_count + pending_count + skipped_count;
|
||||||
ttyconf.setColor(w, .cyan) catch {};
|
ttyconf.setColor(w, .cyan) catch {};
|
||||||
w.writeAll("\nBuild Summary:") catch {};
|
w.writeAll("Build Summary:") catch {};
|
||||||
ttyconf.setColor(w, .reset) catch {};
|
ttyconf.setColor(w, .reset) catch {};
|
||||||
w.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
|
w.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
|
||||||
if (skipped_count > 0) w.print(", {d} skipped", .{skipped_count}) catch {};
|
if (skipped_count > 0) w.print(", {d} skipped", .{skipped_count}) catch {};
|
||||||
@ -862,6 +878,8 @@ fn runStepNames(
|
|||||||
|
|
||||||
w.writeAll("\n") catch {};
|
w.writeAll("\n") catch {};
|
||||||
|
|
||||||
|
if (run.summary == .line) break :summary;
|
||||||
|
|
||||||
// Print a fancy tree with build results.
|
// Print a fancy tree with build results.
|
||||||
var step_stack_copy = try step_stack.clone(gpa);
|
var step_stack_copy = try step_stack.clone(gpa);
|
||||||
defer step_stack_copy.deinit(gpa);
|
defer step_stack_copy.deinit(gpa);
|
||||||
@ -877,7 +895,7 @@ fn runStepNames(
|
|||||||
i -= 1;
|
i -= 1;
|
||||||
const step = b.top_level_steps.get(step_names[i]).?.step;
|
const step = b.top_level_steps.get(step_names[i]).?.step;
|
||||||
const found = switch (run.summary) {
|
const found = switch (run.summary) {
|
||||||
.all, .none => unreachable,
|
.all, .line, .none => unreachable,
|
||||||
.failures => step.state != .success,
|
.failures => step.state != .success,
|
||||||
.new => !step.result_cached,
|
.new => !step.result_cached,
|
||||||
};
|
};
|
||||||
@ -894,28 +912,19 @@ fn runStepNames(
|
|||||||
w.writeByte('\n') catch {};
|
w.writeByte('\n') catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failure_count == 0) {
|
if (run.watch or run.web_server != null) return;
|
||||||
return run.cleanExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, render compile errors at the bottom of the terminal.
|
// Perhaps in the future there could be an Advanced Options flag such as
|
||||||
if (run.prominent_compile_errors and total_compile_errors > 0) {
|
// --debug-build-runner-leaks which would make this code return instead of
|
||||||
for (step_stack.keys()) |s| {
|
// calling exit.
|
||||||
if (s.result_error_bundle.errorMessageCount() > 0) {
|
|
||||||
s.result_error_bundle.renderToStdErr(.{ .ttyconf = ttyconf });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!run.watch and run.web_server == null) {
|
const code: u8 = code: {
|
||||||
// Signal to parent process that we have printed compile errors. The
|
if (failure_count == 0) break :code 0; // success
|
||||||
// parent process may choose to omit the "following command failed"
|
if (run.error_style.verboseContext()) break :code 1; // failure; print build command
|
||||||
// line in this case.
|
break :code 2; // failure; do not print build command
|
||||||
|
};
|
||||||
std.debug.lockStdErr();
|
std.debug.lockStdErr();
|
||||||
process.exit(2);
|
process.exit(code);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!run.watch and run.web_server == null) return uncleanExit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PrintNode = struct {
|
const PrintNode = struct {
|
||||||
@ -1124,7 +1133,7 @@ fn printTreeStep(
|
|||||||
const first = step_stack.swapRemove(s);
|
const first = step_stack.swapRemove(s);
|
||||||
const summary = run.summary;
|
const summary = run.summary;
|
||||||
const skip = switch (summary) {
|
const skip = switch (summary) {
|
||||||
.none => unreachable,
|
.none, .line => unreachable,
|
||||||
.all => false,
|
.all => false,
|
||||||
.new => s.result_cached,
|
.new => s.result_cached,
|
||||||
.failures => s.state == .success,
|
.failures => s.state == .success,
|
||||||
@ -1157,7 +1166,7 @@ fn printTreeStep(
|
|||||||
|
|
||||||
const step = s.dependencies.items[i];
|
const step = s.dependencies.items[i];
|
||||||
const found = switch (summary) {
|
const found = switch (summary) {
|
||||||
.all, .none => unreachable,
|
.all, .line, .none => unreachable,
|
||||||
.failures => step.state != .success,
|
.failures => step.state != .success,
|
||||||
.new => !step.result_cached,
|
.new => !step.result_cached,
|
||||||
};
|
};
|
||||||
@ -1316,15 +1325,13 @@ fn workerMakeOneStep(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// No matter the result, we want to display error/warning messages.
|
// No matter the result, we want to display error/warning messages.
|
||||||
const show_compile_errors = !run.prominent_compile_errors and
|
const show_compile_errors = s.result_error_bundle.errorMessageCount() > 0;
|
||||||
s.result_error_bundle.errorMessageCount() > 0;
|
|
||||||
const show_error_msgs = s.result_error_msgs.items.len > 0;
|
const show_error_msgs = s.result_error_msgs.items.len > 0;
|
||||||
const show_stderr = s.result_stderr.len > 0;
|
const show_stderr = s.result_stderr.len > 0;
|
||||||
|
|
||||||
if (show_error_msgs or show_compile_errors or show_stderr) {
|
if (show_error_msgs or show_compile_errors or show_stderr) {
|
||||||
const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation);
|
const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation);
|
||||||
defer std.debug.unlockStderrWriter();
|
defer std.debug.unlockStderrWriter();
|
||||||
printErrorMessages(run.gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.prominent_compile_errors) catch {};
|
printErrorMessages(run.gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.error_style, run.multiline_errors) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_result: {
|
handle_result: {
|
||||||
@ -1388,11 +1395,14 @@ pub fn printErrorMessages(
|
|||||||
failing_step: *Step,
|
failing_step: *Step,
|
||||||
options: std.zig.ErrorBundle.RenderOptions,
|
options: std.zig.ErrorBundle.RenderOptions,
|
||||||
stderr: *Writer,
|
stderr: *Writer,
|
||||||
prominent_compile_errors: bool,
|
error_style: ErrorStyle,
|
||||||
|
multiline_errors: MultilineErrors,
|
||||||
) !void {
|
) !void {
|
||||||
|
const ttyconf = options.ttyconf;
|
||||||
|
|
||||||
|
if (error_style.verboseContext()) {
|
||||||
// Provide context for where these error messages are coming from by
|
// Provide context for where these error messages are coming from by
|
||||||
// printing the corresponding Step subtree.
|
// printing the corresponding Step subtree.
|
||||||
|
|
||||||
var step_stack: std.ArrayListUnmanaged(*Step) = .empty;
|
var step_stack: std.ArrayListUnmanaged(*Step) = .empty;
|
||||||
defer step_stack.deinit(gpa);
|
defer step_stack.deinit(gpa);
|
||||||
try step_stack.append(gpa, failing_step);
|
try step_stack.append(gpa, failing_step);
|
||||||
@ -1401,7 +1411,6 @@ pub fn printErrorMessages(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now, `step_stack` has the subtree that we want to print, in reverse order.
|
// Now, `step_stack` has the subtree that we want to print, in reverse order.
|
||||||
const ttyconf = options.ttyconf;
|
|
||||||
try ttyconf.setColor(stderr, .dim);
|
try ttyconf.setColor(stderr, .dim);
|
||||||
var indent: usize = 0;
|
var indent: usize = 0;
|
||||||
while (step_stack.pop()) |s| : (indent += 1) {
|
while (step_stack.pop()) |s| : (indent += 1) {
|
||||||
@ -1419,6 +1428,13 @@ pub fn printErrorMessages(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try ttyconf.setColor(stderr, .reset);
|
try ttyconf.setColor(stderr, .reset);
|
||||||
|
} else {
|
||||||
|
// Just print the failing step itself.
|
||||||
|
try ttyconf.setColor(stderr, .dim);
|
||||||
|
try stderr.writeAll(failing_step.name);
|
||||||
|
try printStepFailure(failing_step, stderr, ttyconf);
|
||||||
|
try ttyconf.setColor(stderr, .reset);
|
||||||
|
}
|
||||||
|
|
||||||
if (failing_step.result_stderr.len > 0) {
|
if (failing_step.result_stderr.len > 0) {
|
||||||
try stderr.writeAll(failing_step.result_stderr);
|
try stderr.writeAll(failing_step.result_stderr);
|
||||||
@ -1427,23 +1443,28 @@ pub fn printErrorMessages(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) {
|
|
||||||
try failing_step.result_error_bundle.renderToWriter(options, stderr);
|
try failing_step.result_error_bundle.renderToWriter(options, stderr);
|
||||||
}
|
|
||||||
|
|
||||||
for (failing_step.result_error_msgs.items) |msg| {
|
for (failing_step.result_error_msgs.items) |msg| {
|
||||||
try ttyconf.setColor(stderr, .red);
|
try ttyconf.setColor(stderr, .red);
|
||||||
try stderr.writeAll("error:");
|
try stderr.writeAll("error:");
|
||||||
try ttyconf.setColor(stderr, .reset);
|
try ttyconf.setColor(stderr, .reset);
|
||||||
// If the message has multiple lines, indent the non-initial ones to align them with the 'error:' text.
|
if (std.mem.indexOfScalar(u8, msg, '\n') == null) {
|
||||||
|
try stderr.print(" {s}\n", .{msg});
|
||||||
|
} else switch (multiline_errors) {
|
||||||
|
.indent => {
|
||||||
var it = std.mem.splitScalar(u8, msg, '\n');
|
var it = std.mem.splitScalar(u8, msg, '\n');
|
||||||
try stderr.writeAll(it.first());
|
try stderr.print(" {s}\n", .{it.first()});
|
||||||
while (it.next()) |line| {
|
while (it.next()) |line| {
|
||||||
try stderr.print("\n {s}", .{line});
|
try stderr.print(" {s}\n", .{line});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.newline => try stderr.print("\n{s}\n", .{msg}),
|
||||||
|
.none => try stderr.print(" {s}\n", .{msg}),
|
||||||
}
|
}
|
||||||
try stderr.writeAll("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error_style.verboseContext()) {
|
||||||
if (failing_step.result_failed_command) |cmd_str| {
|
if (failing_step.result_failed_command) |cmd_str| {
|
||||||
try ttyconf.setColor(stderr, .red);
|
try ttyconf.setColor(stderr, .red);
|
||||||
try stderr.writeAll("failed command: ");
|
try stderr.writeAll("failed command: ");
|
||||||
@ -1453,6 +1474,9 @@ pub fn printErrorMessages(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try stderr.writeByte('\n');
|
||||||
|
}
|
||||||
|
|
||||||
fn printSteps(builder: *std.Build, w: *Writer) !void {
|
fn printSteps(builder: *std.Build, w: *Writer) !void {
|
||||||
const arena = builder.graph.arena;
|
const arena = builder.graph.arena;
|
||||||
for (builder.top_level_steps.values()) |top_level_step| {
|
for (builder.top_level_steps.values()) |top_level_step| {
|
||||||
@ -1505,11 +1529,20 @@ fn printUsage(b: *std.Build, w: *Writer) !void {
|
|||||||
\\ -l, --list-steps Print available steps
|
\\ -l, --list-steps Print available steps
|
||||||
\\ --verbose Print commands before executing them
|
\\ --verbose Print commands before executing them
|
||||||
\\ --color [auto|off|on] Enable or disable colored error messages
|
\\ --color [auto|off|on] Enable or disable colored error messages
|
||||||
\\ --prominent-compile-errors Buffer compile errors and display at end
|
\\ --error-style [style] Control how build errors are printed
|
||||||
|
\\ verbose (Default) Report errors with full context
|
||||||
|
\\ minimal Report errors after summary, excluding context like command lines
|
||||||
|
\\ verbose_clear Like 'verbose', but clear the terminal at the start of each update
|
||||||
|
\\ minimal_clear Like 'minimal', but clear the terminal at the start of each update
|
||||||
|
\\ --multiline-errors [style] Control how multi-line error messages are printed
|
||||||
|
\\ indent (Default) Indent non-initial lines to align with initial line
|
||||||
|
\\ newline Include a leading newline so that the error message is on its own lines
|
||||||
|
\\ none Print as usual so the first line is misaligned
|
||||||
\\ --summary [mode] Control the printing of the build summary
|
\\ --summary [mode] Control the printing of the build summary
|
||||||
\\ all Print the build summary in its entirety
|
\\ all Print the build summary in its entirety
|
||||||
\\ new Omit cached steps
|
\\ new Omit cached steps
|
||||||
\\ failures (Default) Only print failed steps
|
\\ failures (Default if short-lived) Only print failed steps
|
||||||
|
\\ line (Default if long-lived) Only print the single-line summary
|
||||||
\\ none Do not print the build summary
|
\\ none Do not print the build summary
|
||||||
\\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
|
\\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
|
||||||
\\ --maxrss <bytes> Limit memory usage (default is to use available memory)
|
\\ --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 {
|
|||||||
return args[idx..];
|
return args[idx..];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perhaps in the future there could be an Advanced Options flag such as
|
|
||||||
/// --debug-build-runner-leaks which would make this function return instead of
|
|
||||||
/// calling exit.
|
|
||||||
fn cleanExit() void {
|
|
||||||
std.debug.lockStdErr();
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Perhaps in the future there could be an Advanced Options flag such as
|
|
||||||
/// --debug-build-runner-leaks which would make this function return instead of
|
|
||||||
/// calling exit.
|
|
||||||
fn uncleanExit() error{UncleanExit} {
|
|
||||||
std.debug.lockStdErr();
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Color = std.zig.Color;
|
const Color = std.zig.Color;
|
||||||
const Summary = enum { all, new, failures, none };
|
const ErrorStyle = enum {
|
||||||
|
verbose,
|
||||||
|
minimal,
|
||||||
|
verbose_clear,
|
||||||
|
minimal_clear,
|
||||||
|
fn verboseContext(s: ErrorStyle) bool {
|
||||||
|
return switch (s) {
|
||||||
|
.verbose, .verbose_clear => true,
|
||||||
|
.minimal, .minimal_clear => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fn clearOnUpdate(s: ErrorStyle) bool {
|
||||||
|
return switch (s) {
|
||||||
|
.verbose, .minimal => false,
|
||||||
|
.verbose_clear, .minimal_clear => true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const MultilineErrors = enum { indent, newline, none };
|
||||||
|
const Summary = enum { all, new, failures, line, none };
|
||||||
|
|
||||||
fn get_tty_conf(color: Color, stderr: File) tty.Config {
|
fn get_tty_conf(color: Color, stderr: File) tty.Config {
|
||||||
return switch (color) {
|
return switch (color) {
|
||||||
|
|||||||
@ -178,7 +178,7 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: std.Io
|
|||||||
var buf: [256]u8 = undefined;
|
var buf: [256]u8 = undefined;
|
||||||
const w = std.debug.lockStderrWriter(&buf);
|
const w = std.debug.lockStderrWriter(&buf);
|
||||||
defer std.debug.unlockStderrWriter();
|
defer std.debug.unlockStderrWriter();
|
||||||
build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, w, false) catch {};
|
build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, w, .verbose, .indent) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const rebuilt_bin_path = result catch |err| switch (err) {
|
const rebuilt_bin_path = result catch |err| switch (err) {
|
||||||
@ -204,7 +204,7 @@ fn fuzzWorkerRun(
|
|||||||
var buf: [256]u8 = undefined;
|
var buf: [256]u8 = undefined;
|
||||||
const w = std.debug.lockStderrWriter(&buf);
|
const w = std.debug.lockStderrWriter(&buf);
|
||||||
defer std.debug.unlockStderrWriter();
|
defer std.debug.unlockStderrWriter();
|
||||||
build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = fuzz.ttyconf }, w, false) catch {};
|
build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = fuzz.ttyconf }, w, .verbose, .indent) catch {};
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
|||||||
@ -697,6 +697,8 @@ pub const EnvVar = enum {
|
|||||||
ZIG_LIB_DIR,
|
ZIG_LIB_DIR,
|
||||||
ZIG_LIBC,
|
ZIG_LIBC,
|
||||||
ZIG_BUILD_RUNNER,
|
ZIG_BUILD_RUNNER,
|
||||||
|
ZIG_BUILD_ERROR_STYLE,
|
||||||
|
ZIG_BUILD_MULTILINE_ERRORS,
|
||||||
ZIG_VERBOSE_LINK,
|
ZIG_VERBOSE_LINK,
|
||||||
ZIG_VERBOSE_CC,
|
ZIG_VERBOSE_CC,
|
||||||
ZIG_BTRFS_WORKAROUND,
|
ZIG_BTRFS_WORKAROUND,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user