authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-02 13:39:37+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-03 15:45:11+00:00
log4de33579d8d8fdf310cd1a496eb68a7c5c62d81f
tree9ddb96b16c8d6f7ffb141e9d7792f07274c0f8c7
parentb3c498454b6006f64aecf96b181720c524d76ae8
signaturelock-open Commit is signed but in an unrecognized format.

incr-check: make sure to always show the target

Change the log implementation to prepend the current target and update to all logs which happen during an update. Makes progress on https://github.com/ziglang/zig/issues/22510, but does not fully resolve it.

1 files changed, 51 insertions(+), 43 deletions(-)

tools/incr-check.zig+51-43
...@@ -6,6 +6,27 @@ const Cache = std.Build.Cache;...@@ -6,6 +6,27 @@ const Cache = std.Build.Cache;
66
7const usage = "usage: incr-check <zig binary path> <input file> [--zig-lib-dir lib] [--debug-log foo] [--preserve-tmp] [--zig-cc-binary /path/to/zig]";7const usage = "usage: incr-check <zig binary path> <input file> [--zig-lib-dir lib] [--debug-log foo] [--preserve-tmp] [--zig-cc-binary /path/to/zig]";
88
9pub const std_options: std.Options = .{
10 .logFn = logImpl,
11};
12var log_cur_update: ?struct { *const Case.Target, *const Case.Update } = null;
13fn logImpl(
14 comptime level: std.log.Level,
15 comptime scope: @EnumLiteral(),
16 comptime format: []const u8,
17 args: anytype,
18) void {
19 const target, const update = log_cur_update orelse {
20 return std.log.defaultLog(level, scope, format, args);
21 };
22 std.log.defaultLog(
23 level,
24 scope,
25 "[{s}-{t} '{s}'] " ++ format,
26 .{ target.query, target.backend, update.name } ++ args,
27 );
28}
29
9pub fn main() !void {30pub fn main() !void {
10 const fatal = std.process.fatal;31 const fatal = std.process.fatal;
1132
...@@ -225,6 +246,9 @@ pub fn main() !void {...@@ -225,6 +246,9 @@ pub fn main() !void {
225 std.log.scoped(.status).info("update: '{s}'", .{update.name});246 std.log.scoped(.status).info("update: '{s}'", .{update.name});
226 }247 }
227248
249 log_cur_update = .{ &target, &update };
250 defer log_cur_update = null;
251
228 eval.write(update);252 eval.write(update);
229 try eval.requestUpdate();253 try eval.requestUpdate();
230 try eval.check(&poller, update, update_node);254 try eval.check(&poller, update, update_node);
...@@ -295,9 +319,9 @@ const Eval = struct {...@@ -295,9 +319,9 @@ const Eval = struct {
295 if (stderr.bufferedLen() > 0) {319 if (stderr.bufferedLen() > 0) {
296 const stderr_data = try poller.toOwnedSlice(.stderr);320 const stderr_data = try poller.toOwnedSlice(.stderr);
297 if (eval.allow_stderr) {321 if (eval.allow_stderr) {
298 std.log.info("error_bundle included stderr:\n{s}", .{stderr_data});322 std.log.info("error_bundle stderr:\n{s}", .{stderr_data});
299 } else {323 } else {
300 eval.fatal("error_bundle included unexpected stderr:\n{s}", .{stderr_data});324 eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr_data});
301 }325 }
302 }326 }
303 if (result_error_bundle.errorMessageCount() != 0) {327 if (result_error_bundle.errorMessageCount() != 0) {
...@@ -312,9 +336,9 @@ const Eval = struct {...@@ -312,9 +336,9 @@ const Eval = struct {
312 if (stderr.bufferedLen() > 0) {336 if (stderr.bufferedLen() > 0) {
313 const stderr_data = try poller.toOwnedSlice(.stderr);337 const stderr_data = try poller.toOwnedSlice(.stderr);
314 if (eval.allow_stderr) {338 if (eval.allow_stderr) {
315 std.log.info("emit_digest included stderr:\n{s}", .{stderr_data});339 std.log.info("emit_digest stderr:\n{s}", .{stderr_data});
316 } else {340 } else {
317 eval.fatal("emit_digest included unexpected stderr:\n{s}", .{stderr_data});341 eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr_data});
318 }342 }
319 }343 }
320344
...@@ -344,14 +368,14 @@ const Eval = struct {...@@ -344,14 +368,14 @@ const Eval = struct {
344368
345 if (stderr.bufferedLen() > 0) {369 if (stderr.bufferedLen() > 0) {
346 if (eval.allow_stderr) {370 if (eval.allow_stderr) {
347 std.log.info("update '{s}' included stderr:\n{s}", .{ update.name, stderr.buffered() });371 std.log.info("stderr:\n{s}", .{stderr.buffered()});
348 } else {372 } else {
349 eval.fatal("update '{s}' failed:\n{s}", .{ update.name, stderr.buffered() });373 eval.fatal("unexpected stderr:\n{s}", .{stderr.buffered()});
350 }374 }
351 }375 }
352376
353 waitChild(eval.child, eval);377 waitChild(eval.child, eval);
354 eval.fatal("update '{s}': compiler failed to send error_bundle or emit_bin_path", .{update.name});378 eval.fatal("compiler failed to send error_bundle or emit_bin_path", .{});
355 }379 }
356380
357 fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void {381 fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void {
...@@ -361,7 +385,7 @@ const Eval = struct {...@@ -361,7 +385,7 @@ const Eval = struct {
361 .compile_errors => |ce| ce,385 .compile_errors => |ce| ce,
362 .stdout, .exit_code => {386 .stdout, .exit_code => {
363 try error_bundle.renderToStderr(io, .{}, .auto);387 try error_bundle.renderToStderr(io, .{}, .auto);
364 eval.fatal("update '{s}': unexpected compile errors", .{update.name});388 eval.fatal("unexpected compile errors", .{});
365 },389 },
366 };390 };
367391
...@@ -370,30 +394,29 @@ const Eval = struct {...@@ -370,30 +394,29 @@ const Eval = struct {
370 for (error_bundle.getMessages()) |err_idx| {394 for (error_bundle.getMessages()) |err_idx| {
371 if (expected_idx == expected.errors.len) {395 if (expected_idx == expected.errors.len) {
372 try error_bundle.renderToStderr(io, .{}, .auto);396 try error_bundle.renderToStderr(io, .{}, .auto);
373 eval.fatal("update '{s}': more errors than expected", .{update.name});397 eval.fatal("more errors than expected", .{});
374 }398 }
375 try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], false, err_idx);399 try eval.checkOneError(error_bundle, expected.errors[expected_idx], false, err_idx);
376 expected_idx += 1;400 expected_idx += 1;
377401
378 for (error_bundle.getNotes(err_idx)) |note_idx| {402 for (error_bundle.getNotes(err_idx)) |note_idx| {
379 if (expected_idx == expected.errors.len) {403 if (expected_idx == expected.errors.len) {
380 try error_bundle.renderToStderr(io, .{}, .auto);404 try error_bundle.renderToStderr(io, .{}, .auto);
381 eval.fatal("update '{s}': more error notes than expected", .{update.name});405 eval.fatal("more error notes than expected", .{});
382 }406 }
383 try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], true, note_idx);407 try eval.checkOneError(error_bundle, expected.errors[expected_idx], true, note_idx);
384 expected_idx += 1;408 expected_idx += 1;
385 }409 }
386 }410 }
387411
388 if (!std.mem.eql(u8, error_bundle.getCompileLogOutput(), expected.compile_log_output)) {412 if (!std.mem.eql(u8, error_bundle.getCompileLogOutput(), expected.compile_log_output)) {
389 try error_bundle.renderToStderr(io, .{}, .auto);413 try error_bundle.renderToStderr(io, .{}, .auto);
390 eval.fatal("update '{s}': unexpected compile log output", .{update.name});414 eval.fatal("unexpected compile log output", .{});
391 }415 }
392 }416 }
393417
394 fn checkOneError(418 fn checkOneError(
395 eval: *Eval,419 eval: *Eval,
396 update: Case.Update,
397 eb: std.zig.ErrorBundle,420 eb: std.zig.ErrorBundle,
398 expected: Case.ExpectedError,421 expected: Case.ExpectedError,
399 is_note: bool,422 is_note: bool,
...@@ -423,7 +446,7 @@ const Eval = struct {...@@ -423,7 +446,7 @@ const Eval = struct {
423 !std.mem.eql(u8, expected.msg, msg))446 !std.mem.eql(u8, expected.msg, msg))
424 {447 {
425 eb.renderToStderr(io, .{}, .auto) catch {};448 eb.renderToStderr(io, .{}, .auto) catch {};
426 eval.fatal("update '{s}': compile error did not match expected error", .{update.name});449 eval.fatal("compile error did not match expected error", .{});
427 }450 }
428 }451 }
429452
...@@ -444,7 +467,7 @@ const Eval = struct {...@@ -444,7 +467,7 @@ const Eval = struct {
444 .cbe => bin: {467 .cbe => bin: {
445 const rand_int = std.crypto.random.int(u64);468 const rand_int = std.crypto.random.int(u64);
446 const out_bin_name = "./out_" ++ std.fmt.hex(rand_int);469 const out_bin_name = "./out_" ++ std.fmt.hex(rand_int);
447 try eval.buildCOutput(update, emitted_path, out_bin_name, prog_node);470 try eval.buildCOutput(emitted_path, out_bin_name, prog_node);
448 break :bin out_bin_name;471 break :bin out_bin_name;
449 },472 },
450 };473 };
...@@ -521,8 +544,7 @@ const Eval = struct {...@@ -521,8 +544,7 @@ const Eval = struct {
521 if (is_foreign) {544 if (is_foreign) {
522 // Chances are the foreign executor isn't available. Skip this evaluation.545 // Chances are the foreign executor isn't available. Skip this evaluation.
523 if (eval.allow_stderr) {546 if (eval.allow_stderr) {
524 std.log.warn("update '{s}': skipping execution of '{s}' via executor for foreign target '{s}': {t}", .{547 std.log.warn("skipping execution of '{s}' via executor for foreign target '{s}': {t}", .{
525 update.name,
526 binary_path,548 binary_path,
527 try eval.target.resolved.zigTriple(eval.arena),549 try eval.target.resolved.zigTriple(eval.arena),
528 err,550 err,
...@@ -530,16 +552,14 @@ const Eval = struct {...@@ -530,16 +552,14 @@ const Eval = struct {
530 }552 }
531 return;553 return;
532 }554 }
533 eval.fatal("update '{s}': failed to run the generated executable '{s}': {t}", .{555 eval.fatal("failed to run the generated executable '{s}': {t}", .{ binary_path, err });
534 update.name, binary_path, err,
535 });
536 };556 };
537557
538 // Some executors (looking at you, Wine) like throwing some stderr in, just for fun.558 // Some executors (looking at you, Wine) like throwing some stderr in, just for fun.
539 // Therefore, we'll ignore stderr when using a foreign executor.559 // Therefore, we'll ignore stderr when using a foreign executor.
540 if (!is_foreign and result.stderr.len != 0) {560 if (!is_foreign and result.stderr.len != 0) {
541 std.log.err("update '{s}': generated executable '{s}' had unexpected stderr:\n{s}", .{561 std.log.err("generated executable '{s}' had unexpected stderr:\n{s}", .{
542 update.name, binary_path, result.stderr,562 binary_path, result.stderr,
543 });563 });
544 }564 }
545565
...@@ -548,18 +568,14 @@ const Eval = struct {...@@ -548,18 +568,14 @@ const Eval = struct {
548 .unknown, .compile_errors => unreachable,568 .unknown, .compile_errors => unreachable,
549 .stdout => |expected_stdout| {569 .stdout => |expected_stdout| {
550 if (code != 0) {570 if (code != 0) {
551 eval.fatal("update '{s}': generated executable '{s}' failed with code {d}", .{571 eval.fatal("generated executable '{s}' failed with code {d}", .{ binary_path, code });
552 update.name, binary_path, code,
553 });
554 }572 }
555 try std.testing.expectEqualStrings(expected_stdout, result.stdout);573 try std.testing.expectEqualStrings(expected_stdout, result.stdout);
556 },574 },
557 .exit_code => |expected_code| try std.testing.expectEqual(expected_code, result.term.Exited),575 .exit_code => |expected_code| try std.testing.expectEqual(expected_code, result.term.Exited),
558 },576 },
559 .Signal, .Stopped, .Unknown => {577 .Signal, .Stopped, .Unknown => {
560 eval.fatal("update '{s}': generated executable '{s}' terminated unexpectedly", .{578 eval.fatal("generated executable '{s}' terminated unexpectedly", .{binary_path});
561 update.name, binary_path,
562 });
563 },579 },
564 }580 }
565581
...@@ -597,7 +613,7 @@ const Eval = struct {...@@ -597,7 +613,7 @@ const Eval = struct {
597 }613 }
598 }614 }
599615
600 fn buildCOutput(eval: *Eval, update: Case.Update, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void {616 fn buildCOutput(eval: *Eval, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void {
601 std.debug.assert(eval.cc_child_args.items.len > 0);617 std.debug.assert(eval.cc_child_args.items.len > 0);
602618
603 const child_prog_node = prog_node.start("build cbe output", 0);619 const child_prog_node = prog_node.start("build cbe output", 0);
...@@ -612,28 +628,20 @@ const Eval = struct {...@@ -612,28 +628,20 @@ const Eval = struct {
612 .cwd = eval.tmp_dir_path,628 .cwd = eval.tmp_dir_path,
613 .progress_node = child_prog_node,629 .progress_node = child_prog_node,
614 }) catch |err| {630 }) catch |err| {
615 eval.fatal("update '{s}': failed to spawn zig cc for '{s}': {t}", .{ update.name, c_path, err });631 eval.fatal("failed to spawn zig cc for '{s}': {t}", .{ c_path, err });
616 };632 };
617 switch (result.term) {633 switch (result.term) {
618 .Exited => |code| if (code != 0) {634 .Exited => |code| if (code != 0) {
619 if (result.stderr.len != 0) {635 if (result.stderr.len != 0) {
620 std.log.err("update '{s}': zig cc stderr:\n{s}", .{636 std.log.err("zig cc stderr:\n{s}", .{result.stderr});
621 update.name, result.stderr,
622 });
623 }637 }
624 eval.fatal("update '{s}': zig cc for '{s}' failed with code {d}", .{638 eval.fatal("zig cc for '{s}' failed with code {d}", .{ c_path, code });
625 update.name, c_path, code,
626 });
627 },639 },
628 .Signal, .Stopped, .Unknown => {640 .Signal, .Stopped, .Unknown => {
629 if (result.stderr.len != 0) {641 if (result.stderr.len != 0) {
630 std.log.err("update '{s}': zig cc stderr:\n{s}", .{642 std.log.err("zig cc stderr:\n{s}", .{result.stderr});
631 update.name, result.stderr,
632 });
633 }643 }
634 eval.fatal("update '{s}': zig cc for '{s}' terminated unexpectedly", .{644 eval.fatal("zig cc for '{s}' terminated unexpectedly", .{c_path});
635 update.name, c_path,
636 });
637 },645 },
638 }646 }
639 }647 }