human review: build.zig and build/

This commit is contained in:
Emil Lerch 2026-09-24 07:01:14 -07:00
parent 64c80e5797
commit a0c0a8365d
Signed by: lobo
GPG key ID: A7B62D657EF764F8
3 changed files with 36 additions and 18 deletions

View file

@ -675,10 +675,10 @@ Remaining subcommands deferred until their engine modules exist.
per-section height gating silently dropped the Convert section once Financial per-section height gating silently dropped the Convert section once Financial
was added above it, which a render test caught was added above it, which a render test caught
- Coverage now measured for the CLI and TUI, not just the engine (NFR-5): three - Coverage now measured for the CLI and TUI, not just the engine (NFR-5): three
reports with disjoint include paths. `Coverage.addModule` takes include paths reports with disjoint include paths. The coverage helper takes include paths
instead of hardcoding `engine/src`, resolved to absolute paths because the instead of hardcoding `engine/src`, resolved to absolute paths because the
substring form matched any home directory containing `/src/` substring form matched any home directory containing `/src/`
- TUI coverage went from unmeasured (the view modules had literally zero - TUI coverage went from unmeasured (the view files had literally zero
instrumented lines) to 98.91%, via the render harness in instrumented lines) to 98.91%, via the render harness in
`src/tui/test_render.zig` and event tests through the real handlers `src/tui/test_render.zig` and event tests through the real handlers
- Verify: 811 tests, engine 99.30%, CLI 95.74%, TUI 98.91%; frames inspected for - Verify: 811 tests, engine 99.30%, CLI 95.74%, TUI 98.91%; frames inspected for
@ -914,6 +914,25 @@ plans a `--raw` flag, but today it is exercised only by tests.
100% line coverage, engine 99.44%. CLI output byte-identical across all five rows, 100% line coverage, engine 99.44%. CLI output byte-identical across all five rows,
both byte orders, ASCII packing and the multi-base standard-mode view. both byte orders, ASCII packing and the multi-base standard-mode view.
### Task 5.29: One word, and the name it was hiding in
Entry 17 covered `build.zig`, `build/Coverage.zig` and `build/download_kcov.zig`, and
found nothing to change in what they do. The only fix is vocabulary, and it went one
level deeper than a comment.
`Coverage.addModule` did not add anything of the sort: it builds a test executable from
a root and registers a kcov run plus a threshold check over it. What it adds is a
report, so it is `addReport` now, its `root_module` parameter is `root`, and the three
call sites in `build.zig` read `cov.addReport(engine_cov, "tally-engine", ...)`. Two
doc comments that described reports as modules were reworded to say reports, and
`build.zig`'s header comment above the engine now names the engine.
`b.addModule` and `root_module` in the `addTest` call stay: those are Zig's own API,
not ours to rename.
- Verify: 942 tests pass, fmt and zlint clean, `zig build coverage` still produces all
three reports (98.87% for the CLI on that run, with the engine and TUI unchanged).
### Task 5.28: The views stop drawing what they cannot fit ### Task 5.28: The views stop drawing what they cannot fit
Entry 16 covered the five view files. The common fault was the same one Task 5.27 Entry 16 covered the five view files. The common fault was the same one Task 5.27

View file

