authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-23 21:17:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-25 18:52:21-07:00
log711ed56ce361fd9051fcf6039de48022b8dbc2d1
tree856a966ec867171cff804e7a09f8184ca6c3cb9e
parent047640383e5e635ffe52ab360e03dbe08e73d025

build runner: extract logic to std.Build.Fuzz


4 files changed, 53 insertions(+), 38 deletions(-)

lib/compiler/build_runner.zig+2-38
...@@ -9,6 +9,7 @@ const ArrayList = std.ArrayList;...@@ -9,6 +9,7 @@ const ArrayList = std.ArrayList;
9const File = std.fs.File;9const File = std.fs.File;
10const Step = std.Build.Step;10const Step = std.Build.Step;
11const Watch = std.Build.Watch;11const Watch = std.Build.Watch;
12const Fuzz = std.Build.Fuzz;
12const Allocator = std.mem.Allocator;13const Allocator = std.mem.Allocator;
13const fatal = std.process.fatal;14const fatal = std.process.fatal;
14const runner = @This();15const runner = @This();
...@@ -400,7 +401,7 @@ pub fn main() !void {...@@ -400,7 +401,7 @@ pub fn main() !void {
400 else => return err,401 else => return err,
401 };402 };
402 if (fuzz) {403 if (fuzz) {
403 startFuzzing(&run.thread_pool, run.step_stack.keys(), main_progress_node);404 Fuzz.start(&run.thread_pool, run.step_stack.keys(), main_progress_node);
404 }405 }
405406
406 if (!watch) return cleanExit();407 if (!watch) return cleanExit();
...@@ -439,43 +440,6 @@ pub fn main() !void {...@@ -439,43 +440,6 @@ pub fn main() !void {
439 }440 }
440}441}
441442
442fn startFuzzing(thread_pool: *std.Thread.Pool, all_steps: []const *Step, prog_node: std.Progress.Node) void {
443 {
444 const rebuild_node = prog_node.start("Rebuilding Unit Tests", 0);
445 defer rebuild_node.end();
446 var count: usize = 0;
447 var wait_group: std.Thread.WaitGroup = .{};
448 defer wait_group.wait();
449 for (all_steps) |step| {
450 const run = step.cast(Step.Run) orelse continue;
451 if (run.fuzz_tests.items.len > 0 and run.producer != null) {
452 thread_pool.spawnWg(&wait_group, rebuildTestsWorkerRun, .{ run, prog_node });
453 count += 1;
454 }
455 }
456 if (count == 0) {
457 std.debug.lockStdErr();
458 std.debug.print("no fuzz tests found\n", .{});
459 process.exit(2);
460 }
461 rebuild_node.setEstimatedTotalItems(count);
462 }
463 @panic("TODO do something with the rebuilt unit tests");
464}
465
466fn rebuildTestsWorkerRun(run: *Step.Run, parent_prog_node: std.Progress.Node) void {
467 const compile_step = run.producer.?;
468 const prog_node = parent_prog_node.start(compile_step.step.name, 0);
469 defer prog_node.end();
470 const rebuilt_bin_path = compile_step.rebuildInFuzzMode(prog_node) catch |err| {
471 std.debug.print("failed to rebuild {s} in fuzz mode: {s}", .{
472 compile_step.step.name, @errorName(err),
473 });
474 return;
475 };
476 std.debug.print("rebuilt binary: '{s}'\n", .{rebuilt_bin_path});
477}
478
479fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void {443fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void {
480 for (all_steps) |step| switch (step.state) {444 for (all_steps) |step| switch (step.state) {
481 .dependency_failure, .failure, .skipped => step.recursiveReset(gpa),445 .dependency_failure, .failure, .skipped => step.recursiveReset(gpa),
lib/std/Build.zig+1
...@@ -21,6 +21,7 @@ pub const Cache = @import("Build/Cache.zig");...@@ -21,6 +21,7 @@ pub const Cache = @import("Build/Cache.zig");
21pub const Step = @import("Build/Step.zig");21pub const Step = @import("Build/Step.zig");
22pub const Module = @import("Build/Module.zig");22pub const Module = @import("Build/Module.zig");
23pub const Watch = @import("Build/Watch.zig");23pub const Watch = @import("Build/Watch.zig");
24pub const Fuzz = @import("Build/Fuzz.zig");
2425
25/// Shared state among all Build instances.26/// Shared state among all Build instances.
26graph: *Graph,27graph: *Graph,
lib/std/Build/Fuzz.zig created+46
...@@ -0,0 +1,46 @@
1const std = @import("../std.zig");
2const Fuzz = @This();
3const Step = std.Build.Step;
4const assert = std.debug.assert;
5const fatal = std.process.fatal;
6
7pub fn start(thread_pool: *std.Thread.Pool, all_steps: []const *Step, prog_node: std.Progress.Node) void {
8 {
9 const rebuild_node = prog_node.start("Rebuilding Unit Tests", 0);
10 defer rebuild_node.end();
11 var count: usize = 0;
12 var wait_group: std.Thread.WaitGroup = .{};
13 defer wait_group.wait();
14 for (all_steps) |step| {
15 const run = step.cast(Step.Run) orelse continue;
16 if (run.fuzz_tests.items.len > 0 and run.producer != null) {
17 thread_pool.spawnWg(&wait_group, rebuildTestsWorkerRun, .{ run, prog_node });
18 count += 1;
19 }
20 }
21 if (count == 0) fatal("no fuzz tests found", .{});
22 rebuild_node.setEstimatedTotalItems(count);
23 }
24
25 // Detect failure.
26 for (all_steps) |step| {
27 const run = step.cast(Step.Run) orelse continue;
28 if (run.fuzz_tests.items.len > 0 and run.rebuilt_executable == null)
29 fatal("one or more unit tests failed to be rebuilt in fuzz mode", .{});
30 }
31
32 @panic("TODO do something with the rebuilt unit tests");
33}
34
35fn rebuildTestsWorkerRun(run: *Step.Run, parent_prog_node: std.Progress.Node) void {
36 const compile_step = run.producer.?;
37 const prog_node = parent_prog_node.start(compile_step.step.name, 0);
38 defer prog_node.end();
39 const rebuilt_bin_path = compile_step.rebuildInFuzzMode(prog_node) catch |err| {
40 std.debug.print("failed to rebuild {s} in fuzz mode: {s}", .{
41 compile_step.step.name, @errorName(err),
42 });
43 return;
44 };
45 run.rebuilt_executable = rebuilt_bin_path;
46}
lib/std/Build/Step/Run.zig+4
...@@ -89,6 +89,9 @@ has_side_effects: bool,...@@ -89,6 +89,9 @@ has_side_effects: bool,
89/// If this is a Zig unit test binary, this tracks the indexes of the unit89/// If this is a Zig unit test binary, this tracks the indexes of the unit
90/// tests that are also fuzz tests.90/// tests that are also fuzz tests.
91fuzz_tests: std.ArrayListUnmanaged(u32),91fuzz_tests: std.ArrayListUnmanaged(u32),
92/// Populated during the fuzz phase if this run step corresponds to a unit test
93/// executable that contains fuzz tests.
94rebuilt_executable: ?[]const u8,
9295
93/// If this Run step was produced by a Compile step, it is tracked here.96/// If this Run step was produced by a Compile step, it is tracked here.
94producer: ?*Step.Compile,97producer: ?*Step.Compile,
...@@ -183,6 +186,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {...@@ -183,6 +186,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {
183 .dep_output_file = null,186 .dep_output_file = null,
184 .has_side_effects = false,187 .has_side_effects = false,
185 .fuzz_tests = .{},188 .fuzz_tests = .{},
189 .rebuilt_executable = null,
186 .producer = null,190 .producer = null,
187 };191 };
188 return run;192 return run;