Commit 0cc492a272

Andrew Kelley <andrew@ziglang.org>
2024-07-10 06:08:20
make more build steps integrate with the watch system
1 parent 956f1eb
lib/std/Build/Step/CheckFile.zig
@@ -50,6 +50,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
     _ = prog_node;
     const b = step.owner;
     const check_file: *CheckFile = @fieldParentPtr("step", step);
+    try step.singleUnchangingWatchInput(check_file.source);
 
     const src_path = check_file.source.getPath2(b, step);
     const contents = fs.cwd().readFileAlloc(b.allocator, src_path, check_file.max_bytes) catch |err| {
lib/std/Build/Step/CheckObject.zig
@@ -555,6 +555,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
     const b = step.owner;
     const gpa = b.allocator;
     const check_object: *CheckObject = @fieldParentPtr("step", step);
+    try step.singleUnchangingWatchInput(check_object.source);
 
     const src_path = check_object.source.getPath2(b, step);
     const contents = fs.cwd().readFileAllocOptions(
lib/std/Build/Step/ConfigHeader.zig
@@ -168,6 +168,8 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
     _ = prog_node;
     const b = step.owner;
     const config_header: *ConfigHeader = @fieldParentPtr("step", step);
+    if (config_header.style.getPath()) |lp| try step.singleUnchangingWatchInput(lp);
+
     const gpa = b.allocator;
     const arena = b.allocator;
 
lib/std/Build/Step/InstallFile.zig
@@ -39,9 +39,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
     _ = prog_node;
     const b = step.owner;
     const install_file: *InstallFile = @fieldParentPtr("step", step);
-
-    // Inputs never change when re-running `make`.
-    if (!step.inputs.populated()) step.addWatchInput(install_file.source);
+    try step.singleUnchangingWatchInput(install_file.source);
 
     const full_src_path = install_file.source.getPath2(b, step);
     const full_dest_path = b.getInstallPath(install_file.dir, install_file.dest_rel_path);
lib/std/Build/Step/ObjCopy.zig
@@ -93,6 +93,7 @@ pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath {
 fn make(step: *Step, prog_node: std.Progress.Node) !void {
     const b = step.owner;
     const objcopy: *ObjCopy = @fieldParentPtr("step", step);
+    try step.singleUnchangingWatchInput(objcopy.input_file);
 
     var man = b.graph.cache.obtain();
     defer man.deinit();
lib/std/Build/Step/Options.zig
@@ -424,6 +424,9 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
             item.path.getPath2(b, step),
         );
     }
+    if (!step.inputs.populated()) for (options.args.items) |item| {
+        try step.addWatchInput(item.path);
+    };
 
     const basename = "options.zig";
 
lib/std/Build/Step/RemoveDir.zig
@@ -2,22 +2,23 @@ const std = @import("std");
 const fs = std.fs;
 const Step = std.Build.Step;
 const RemoveDir = @This();
+const LazyPath = std.Build.LazyPath;
 
 pub const base_id: Step.Id = .remove_dir;
 
 step: Step,
-dir_path: []const u8,
+doomed_path: LazyPath,
 
-pub fn create(owner: *std.Build, dir_path: []const u8) *RemoveDir {
+pub fn create(owner: *std.Build, doomed_path: LazyPath) *RemoveDir {
     const remove_dir = owner.allocator.create(RemoveDir) catch @panic("OOM");
     remove_dir.* = .{
         .step = Step.init(.{
             .id = base_id,
-            .name = owner.fmt("RemoveDir {s}", .{dir_path}),
+            .name = owner.fmt("RemoveDir {s}", .{doomed_path.getDisplayName()}),
             .owner = owner,
             .makeFn = make,
         }),
-        .dir_path = owner.dupePath(dir_path),
+        .doomed_path = doomed_path.dupe(owner),
     };
     return remove_dir;
 }
@@ -30,14 +31,19 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
     const b = step.owner;
     const remove_dir: *RemoveDir = @fieldParentPtr("step", step);
 
-    b.build_root.handle.deleteTree(remove_dir.dir_path) catch |err| {
+    step.clearWatchInputs();
+    try step.addWatchInput(remove_dir.doomed_path);
+
+    const full_doomed_path = remove_dir.doomed_path.getPath2(b, step);
+
+    b.build_root.handle.deleteTree(full_doomed_path) catch |err| {
         if (b.build_root.path) |base| {
             return step.fail("unable to recursively delete path '{s}/{s}': {s}", .{
-                base, remove_dir.dir_path, @errorName(err),
+                base, full_doomed_path, @errorName(err),
             });
         } else {
             return step.fail("unable to recursively delete path '{s}': {s}", .{
-                remove_dir.dir_path, @errorName(err),
+                full_doomed_path, @errorName(err),
             });
         }
     };
lib/std/Build/Step.zig
@@ -598,14 +598,17 @@ pub fn writeManifest(s: *Step, man: *Build.Cache.Manifest) !void {
     }
 }
 
-fn oom(err: anytype) noreturn {
-    switch (err) {
-        error.OutOfMemory => @panic("out of memory"),
-    }
+/// For steps that have a single input that never changes when re-running `make`.
+pub fn singleUnchangingWatchInput(step: *Step, lazy_path: Build.LazyPath) Allocator.Error!void {
+    if (!step.inputs.populated()) try step.addWatchInput(lazy_path);
+}
+
+pub fn clearWatchInputs(step: *Step) void {
+    const gpa = step.owner.allocator;
+    step.inputs.clear(gpa);
 }
 
-pub fn addWatchInput(step: *Step, lazy_path: Build.LazyPath) void {
-    errdefer |err| oom(err);
+pub fn addWatchInput(step: *Step, lazy_path: Build.LazyPath) Allocator.Error!void {
     switch (lazy_path) {
         .src_path => |src_path| try addWatchInputFromBuilder(step, src_path.owner, src_path.sub_path),
         .dependency => |d| try addWatchInputFromBuilder(step, d.dependency.builder, d.sub_path),
lib/std/Build.zig
@@ -1052,7 +1052,7 @@ pub fn addWriteFiles(b: *Build) *Step.WriteFile {
     return Step.WriteFile.create(b);
 }
 
-pub fn addRemoveDirTree(b: *Build, dir_path: []const u8) *Step.RemoveDir {
+pub fn addRemoveDirTree(b: *Build, dir_path: LazyPath) *Step.RemoveDir {
     return Step.RemoveDir.create(b, dir_path);
 }
 
test/tests.zig
@@ -771,7 +771,7 @@ pub fn addCliTests(b: *std.Build) *Step {
         run_run.expectStdErrEqual("All your codebase are belong to us.\n");
         run_run.step.dependOn(&init_exe.step);
 
-        const cleanup = b.addRemoveDirTree(tmp_path);
+        const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
         cleanup.step.dependOn(&run_test.step);
         cleanup.step.dependOn(&run_run.step);
         cleanup.step.dependOn(&run_bad.step);
@@ -816,7 +816,7 @@ pub fn addCliTests(b: *std.Build) *Step {
         });
         checkfile.setName("check godbolt.org CLI usage generating valid asm");
 
-        const cleanup = b.addRemoveDirTree(tmp_path);
+        const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
         cleanup.step.dependOn(&checkfile.step);
 
         step.dependOn(&cleanup.step);
@@ -902,7 +902,7 @@ pub fn addCliTests(b: *std.Build) *Step {
         });
         check6.step.dependOn(&run6.step);
 
-        const cleanup = b.addRemoveDirTree(tmp_path);
+        const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
         cleanup.step.dependOn(&check6.step);
 
         step.dependOn(&cleanup.step);