diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-03-01 22:56:37 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-03-15 10:48:13 -0700 |
| commit | 58edefc6d1716c0731ee2fe672ec8d073651aafb (patch) | |
| tree | 9de4d030be9f44d3bc953d114eaef0812bd11cf4 /lib/build_runner.zig | |
| parent | d0f675827c28b1d50e8aea6a7d29cb45ad8d4e67 (diff) | |
| download | zig-58edefc6d1716c0731ee2fe672ec8d073651aafb.tar.gz zig-58edefc6d1716c0731ee2fe672ec8d073651aafb.zip | |
zig build: many enhancements related to parallel building
Rework std.Build.Step to have an `owner: *Build` field. This
simplified the implementation of installation steps, as well as provided
some much-needed common API for the new parallelized build system.
--verbose is now defined very concretely: it prints to stderr just
before spawning a child process.
Child process execution is updated to conform to the new
parallel-friendly make() function semantics.
DRY up the failWithCacheError handling code. It now integrates properly
with the step graph instead of incorrectly dumping to stderr and calling
process exit.
In the main CLI, fix `zig fmt` crash when there are no errors and stdin
is used.
Deleted steps:
* EmulatableRunStep - this entire thing can be removed in favor of a
flag added to std.Build.RunStep called `skip_foreign_checks`.
* LogStep - this doesn't really fit with a multi-threaded build runner
and is effectively superseded by the new build summary output.
build runner:
* add -fsummary and -fno-summary to override the default behavior,
which is to print a summary if any of the build steps fail.
* print the dep prefix when emitting error messages for steps.
std.Build.FmtStep:
* This step now supports exclude paths as well as a check flag.
* The check flag decides between two modes, modify mode, and check
mode. These can be used to update source files in place, or to fail
the build, respectively.
Zig's own build.zig:
* The `test-fmt` step will do all the `zig fmt` checking that we expect
to be done. Since the `test` step depends on this one, we can simply
remove the explicit call to `zig fmt` in the CI.
* The new `fmt` step will actually perform `zig fmt` and update source
files in place.
std.Build.RunStep:
* expose max_stdio_size is a field (previously an unchangeable
hard-coded value).
* rework the API. Instead of configuring each stream independently,
there is a `stdio` field where you can choose between
`infer_from_args`, `inherit`, or `check`. These determine whether the
RunStep is considered to have side-effects or not. The previous
field, `condition` is gone.
* when stdio mode is set to `check` there is a slice of any number of
checks to make, which include things like exit code, stderr matching,
or stdout matching.
* remove the ill-defined `print` field.
* when adding an output arg, it takes the opportunity to give itself a
better name.
* The flag `skip_foreign_checks` is added. If this is true, a RunStep
which is configured to check the output of the executed binary will
not fail the build if the binary cannot be executed due to being for
a foreign binary to the host system which is running the build graph.
Command-line arguments such as -fqemu and -fwasmtime may affect
whether a binary is detected as foreign, as well as system
configuration such as Rosetta (macOS) and binfmt_misc (Linux).
- This makes EmulatableRunStep no longer needed.
* Fix the child process handling to properly integrate with the new
bulid API and to avoid deadlocks in stdout/stderr streams by polling
if necessary.
std.Build.RemoveDirStep now uses the open build_root directory handle
instead of an absolute path.
Diffstat (limited to 'lib/build_runner.zig')
| -rw-r--r-- | lib/build_runner.zig | 71 |
1 files changed, 46 insertions, 25 deletions
diff --git a/lib/build_runner.zig b/lib/build_runner.zig index 2c5bcdd617..40f45d9ac8 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -93,6 +93,7 @@ pub fn main() !void { var install_prefix: ?[]const u8 = null; var dir_list = std.Build.DirList{}; + var enable_summary: ?bool = null; const Color = enum { auto, off, on }; var color: Color = .auto; @@ -217,6 +218,10 @@ pub fn main() !void { builder.enable_darling = true; } else if (mem.eql(u8, arg, "-fno-darling")) { builder.enable_darling = false; + } else if (mem.eql(u8, arg, "-fsummary")) { + enable_summary = true; + } else if (mem.eql(u8, arg, "-fno-summary")) { + enable_summary = false; } else if (mem.eql(u8, arg, "-freference-trace")) { builder.reference_trace = 256; } else if (mem.startsWith(u8, arg, "-freference-trace=")) { @@ -252,8 +257,9 @@ pub fn main() !void { } } + const stderr = std.io.getStdErr(); const ttyconf: std.debug.TTY.Config = switch (color) { - .auto => std.debug.detectTTYConfig(std.io.getStdErr()), + .auto => std.debug.detectTTYConfig(stderr), .on => .escape_codes, .off => .no_color, }; @@ -279,6 +285,8 @@ pub fn main() !void { main_progress_node, thread_pool_options, ttyconf, + stderr, + enable_summary, ) catch |err| switch (err) { error.UncleanExit => process.exit(1), else => return err, @@ -292,6 +300,8 @@ fn runStepNames( parent_prog_node: *std.Progress.Node, thread_pool_options: std.Thread.Pool.Options, ttyconf: std.debug.TTY.Config, + stderr: std.fs.File, + enable_summary: ?bool, ) !void { const gpa = b.allocator; var step_stack: std.AutoArrayHashMapUnmanaged(*Step, void) = .{}; @@ -382,28 +392,35 @@ fn runStepNames( // A proper command line application defaults to silently succeeding. // The user may request verbose mode if they have a different preference. - if (failure_count == 0 and !b.verbose) return cleanExit(); - - const stderr = std.io.getStdErr(); - - const total_count = success_count + failure_count + pending_count; - ttyconf.setColor(stderr, .Cyan) catch {}; - stderr.writeAll("Build Summary: ") catch {}; - ttyconf.setColor(stderr, .Reset) catch {}; - stderr.writer().print("{d}/{d} steps succeeded; {d} failed; {d} total compile errors\n", .{ - success_count, total_count, failure_count, total_compile_errors, - }) catch {}; + if (failure_count == 0 and enable_summary != true) return cleanExit(); + + if (enable_summary != false) { + const total_count = success_count + failure_count + pending_count; + ttyconf.setColor(stderr, .Cyan) catch {}; + stderr.writeAll("Build Summary:") catch {}; + ttyconf.setColor(stderr, .Reset) catch {}; + stderr.writer().print(" {d}/{d} steps succeeded; {d} failed", .{ + success_count, total_count, failure_count, + }) catch {}; + + if (enable_summary == null) { + ttyconf.setColor(stderr, .Dim) catch {}; + stderr.writeAll(" (disable with -fno-summary)") catch {}; + ttyconf.setColor(stderr, .Reset) catch {}; + } + stderr.writeAll("\n") catch {}; - // Print a fancy tree with build results. - var print_node: PrintNode = .{ .parent = null }; - if (step_names.len == 0) { - print_node.last = true; - printTreeStep(b, b.default_step, stderr, ttyconf, &print_node, &step_stack) catch {}; - } else { - for (step_names, 0..) |step_name, i| { - const tls = b.top_level_steps.get(step_name).?; - print_node.last = i + 1 == b.top_level_steps.count(); - printTreeStep(b, &tls.step, stderr, ttyconf, &print_node, &step_stack) catch {}; + // Print a fancy tree with build results. + var print_node: PrintNode = .{ .parent = null }; + if (step_names.len == 0) { + print_node.last = true; + printTreeStep(b, b.default_step, stderr, ttyconf, &print_node, &step_stack) catch {}; + } else { + for (step_names, 0..) |step_name, i| { + const tls = b.top_level_steps.get(step_name).?; + print_node.last = i + 1 == b.top_level_steps.count(); + printTreeStep(b, &tls.step, stderr, ttyconf, &print_node, &step_stack) catch {}; + } } } @@ -453,9 +470,9 @@ fn printTreeStep( step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), ) !void { const first = step_stack.swapRemove(s); - if (!first) try ttyconf.setColor(stderr, .Dim); try printPrefix(parent_node, stderr); + if (!first) try ttyconf.setColor(stderr, .Dim); if (parent_node.parent != null) { if (parent_node.last) { try stderr.writeAll("└─ "); @@ -464,7 +481,7 @@ fn printTreeStep( } } - // TODO print the dep prefix too? + // dep_prefix omitted here because it is redundant with the tree. try stderr.writeAll(s.name); if (first) { @@ -608,8 +625,10 @@ fn workerMakeOneStep( const stderr = std.io.getStdErr(); for (s.result_error_msgs.items) |msg| { - // TODO print the dep prefix too + // Sometimes it feels like you just can't catch a break. Finally, + // with Zig, you can. ttyconf.setColor(stderr, .Bold) catch break; + stderr.writeAll(s.owner.dep_prefix) catch break; stderr.writeAll(s.name) catch break; stderr.writeAll(": ") catch break; ttyconf.setColor(stderr, .Red) catch break; @@ -735,6 +754,8 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi \\Advanced Options: \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error \\ -fno-reference-trace Disable reference trace + \\ -fsummary Print the build summary, even on success + \\ -fno-summary Omit the build summary, even on failure \\ --build-file [file] Override path to build.zig \\ --cache-dir [path] Override path to local Zig cache directory \\ --global-cache-dir [path] Override path to global Zig cache directory |
