Commit 0b744d7d67

Andrew Kelley <andrew@ziglang.org>
2023-02-13 21:28:18
build runner: untangle dependency loop checking from making
1 parent c6a895f
Changed files (2)
lib/std/Build/Step.zig
@@ -2,7 +2,8 @@ id: Id,
 name: []const u8,
 makeFn: *const fn (self: *Step) anyerror!void,
 dependencies: std.ArrayList(*Step),
-loop_flag: bool,
+/// Used only during a pre-check for dependency loops.
+loop_tag: enum { unstarted, started, done },
 done_flag: bool,
 
 pub const Id = enum {
@@ -60,7 +61,7 @@ pub fn init(
         .name = allocator.dupe(u8, name) catch @panic("OOM"),
         .makeFn = makeFn,
         .dependencies = std.ArrayList(*Step).init(allocator),
-        .loop_flag = false,
+        .loop_tag = .unstarted,
         .done_flag = false,
     };
 }
lib/build_runner.zig
@@ -274,20 +274,27 @@ fn make(b: *std.Build, step_names: []const []const u8) !void {
         }
     }
 
+    for (wanted_steps.items) |s| {
+        checkForDependencyLoop(b, s) catch |err| switch (err) {
+            error.DependencyLoopDetected => return error.UncleanExit,
+            else => |e| return e,
+        };
+    }
+
     for (wanted_steps.items) |s| {
         try makeOneStep(b, s);
     }
 }
 
-fn makeOneStep(b: *std.Build, s: *std.Build.Step) anyerror!void {
-    if (s.loop_flag) {
+fn checkForDependencyLoop(b: *std.Build, s: *std.Build.Step) !void {
+    if (s.loop_tag == .started) {
         std.debug.print("dependency loop detected:\n  {s}\n", .{s.name});
         return error.DependencyLoopDetected;
     }
-    s.loop_flag = true;
+    s.loop_tag = .started;
 
     for (s.dependencies.items) |dep| {
-        makeOneStep(b, dep) catch |err| {
+        checkForDependencyLoop(b, dep) catch |err| {
             if (err == error.DependencyLoopDetected) {
                 std.debug.print("  {s}\n", .{s.name});
             }
@@ -295,7 +302,13 @@ fn makeOneStep(b: *std.Build, s: *std.Build.Step) anyerror!void {
         };
     }
 
-    s.loop_flag = false;
+    s.loop_tag = .done;
+}
+
+fn makeOneStep(b: *std.Build, s: *std.Build.Step) anyerror!void {
+    for (s.dependencies.items) |dep| {
+        try makeOneStep(b, dep);
+    }
 
     try s.make();
 }