From 7d5bce56e16cd7661b79046d573427972bbb6cf5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 9 Mar 2023 23:56:12 -0700 Subject: [PATCH] build runner: print to stderr in dumb terminals Terminal progress is suppressed and instead there is an explicit handling of printing to stderr, one line per step make() function call. The output looks very similar to Ninja. A future commit should add a -q to quiet the output. --- lib/build_runner.zig | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/lib/build_runner.zig b/lib/build_runner.zig index e1c3768048..a1b88f8c0b 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -278,8 +278,12 @@ pub fn main() !void { .windows_api => {}, } - var progress: std.Progress = .{ .dont_print_on_dumb = true }; + var progress: std.Progress = .{}; const main_progress_node = progress.start("", 0); + if (ttyconf == .no_color) { + progress.timer = null; + progress.terminal = null; + } builder.debug_log_scopes = debug_log_scopes.items; builder.resolveInstallPrefix(install_prefix, dir_list); @@ -302,6 +306,9 @@ pub fn main() !void { .enable_summary = enable_summary, .ttyconf = ttyconf, .stderr = stderr, + + .step_index = 0, + .step_count = undefined, }; if (run.max_rss == 0) { @@ -332,6 +339,9 @@ const Run = struct { enable_summary: ?bool, ttyconf: std.debug.TTY.Config, stderr: std.fs.File, + + step_count: usize, + step_index: usize, }; fn runStepNames( @@ -395,7 +405,8 @@ fn runStepNames( { defer parent_prog_node.end(); - var step_prog = parent_prog_node.start("run steps", step_stack.count()); + run.step_count = step_stack.count(); + var step_prog = parent_prog_node.start("run steps", run.step_count); defer step_prog.end(); var wait_group: std.Thread.WaitGroup = .{}; @@ -739,10 +750,27 @@ fn workerMakeOneStep( sub_prog_node.activate(); defer sub_prog_node.end(); - // I suspect we will want to pass `b` to make() in a future modification. - // For example, CompileStep does some sus things with modifying the saved - // *Build object in install header steps that might be able to be removed - // by passing the *Build object through the make() functions. + const stderr = run.stderr; + const ttyconf = run.ttyconf; + + // If we are unable to print a fancy terminal progress bar, then we resort + // to 1 line printed to stderr for each step, similar to Ninja. + if (ttyconf == .no_color) { + var buf: [120]u8 = undefined; + const step_index = @atomicRmw(usize, &run.step_index, .Add, 1, .Monotonic); + const text = std.fmt.bufPrint(&buf, "[{d}/{d}] Making {s}{s}\n", .{ + step_index + 1, run.step_count, s.owner.dep_prefix, s.name, + }) catch |err| switch (err) { + error.NoSpaceLeft => blk: { + buf[buf.len - 4 ..].* = "...\n".*; + break :blk &buf; + }, + }; + std.debug.getStderrMutex().lock(); + defer std.debug.getStderrMutex().unlock(); + stderr.writeAll(text) catch {}; + } + const make_result = s.make(&sub_prog_node); // No matter the result, we want to display error/warning messages. @@ -750,9 +778,6 @@ fn workerMakeOneStep( sub_prog_node.context.lock_stderr(); defer sub_prog_node.context.unlock_stderr(); - const stderr = run.stderr; - const ttyconf = run.ttyconf; - for (s.result_error_msgs.items) |msg| { // Sometimes it feels like you just can't catch a break. Finally, // with Zig, you can.