@ -5,7 +5,7 @@ pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
// -- Engine module (the calculation library) -- // -- The engine: the calculation library every frontend imports --
const engine_mod = b.addModule("engine", .{ const engine_mod = b.addModule("engine", .{
.root_source_file = b.path("engine/src/engine.zig"), .root_source_file = b.path("engine/src/engine.zig"),
.target = target, .target = target,
@ -116,7 +116,7 @@ pub fn build(b: *std.Build) void {
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); });
_ = cov.addModule(engine_cov, "tally-engine", &.{"engine/src"}); _ = cov.addReport(engine_cov, "tally-engine", &.{"engine/src"});
const cli_cov = b.createModule(.{ const cli_cov = b.createModule(.{
.root_source_file = b.path("src/main.zig"), .root_source_file = b.path("src/main.zig"),
@ -127,7 +127,7 @@ pub fn build(b: *std.Build) void {
.{ .name = "vaxis", .module = vaxis_dep.module("vaxis") }, .{ .name = "vaxis", .module = vaxis_dep.module("vaxis") },
}, },
}); });
_ = cov.addModule(cli_cov, "tally-cli", &.{ "src/main.zig", "src/cli" }); _ = cov.addReport(cli_cov, "tally-cli", &.{ "src/main.zig", "src/cli" });
const tui_cov = b.createModule(.{ const tui_cov = b.createModule(.{
.root_source_file = b.path("src/tui.zig"), .root_source_file = b.path("src/tui.zig"),
@ -141,7 +141,7 @@ pub fn build(b: *std.Build) void {
// tui.zig plus its views. main.zig and src/cli are deliberately excluded // tui.zig plus its views. main.zig and src/cli are deliberately excluded
// even though they are not compiled into this binary, so the two app reports // even though they are not compiled into this binary, so the two app reports
// stay disjoint by construction rather than by accident. // stay disjoint by construction rather than by accident.
_ = cov.addModule(tui_cov, "tally-tui", &.{ "src/tui.zig", "src/tui" }); _ = cov.addReport(tui_cov, "tally-tui", &.{ "src/tui.zig", "src/tui" });
} }
// -- Run step -- // -- Run step --

View file

@ -11,12 +11,11 @@ const Coverage = @This();
/// ///
/// Use `zig build coverage --verbose` to see per-file coverage breakdown. /// Use `zig build coverage --verbose` to see per-file coverage breakdown.
/// ///
/// Call `addModule()` on the returned value to add the test module to the /// Call `addReport()` on the returned value to add a test binary to the coverage
/// coverage run. /// run.
/// ///
/// Because addModule creates a new test executable from the root module provided, /// Because `addReport` creates a new test executable from the root it is given, any
/// if there are any linking steps being done to your test executable, those /// linking steps your tests need must also be applied to the executable it returns.
/// must also be done to the test_exe returned by addModule.
pub fn init(b: *Build) Coverage { pub fn init(b: *Build) Coverage {
const coverage_threshold = b.option(u7, "coverage-threshold", "Minimum coverage percentage required") orelse 0; const coverage_threshold = b.option(u7, "coverage-threshold", "Minimum coverage percentage required") orelse 0;
const coverage_dir = b.option([]const u8, "coverage-dir", "Coverage output directory") orelse const coverage_dir = b.option([]const u8, "coverage-dir", "Coverage output directory") orelse
@ -66,13 +65,13 @@ pub fn init(b: *Build) Coverage {
}; };
} }
/// Add a test module to the coverage run. Runs kcov on the test binary, /// Add a coverage report for one test binary. Runs kcov on it, then reads the
/// then reads the coverage JSON and prints a summary (with per-file /// coverage JSON and prints a summary (with per-file breakdown if --verbose).
/// breakdown if --verbose). Fails if below -Dcoverage-threshold. /// Fails if below -Dcoverage-threshold.
/// ///
/// `include_paths` are paths relative to the build root deciding which sources /// `include_paths` are paths relative to the build root deciding which sources
/// this report accounts for; each may be a directory or a single file. Keep them /// this report accounts for; each may be a directory or a single file. Keep them
/// disjoint across modules: a file appearing in two reports means a query tool has /// disjoint across reports: a file appearing in two means a query tool has
/// to guess which one answers for it, and the wrong guess reports covered lines as /// to guess which one answers for it, and the wrong guess reports covered lines as
/// uncovered. /// uncovered.
/// ///
@ -82,9 +81,9 @@ pub fn init(b: *Build) Coverage {
/// dependency tree). /// dependency tree).
/// ///
/// Returns the test executable so the caller can add any extra linking steps. /// Returns the test executable so the caller can add any extra linking steps.
pub fn addModule( pub fn addReport(
self: *Coverage, self: *Coverage,
root_module: *Build.Module, root: *Build.Module,
name: []const u8, name: []const u8,
include_paths: []const []const u8, include_paths: []const []const u8,
) *Build.Step.Compile { ) *Build.Step.Compile {
@ -103,7 +102,7 @@ pub fn addModule(
const test_exe = b.addTest(.{ const test_exe = b.addTest(.{
.name = name, .name = name,
.root_module = root_module, .root_module = root,
.use_llvm = true, .use_llvm = true,
}); });
run_coverage.addArtifactArg(test_exe); run_coverage.addArtifactArg(test_exe);