authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-01 13:44:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:13-07:00
log1bcf674a4390ee238bc63477d3db545dbf7f66dd
treec30e20edc65fcd3475786c273a13cc53dcd3a640
parentb5baa41077dce5ef61667e76d80835c0792a2fc4

build runner: make step_stack a map to remove redundant steps

This prevents compilation errors from being emitted twice.

1 files changed, 27 insertions(+), 25 deletions(-)

lib/build_runner.zig+27-25
...@@ -22,10 +22,9 @@ pub fn main() !void {...@@ -22,10 +22,9 @@ pub fn main() !void {
22 var thread_safe_arena: std.heap.ThreadSafeAllocator = .{22 var thread_safe_arena: std.heap.ThreadSafeAllocator = .{
23 .child_allocator = single_threaded_arena.allocator(),23 .child_allocator = single_threaded_arena.allocator(),
24 };24 };
25 const allocator = thread_safe_arena.allocator();25 const arena = thread_safe_arena.allocator();
2626
27 var args = try process.argsAlloc(allocator);27 var args = try process.argsAlloc(arena);
28 defer process.argsFree(allocator, args);
2928
30 // skip my own exe name29 // skip my own exe name
31 var arg_idx: usize = 1;30 var arg_idx: usize = 1;
...@@ -65,7 +64,7 @@ pub fn main() !void {...@@ -65,7 +64,7 @@ pub fn main() !void {
65 };64 };
6665
67 var cache: std.Build.Cache = .{66 var cache: std.Build.Cache = .{
68 .gpa = allocator,67 .gpa = arena,
69 .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}),68 .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}),
70 };69 };
71 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });70 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
...@@ -75,7 +74,7 @@ pub fn main() !void {...@@ -75,7 +74,7 @@ pub fn main() !void {
75 cache.hash.addBytes(builtin.zig_version_string);74 cache.hash.addBytes(builtin.zig_version_string);
7675
77 const builder = try std.Build.create(76 const builder = try std.Build.create(
78 allocator,77 arena,
79 zig_exe,78 zig_exe,
80 build_root_directory,79 build_root_directory,
81 local_cache_directory,80 local_cache_directory,
...@@ -85,9 +84,9 @@ pub fn main() !void {...@@ -85,9 +84,9 @@ pub fn main() !void {
85 );84 );
86 defer builder.destroy();85 defer builder.destroy();
8786
88 var targets = ArrayList([]const u8).init(allocator);87 var targets = ArrayList([]const u8).init(arena);
89 var debug_log_scopes = ArrayList([]const u8).init(allocator);88 var debug_log_scopes = ArrayList([]const u8).init(arena);
90 var thread_pool_options: std.Thread.Pool.Options = .{ .allocator = allocator };89 var thread_pool_options: std.Thread.Pool.Options = .{ .allocator = arena };
9190
92 const stderr_stream = io.getStdErr().writer();91 const stderr_stream = io.getStdErr().writer();
93 const stdout_stream = io.getStdOut().writer();92 const stdout_stream = io.getStdOut().writer();
...@@ -274,6 +273,7 @@ pub fn main() !void {...@@ -274,6 +273,7 @@ pub fn main() !void {
274 usageAndErr(builder, true, stderr_stream);273 usageAndErr(builder, true, stderr_stream);
275274
276 runStepNames(275 runStepNames(
276 arena,
277 builder,277 builder,
278 targets.items,278 targets.items,
279 main_progress_node,279 main_progress_node,
...@@ -286,30 +286,32 @@ pub fn main() !void {...@@ -286,30 +286,32 @@ pub fn main() !void {
286}286}
287287
288fn runStepNames(288fn runStepNames(
289 arena: std.mem.Allocator,
289 b: *std.Build,290 b: *std.Build,
290 step_names: []const []const u8,291 step_names: []const []const u8,
291 parent_prog_node: *std.Progress.Node,292 parent_prog_node: *std.Progress.Node,
292 thread_pool_options: std.Thread.Pool.Options,293 thread_pool_options: std.Thread.Pool.Options,
293 ttyconf: std.debug.TTY.Config,294 ttyconf: std.debug.TTY.Config,
294) !void {295) !void {
295 var step_stack = ArrayList(*Step).init(b.allocator);296 const gpa = b.allocator;
296 defer step_stack.deinit();297 var step_stack: std.AutoArrayHashMapUnmanaged(*Step, void) = .{};
298 defer step_stack.deinit(gpa);
297299
298 if (step_names.len == 0) {300 if (step_names.len == 0) {
299 try step_stack.append(b.default_step);301 try step_stack.put(gpa, b.default_step, {});
300 } else {302 } else {
301 try step_stack.resize(step_names.len);303 try step_stack.ensureUnusedCapacity(gpa, step_names.len);
302304 for (0..step_names.len) |i| {
303 for (step_names, 0..) |step_name, i| {305 const step_name = step_names[step_names.len - i - 1];
304 const s = b.top_level_steps.get(step_name) orelse {306 const s = b.top_level_steps.get(step_name) orelse {
305 std.debug.print("no step named '{s}'. Access the help menu with 'zig build -h'\n", .{step_name});307 std.debug.print("no step named '{s}'. Access the help menu with 'zig build -h'\n", .{step_name});
306 process.exit(1);308 process.exit(1);
307 };309 };
308 step_stack.items[step_names.len - i - 1] = &s.step;310 step_stack.putAssumeCapacity(&s.step, {});
309 }311 }
310 }312 }
311313
312 const starting_steps = try b.allocator.dupe(*Step, step_stack.items);314 const starting_steps = try arena.dupe(*Step, step_stack.keys());
313 for (starting_steps) |s| {315 for (starting_steps) |s| {
314 checkForDependencyLoop(b, s, &step_stack) catch |err| switch (err) {316 checkForDependencyLoop(b, s, &step_stack) catch |err| switch (err) {
315 error.DependencyLoopDetected => return error.UncleanExit,317 error.DependencyLoopDetected => return error.UncleanExit,
...@@ -324,7 +326,7 @@ fn runStepNames(...@@ -324,7 +326,7 @@ fn runStepNames(
324 {326 {
325 defer parent_prog_node.end();327 defer parent_prog_node.end();
326328
327 var step_prog = parent_prog_node.start("run steps", step_stack.items.len);329 var step_prog = parent_prog_node.start("run steps", step_stack.count());
328 defer step_prog.end();330 defer step_prog.end();
329331
330 var wait_group: std.Thread.WaitGroup = .{};332 var wait_group: std.Thread.WaitGroup = .{};
...@@ -333,10 +335,9 @@ fn runStepNames(...@@ -333,10 +335,9 @@ fn runStepNames(
333 // Here we spawn the initial set of tasks with a nice heuristic -335 // Here we spawn the initial set of tasks with a nice heuristic -
334 // dependency order. Each worker when it finishes a step will then336 // dependency order. Each worker when it finishes a step will then
335 // check whether it should run any dependants.337 // check whether it should run any dependants.
336 var i = step_stack.items.len;338 const steps_slice = step_stack.keys();
337 while (i > 0) {339 for (0..steps_slice.len) |i| {
338 i -= 1;340 const step = steps_slice[steps_slice.len - i - 1];
339 const step = step_stack.items[i];
340341
341 wait_group.start();342 wait_group.start();
342 thread_pool.spawn(workerMakeOneStep, .{343 thread_pool.spawn(workerMakeOneStep, .{
...@@ -350,7 +351,7 @@ fn runStepNames(...@@ -350,7 +351,7 @@ fn runStepNames(
350 var pending_count: usize = 0;351 var pending_count: usize = 0;
351 var total_compile_errors: usize = 0;352 var total_compile_errors: usize = 0;
352353
353 for (step_stack.items) |s| {354 for (step_stack.keys()) |s| {
354 switch (s.state) {355 switch (s.state) {
355 .precheck_unstarted => unreachable,356 .precheck_unstarted => unreachable,
356 .precheck_started => unreachable,357 .precheck_started => unreachable,
...@@ -404,7 +405,7 @@ fn runStepNames(...@@ -404,7 +405,7 @@ fn runStepNames(
404405
405 // Finally, render compile errors at the bottom of the terminal.406 // Finally, render compile errors at the bottom of the terminal.
406 if (total_compile_errors > 0) {407 if (total_compile_errors > 0) {
407 for (step_stack.items) |s| {408 for (step_stack.keys()) |s| {
408 if (s.result_error_bundle.errorMessageCount() > 0) {409 if (s.result_error_bundle.errorMessageCount() > 0) {
409 s.result_error_bundle.renderToStdErr(ttyconf);410 s.result_error_bundle.renderToStdErr(ttyconf);
410 }411 }
...@@ -498,7 +499,7 @@ fn printTreeStep(...@@ -498,7 +499,7 @@ fn printTreeStep(
498fn checkForDependencyLoop(499fn checkForDependencyLoop(
499 b: *std.Build,500 b: *std.Build,
500 s: *Step,501 s: *Step,
501 step_stack: *ArrayList(*Step),502 step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void),
502) !void {503) !void {
503 switch (s.state) {504 switch (s.state) {
504 .precheck_started => {505 .precheck_started => {
...@@ -508,8 +509,9 @@ fn checkForDependencyLoop(...@@ -508,8 +509,9 @@ fn checkForDependencyLoop(
508 .precheck_unstarted => {509 .precheck_unstarted => {
509 s.state = .precheck_started;510 s.state = .precheck_started;
510511
512 try step_stack.ensureUnusedCapacity(b.allocator, s.dependencies.items.len);
511 for (s.dependencies.items) |dep| {513 for (s.dependencies.items) |dep| {
512 try step_stack.append(dep);514 try step_stack.put(b.allocator, dep, {});
513 try dep.dependants.append(b.allocator, s);515 try dep.dependants.append(b.allocator, s);
514 checkForDependencyLoop(b, dep, step_stack) catch |err| {516 checkForDependencyLoop(b, dep, step_stack) catch |err| {
515 if (err == error.DependencyLoopDetected) {517 if (err == error.DependencyLoopDetected) {