From d22231c039ce8f087b2499a97eb769fb800f2000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 5 Dec 2025 10:18:05 +0100 Subject: [PATCH] Compilation: track indirect file system inputs from clang's depfile Co-authored-by: Matthew Lugg --- lib/std/Build/Cache.zig | 2 +- src/Compilation.zig | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index e68c3e7892..5e8412cfcf 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -123,7 +123,7 @@ pub const HexDigest = [hex_digest_len]u8; /// This is currently just an arbitrary non-empty string that can't match another manifest line. const manifest_header = "0"; -const manifest_file_size_max = 100 * 1024 * 1024; +pub const manifest_file_size_max = 100 * 1024 * 1024; /// The type used for hashing file contents. Currently, this is SipHash128(1, 3), because it /// provides enough collision resistance for the Manifest use cases, while being one of our diff --git a/src/Compilation.zig b/src/Compilation.zig index 01ab281c14..1387557738 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6419,6 +6419,38 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr if (out_dep_path) |dep_file_path| { const dep_basename = fs.path.basename(dep_file_path); + + if (comp.file_system_inputs != null) { + // Use the same file size limit as the cache code does for dependency files. + const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(dep_basename, gpa, .limited(Cache.manifest_file_size_max)); + defer gpa.free(dep_file_contents); + + var str_buf: std.ArrayList(u8) = .empty; + defer str_buf.deinit(gpa); + + var it: std.Build.Cache.DepTokenizer = .{ .bytes = dep_file_contents }; + while (it.next()) |token| { + const input_path: Compilation.Path = switch (token) { + .target, .target_must_resolve => continue, + .prereq => |file_path| try .fromUnresolved(arena, comp.dirs, &.{file_path}), + .prereq_must_resolve => p: { + try token.resolve(gpa, &str_buf); + break :p try .fromUnresolved(arena, comp.dirs, &.{str_buf.items}); + }, + else => |err| { + try err.printError(gpa, &str_buf); + log.err("failed parsing {s}: {s}", .{ dep_basename, str_buf.items }); + return error.InvalidDepFile; + }, + }; + + // There may be concurrent calls to `appendFileSystemInput` from other C objects. + comp.mutex.lock(); + defer comp.mutex.unlock(); + try comp.appendFileSystemInput(input_path); + } + } + // Add the files depended on to the cache system. try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); switch (comp.cache_use) {