Commit ad72172293

Jacob Young <jacobly0@users.noreply.github.com>
2024-05-13 05:09:40
Build.Step.Run: fix cache management when there are side effects
Closes #19947
1 parent 6574424
Changed files (2)
lib
std
Build
lib/std/Build/Step/Run.zig
@@ -659,7 +659,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
         _ = try man.addFile(lazy_path.getPath2(b, step), null);
     }
 
-    if (try step.cacheHit(&man) and !has_side_effects) {
+    if (!has_side_effects and try step.cacheHit(&man)) {
         // cache hit, skip running command
         const digest = man.final();
 
@@ -678,7 +678,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
 
     const dep_output_file = run.dep_output_file orelse {
         // We already know the final output paths, use them directly.
-        const digest = man.final();
+        const digest = if (has_side_effects)
+            man.hash.final()
+        else
+            man.final();
 
         try populateGeneratedPaths(
             arena,
@@ -710,7 +713,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
         }
 
         try runCommand(run, argv_list.items, has_side_effects, output_dir_path, prog_node);
-        try step.writeManifest(&man);
+        if (!has_side_effects) try step.writeManifest(&man);
         return;
     };
 
@@ -741,9 +744,17 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
 
     try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, prog_node);
 
-    try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath());
+    const dep_file_dir = std.fs.cwd();
+    const dep_file_basename = dep_output_file.generated_file.getPath();
+    if (has_side_effects)
+        try man.addDepFile(dep_file_dir, dep_file_basename)
+    else
+        try man.addDepFilePost(dep_file_dir, dep_file_basename);
 
-    const digest = man.final();
+    const digest = if (has_side_effects)
+        man.hash.final()
+    else
+        man.final();
 
     const any_output = output_placeholders.items.len > 0 or
         run.captured_stdout != null or run.captured_stderr != null;
@@ -778,7 +789,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
         };
     }
 
-    try step.writeManifest(&man);
+    if (!has_side_effects) try step.writeManifest(&man);
 
     try populateGeneratedPaths(
         arena,
lib/std/Build/Cache.zig
@@ -397,6 +397,11 @@ pub const Manifest = struct {
         }
     }
 
+    pub fn addDepFile(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
+        assert(self.manifest_file == null);
+        return self.addDepFileMaybePost(dir, dep_file_basename);
+    }
+
     /// Check the cache to see if the input exists in it. If it exists, returns `true`.
     /// A hex encoding of its hash is available by calling `final`.
     ///
@@ -843,7 +848,10 @@ pub const Manifest = struct {
 
     pub fn addDepFilePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
         assert(self.manifest_file != null);
+        return self.addDepFileMaybePost(dir, dep_file_basename);
+    }
 
+    fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
         const dep_file_contents = try dir.readFileAlloc(self.cache.gpa, dep_file_basename, manifest_file_size_max);
         defer self.cache.gpa.free(dep_file_contents);
 
@@ -857,7 +865,9 @@ pub const Manifest = struct {
                 // We don't care about targets, we only want the prereqs
                 // Clang is invoked in single-source mode but other programs may not
                 .target, .target_must_resolve => {},
-                .prereq => |file_path| try self.addFilePost(file_path),
+                .prereq => |file_path| if (self.manifest_file == null) {
+                    _ = try self.addFile(file_path, null);
+                } else try self.addFilePost(file_path),
                 else => |err| {
                     try err.printError(error_buf.writer());
                     log.err("failed parsing {s}: {s}", .{ dep_file_basename, error_buf.items });