From 989b6a1b93e0a8be6b519c4b7fae4d0e41f26b60 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 6 May 2026 09:00:12 +0100 Subject: [PATCH] std.Build: clear step inputs when resetting the step Previously, when using `zig build -fincremental --watch some-run-step`, if the binary initially builds fine but a future update introduces a compile error, the old file system inputs of the `Step.Run`---containing the executable file itself---would remain. This is a bug, because that file *has* changed since the input was registered (due to incremental compilation), and yet the `Run` step is not out-of-date because it was skipped due to a transitive failure. A simple reproduction for this issue was: $ zig init $ zig build test --watch -fincremental Then, in another terminal, introduce a compile error: $ sed -i 's/const/onst/' src/main.zig Before this commit, this would cause the `zig build` command to repeat updates forever, separated only by the 50ms debounce interval. To fix this, when we reset a step with intent to re-run it, we should clear its inputs immediately, so that if the step is skipped, it is correctly marked as having no inputs. This relates to a more general problem with the file system watching logic which is that the set of inputs includes files in the cache which are actually artifacts of other steps. Eventually, the build system should learn to identify such files and exclude them from the set of file system inputs. In other words, the fact that a `Run` step depends on the executable generated by a `Compile` step should be modeled by a dependency in the build step graph, *not* by a dependency on the path where the `Compile` step happens to have emitted its executable file. --- lib/std/Build/Step.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 773706d39ae12c07c067f5600a87b1f15a0f7600..51c1514f8597790dd8c02f53eae2e23dd9a26fd7 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -981,6 +981,7 @@ pub fn reset(step: *Step, gpa: Allocator) void { step.result_peak_rss = 0; step.result_failed_command = null; step.test_results = .{}; + step.clearWatchInputs(); step.result_error_bundle.deinit(gpa); step.result_error_bundle = std.zig.ErrorBundle.empty; -- 2.54.0