authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-07 18:18:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-16 13:12:47-07:00
log0334f14a13c0d61c00a767e87499292d13ef2af1
tree7dd39e8e81aa73f5f5f55350557f870a9d05850c
parent5b57dca62d8094d58a21e5458b5095febce47dc5

compiler: update to new std.Build.Cache API


12 files changed, 175 insertions(+), 134 deletions(-)

lib/compiler/Maker.zig+1-1
......@@ -1500,7 +1500,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
15001500 if (config_man) |man| for (configuration.path_deps) |path_dep| {
15011501 const path = try confPathDepToCachePath(arena, graph, &configuration, path_dep);
15021502 try man.addDiscoveredPath(.{
1503 .path = .{ .unresolved = path },
1503 .discovered_path = .{ .unresolved = path },
15041504 .handle = if (path_dep.flags.is_directory) .{ .dir = null } else .{ .file = null },
15051505 .metadata_only = path_dep.flags.metadata_only,
15061506 });
lib/compiler/Maker/Step.zig+1-1
......@@ -753,7 +753,7 @@ fn failWithCacheError(
753753 switch (err) {
754754 error.CacheCheckFailed => switch (man.diagnostic) {
755755 .none => unreachable,
756 .manifest_create, .manifest_read, .manifest_lock => |e| {
756 .manifest_create, .manifest_stat, .manifest_read, .manifest_lock => |e| {
757757 return s.fail(maker, "failed checking cache: {t} {t}", .{ man.diagnostic, e });
758758 },
759759 .file_open, .file_stat, .file_read, .file_hash => |op| {
lib/std/Build/Cache.zig+96-33
......@@ -1104,25 +1104,45 @@ pub const Manifest = struct {
11041104 return timestamp.nanoseconds >= man.recent_problematic_timestamp.nanoseconds;
11051105 }
11061106
1107 pub const AddPathPostOptions = struct {
1108 path: union(enum) {
1109 unresolved: Path,
1110 prefixed: PrefixedPath,
1111 },
1107 pub const AddDiscoveredPathOptions = struct {
1108 discovered_path: DiscoveredPath,
11121109 handle: PathHandle = .{ .file = null },
11131110 stat: ?Stat = null,
11141111 /// If it is a directory, there is a special encoding required for contents, which
11151112 /// is null-separated sorted entries, each one prefixed with `File.Kind`.
11161113 contents: ?[]const u8 = null,
11171114 metadata_only: bool = false,
1115 /// Populated if and only if `error.FileSystemFailure` is returned from `addDiscoveredPath`.
1116 diagnostic: ?*AddDiscoveredPathDiagnostic = null,
1117 };
1118
1119 pub const DiscoveredPath = union(enum) {
1120 unresolved: Path,
1121 prefixed: PrefixedPath,
1122 };
1123
1124 pub const AddDiscoveredPathDiagnostic = union(enum) {
1125 none,
1126 open_file: Io.File.OpenError,
1127 open_dir: Io.Dir.OpenError,
1128 stat_file: Io.File.StatError,
1129 stat_dir: Io.Dir.StatError,
1130 read_file: Io.File.ReadPositionalError,
1131 read_dir: Io.Dir.Reader.Error,
11181132 };
11191133
1134 pub const AddDiscoveredPathError = error{
1135 /// If this is returned, diagnostic will be populated.
1136 /// If contents and stat are both provided, this is unreachable.
1137 FileSystemFailure,
1138 } || Allocator.Error || Io.Cancelable;
1139
11201140 /// Add a file as a dependency of process being cached, after cache miss
11211141 /// occurs.
11221142 ///
11231143 /// See also:
11241144 /// * `addInputPath`
1125 pub fn addDiscoveredPath(m: *Manifest, options: AddPathPostOptions) !void {
1145 pub fn addDiscoveredPath(m: *Manifest, options: AddDiscoveredPathOptions) AddDiscoveredPathError!void {
11261146 assert(m.manifest_file != null);
11271147 const cache = m.cache;
11281148 const gpa = cache.gpa;
......@@ -1135,7 +1155,7 @@ pub const Manifest = struct {
11351155 try m.contents.appendNTimes(gpa, 0, @offsetOf(File, "path_start"));
11361156 errdefer m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset));
11371157
1138 const new_prefix = switch (options.path) {
1158 const new_prefix = switch (options.discovered_path) {
11391159 .unresolved => |unresolved| try cache.resolveAppendPath(&m.contents, unresolved),
11401160 .prefixed => |prefixed| try cache.appendPrefixedPath(&m.contents, prefixed),
11411161 };
......@@ -1184,26 +1204,38 @@ pub const Manifest = struct {
11841204
11851205 switch (options.handle) {
11861206 .dir => |opt_handle| if (opt_handle) |handle| {
1187 try populateDirectory(m, header, need_stat, handle, options.contents, metadata_only);
1207 try populateDirectory(m, header, need_stat, handle, options.contents, metadata_only, options.diagnostic);
11881208 } else {
11891209 const dir = cache.prefixes()[prefix].handle;
11901210 const sub_path = filePath(m.contents.items, file_offset);
1191 const handle = try dir.openDir(io, sub_path, .{
1211 const handle = dir.openDir(io, sub_path, .{
11921212 .access_sub_paths = false,
11931213 .iterate = true,
1194 });
1214 }) catch |err| switch (err) {
1215 error.Canceled => |e| return e,
1216 else => |e| {
1217 if (options.diagnostic) |d| d.* = .{ .open_dir = e };
1218 return error.FileSystemFailure;
1219 },
1220 };
11951221 defer handle.close(io);
1196 try populateDirectory(m, header, need_stat, handle, options.contents, metadata_only);
1222 try populateDirectory(m, header, need_stat, handle, options.contents, metadata_only, options.diagnostic);
11971223 },
11981224
11991225 .file => |opt_handle| if (opt_handle) |handle| {
1200 try populateFile(m, header, need_stat, handle, options.contents, metadata_only);
1226 try populateFile(m, header, need_stat, handle, options.contents, metadata_only, options.diagnostic);
12011227 } else {
12021228 const dir = cache.prefixes()[prefix].handle;
12031229 const sub_path = filePath(m.contents.items, file_offset);
1204 const handle = try dir.openFile(io, sub_path, .{ .mode = .read_only });
1230 const handle = dir.openFile(io, sub_path, .{ .mode = .read_only }) catch |err| switch (err) {
1231 error.Canceled => |e| return e,
1232 else => |e| {
1233 if (options.diagnostic) |d| d.* = .{ .open_file = e };
1234 return error.FileSystemFailure;
1235 },
1236 };
12051237 defer handle.close(io);
1206 try populateFile(m, header, need_stat, handle, options.contents, metadata_only);
1238 try populateFile(m, header, need_stat, handle, options.contents, metadata_only, options.diagnostic);
12071239 },
12081240 }
12091241
......@@ -1217,11 +1249,18 @@ pub const Manifest = struct {
12171249 handle: Io.File,
12181250 contents: ?[]const u8,
12191251 metadata_only: bool,
1220 ) !void {
1252 diagnostic: ?*AddDiscoveredPathDiagnostic,
1253 ) AddDiscoveredPathError!void {
12211254 const io = m.cache.io;
12221255
12231256 if (need_stat) {
1224 const stat = try handle.stat(io);
1257 const stat = handle.stat(io) catch |err| switch (err) {
1258 error.Canceled => |e| return e,
1259 else => |e| {
1260 if (diagnostic) |d| d.* = .{ .stat_file = e };
1261 return error.FileSystemFailure;
1262 },
1263 };
12251264 try file.setStat(m, .init(stat));
12261265 }
12271266 if (metadata_only) {
......@@ -1233,7 +1272,13 @@ pub const Manifest = struct {
12331272 hasher.update(bytes);
12341273 hasher.final(&file.digest);
12351274 } else {
1236 try hashFile(io, handle, &file.digest);
1275 hashFile(io, handle, &file.digest) catch |err| switch (err) {
1276 error.Canceled => |e| return e,
1277 else => |e| {
1278 if (diagnostic) |d| d.* = .{ .read_file = e };
1279 return error.FileSystemFailure;
1280 },
1281 };
12371282 }
12381283 }
12391284
......@@ -1244,13 +1289,20 @@ pub const Manifest = struct {
12441289 handle: Io.Dir,
12451290 contents: ?[]const u8,
12461291 metadata_only: bool,
1247 ) !void {
1292 diagnostic: ?*AddDiscoveredPathDiagnostic,
1293 ) AddDiscoveredPathError!void {
12481294 const cache = m.cache;
12491295 const io = cache.io;
12501296 const gpa = cache.gpa;
12511297
12521298 if (need_stat) {
1253 const stat = try handle.stat(io);
1299 const stat = handle.stat(io) catch |err| switch (err) {
1300 error.Canceled => |e| return e,
1301 else => |e| {
1302 if (diagnostic) |d| d.* = .{ .stat_dir = e };
1303 return error.FileSystemFailure;
1304 },
1305 };
12541306 try file.setStat(m, .init(stat));
12551307 }
12561308 if (metadata_only) {
......@@ -1264,7 +1316,13 @@ pub const Manifest = struct {
12641316 } else {
12651317 const prev_contents_len = m.all_input_content.items.len;
12661318 defer m.all_input_content.shrinkRetainingCapacity(prev_contents_len);
1267 try hashDir(gpa, io, handle, &file.digest, &m.all_input_content);
1319 hashDir(gpa, io, handle, &file.digest, &m.all_input_content) catch |err| switch (err) {
1320 error.OutOfMemory, error.Canceled => |e| return e,
1321 else => |e| {
1322 if (diagnostic) |d| d.* = .{ .read_dir = e };
1323 return error.FileSystemFailure;
1324 },
1325 };
12681326 }
12691327 }
12701328
......@@ -1297,13 +1355,15 @@ pub const Manifest = struct {
12971355 .target, .target_must_resolve => {},
12981356 .prereq => |file_path| if (self.manifest_file == null) {
12991357 _ = try self.addInputPath(.initCwd(file_path), .{});
1300 } else try self.addDiscoveredPath(.{ .path = .{ .unresolved = .initCwd(file_path) } }),
1358 } else try self.addDiscoveredPath(.{ .discovered_path = .{ .unresolved = .initCwd(file_path) } }),
13011359 .prereq_must_resolve => {
13021360 resolve_buf.clearRetainingCapacity();
13031361 try token.resolve(gpa, &resolve_buf);
13041362 if (self.manifest_file == null) {
13051363 _ = try self.addInputPath(.initCwd(resolve_buf.items), .{});
1306 } else try self.addDiscoveredPath(.{ .path = .{ .unresolved = .initCwd(resolve_buf.items) } });
1364 } else try self.addDiscoveredPath(.{
1365 .discovered_path = .{ .unresolved = .initCwd(resolve_buf.items) },
1366 });
13071367 },
13081368 else => |err| {
13091369 try err.printError(gpa, &error_buf);
......@@ -1456,10 +1516,12 @@ pub const Manifest = struct {
14561516 const gpa = man.cache.gpa;
14571517 const files = man.files.keys();
14581518 if (files.len > 0) {
1519 const contents = man.contents.items;
14591520 for (files) |file| {
1460 try buf.ensureUnusedCapacity(gpa, file.prefixed_path.sub_path.len + 2);
1461 buf.appendAssumeCapacity(file.prefixed_path.prefix + 1);
1462 buf.appendSliceAssumeCapacity(file.prefixed_path.sub_path);
1521 const file_path = filePath(contents, file);
1522 try buf.ensureUnusedCapacity(gpa, file_path.len + 2);
1523 buf.appendAssumeCapacity(@as(u8, file.get(contents).flags.prefix) + 1);
1524 buf.appendSliceAssumeCapacity(file_path);
14631525 buf.appendAssumeCapacity(0);
14641526 }
14651527 // The null byte is a separator, not a terminator.
......@@ -1476,12 +1538,12 @@ pub const Manifest = struct {
14761538 const orig_files_len = other.files.count();
14771539 const orig_contents_len = other.contents.items.len;
14781540 errdefer {
1479 other.files.shrinkRetainingCapacity(orig_files_len);
1541 other.files.shrinkRetainingCapacityContext(orig_files_len, .{ .contents = other.contents.items });
14801542 other.contents.shrinkRetainingCapacity(orig_contents_len);
14811543 }
14821544
14831545 for (man.files.keys(), 0..) |off, file_index| {
1484 try other.files.ensureUnusedCapacity(gpa, 1);
1546 try other.files.ensureUnusedCapacityContext(gpa, 1, .{ .contents = other.contents.items });
14851547
14861548 const next_off = if (file_index < man.files.count())
14871549 @backingInt(man.files.keys()[file_index + 1])
......@@ -1489,20 +1551,21 @@ pub const Manifest = struct {
14891551 man.contents.items.len;
14901552
14911553 const copy_bytes = man.contents.items[@backingInt(off)..next_off];
1492 const prev_contents_len = other.contents.items.len;
1554 const prev_contents_len: File.Offset = @fromBackingInt(@intCast(other.contents.items.len));
14931555 try other.contents.appendSlice(gpa, copy_bytes);
14941556
1495 const gop = other.files.getOrPutAssumeCapacityContext(@fromBackingInt(prev_contents_len), .{
1496 .manifest = other,
1557 const gop = other.files.getOrPutAssumeCapacityContext(prev_contents_len, .{
1558 .contents = other.contents.items,
14971559 });
14981560
14991561 if (gop.found_existing) {
1500 other.contents.shrinkRetainingCapacity(prev_contents_len);
1562 other.contents.shrinkRetainingCapacity(@backingInt(prev_contents_len));
15011563 continue;
15021564 }
15031565
1504 const other_file = File.get(@fromBackingInt(prev_contents_len));
1505 other_file.prefix = prefix_map[other_file.prefix];
1566 // Flags are already copied but the prefix is supposed to be filtered by `prefix_map`.
1567 const other_file = prev_contents_len.get(other.contents.items);
1568 other_file.flags.prefix = @intCast(prefix_map[other_file.flags.prefix]);
15061569 }
15071570 }
15081571
lib/std/zig.zig+1-1
......@@ -1840,7 +1840,7 @@ pub fn buildExeSubprocess(
18401840 const prefix: Server.Message.PathPrefix = @fromBackingInt(@intCast(prefixed_path[0] - 1));
18411841 const sub_path = prefixed_path[1..];
18421842 man.addDiscoveredPath(.{
1843 .path = .{ .prefixed = .{
1843 .discovered_path = .{ .prefixed = .{
18441844 .prefix = @intCast(@backingInt(prefix)),
18451845 .sub_path = sub_path,
18461846 } },
src/Compilation.zig+39-61
......@@ -701,39 +701,12 @@ pub const Path = struct {
701701 };
702702 }
703703
704 pub fn addToCacheManifestPostHit(p: Path, man: *Cache.Manifest, dirs: *const std.zig.Directories) !void {
705 comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd));
706 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));
707 comptime assert(2 == @backingInt(std.zig.Server.Message.PathPrefix.local_cache));
708 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));
709 comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root));
710 comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5);
711 const gpa = man.cache.gpa;
712 const prefixed_path: Cache.PrefixedPath = .{
713 .prefix = switch (p.root) {
714 .none => {
715 const path = try p.toAbsolute(dirs, gpa);
716 defer gpa.free(path);
717 return man.addFilePost(path);
718 },
719 .zig_lib => 1,
720 .local_cache => 2,
721 .global_cache => 3,
722 .build_root => 4,
723 },
724 .sub_path = try gpa.dupe(u8, p.sub_path),
725 };
726 var keep = false;
727 defer if (!keep) gpa.free(prefixed_path.sub_path);
728 keep = try man.addPrefixedPathPost(prefixed_path);
729 }
730
731 pub fn addToCacheManifestPostHitContents(
704 pub fn addToCacheManifestAsDiscovered(
732705 p: Path,
733706 man: *Cache.Manifest,
734707 dirs: *const std.zig.Directories,
735 bytes: []const u8,
736 stat: Cache.File.Stat,
708 contents: ?[]const u8,
709 stat: ?Cache.Manifest.Stat,
737710 ) !void {
738711 comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd));
739712 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));
......@@ -741,24 +714,29 @@ pub const Path = struct {
741714 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));
742715 comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root));
743716 comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5);
744 const gpa = man.cache.gpa;
745 const prefixed_path: Cache.PrefixedPath = .{
746 .prefix = switch (p.root) {
747 .none => {
748 const path = try p.toAbsolute(dirs, gpa);
749 defer gpa.free(path);
750 return man.addFilePostContents(path, bytes, stat);
717 try man.addDiscoveredPath(.{
718 .discovered_path = .{ .prefixed = .{
719 .prefix = switch (p.root) {
720 .none => {
721 const gpa = man.cache.gpa;
722 const path = try p.toAbsolute(dirs, gpa);
723 defer gpa.free(path);
724 return man.addDiscoveredPath(.{
725 .discovered_path = .{ .unresolved = .initCwd(path) },
726 .contents = contents,
727 .stat = stat,
728 });
729 },
730 .zig_lib => 1,
731 .local_cache => 2,
732 .global_cache => 3,
733 .build_root => 4,
751734 },
752 .zig_lib => 1,
753 .local_cache => 2,
754 .global_cache => 3,
755 .build_root => 4,
756 },
757 .sub_path = try gpa.dupe(u8, p.sub_path),
758 };
759 var keep = false;
760 defer if (!keep) gpa.free(prefixed_path.sub_path);
761 keep = try man.addPrefixedPathPostContents(prefixed_path, bytes, stat);
735 .sub_path = p.sub_path,
736 } },
737 .contents = contents,
738 .stat = stat,
739 });
762740 }
763741};
764742
......@@ -2835,20 +2813,18 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
28352813 man.want_shared_lock = false;
28362814 }
28372815
2838 const is_hit = man.check(main_progress_node) catch |err| switch (err) {
2816 const status = man.check(main_progress_node) catch |err| switch (err) {
28392817 error.Canceled, error.OutOfMemory => |e| return e,
28402818 error.CacheCheckFailed => switch (man.diagnostic) {
28412819 .none => unreachable,
2842 .manifest_create, .manifest_read, .manifest_lock => |e| return comp.setMiscFailure(
2820 .manifest_create, .manifest_stat, .manifest_read, .manifest_lock => |e| return comp.setMiscFailure(
28432821 .check_whole_cache,
28442822 "failed to check cache: {t} {t}",
28452823 .{ man.diagnostic, e },
28462824 ),
28472825 .file_open, .file_stat, .file_read, .file_hash => |op| {
2848 const pp = man.files.keys()[op.file_index].prefixed_path;
2849 const prefix = man.cache.prefixes()[pp.prefix];
2850 return comp.setMiscFailure(.check_whole_cache, "failed to check cache: {f}{s} {t} {t}", .{
2851 prefix, pp.sub_path, man.diagnostic, op.err,
2826 return comp.setMiscFailure(.check_whole_cache, "failed to check cache: {f} {t} {t}", .{
2827 op.path(&man), man.diagnostic, op.err,
28522828 });
28532829 },
28542830 },
......@@ -2858,7 +2834,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
28582834 .{},
28592835 ),
28602836 };
2861 if (is_hit and !ignore_hit) {
2837 if (status == .hit and !ignore_hit) {
28622838 // In this case the cache hit contains the full set of file system inputs. Nice!
28632839 if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
28642840 if (comp.parent_whole_cache) |pwc| {
......@@ -3454,8 +3430,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
34543430
34553431 const opts = comp.cache_use.whole.lf_open_opts;
34563432
3457 try man.addOptionalFilePath(opts.linker_script);
3458 try man.addOptionalFilePath(opts.version_script);
3433 try man.addInputPathOptional(opts.linker_script, .{});
3434 try man.addInputPathOptional(opts.version_script, .{});
34593435 man.hash.add(opts.allow_undefined_version);
34603436 man.hash.addOptional(opts.enable_new_dtags);
34613437
......@@ -3514,7 +3490,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
35143490
35153491 // Mach-O specific stuff
35163492 try link.File.MachO.hashAddFrameworks(man, opts.frameworks);
3517 try man.addOptionalFilePath(opts.entitlements);
3493 try man.addInputPathOptional(opts.entitlements, .{});
35183494 man.hash.addOptional(opts.pagezero_size);
35193495 man.hash.addOptional(opts.headerpad_size);
35203496 man.hash.add(opts.headerpad_max_install_names);
......@@ -5905,7 +5881,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
59055881 const rc_basename = try std.fmt.allocPrint(arena, "{s}.rc", .{src_basename});
59065882 const res_basename = try std.fmt.allocPrint(arena, "{s}.res", .{src_basename});
59075883
5908 const digest = if (try man.check(child_progress_node)) man.final() else blk: {
5884 const digest = if (.hit == try man.check(child_progress_node)) man.final() else blk: {
59095885 // The digest only depends on the .manifest file, so we can
59105886 // get the digest now and write the .res directly to the cache
59115887 const digest = man.final();
......@@ -5998,7 +5974,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
59985974
59995975 const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len];
60005976
6001 const digest = if (try man.check(child_progress_node)) man.final() else blk: {
5977 const digest = if (.hit == try man.check(child_progress_node)) man.final() else blk: {
60025978 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{});
60035979 defer zig_cache_tmp_dir.close(io);
60045980
......@@ -6055,12 +6031,14 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
60556031 return comp.failWin32Resource(win32_resource, "depfile from zig rc has unexpected format", .{});
60566032 }
60576033 const dep_file_path = element.string;
6058 try man.addFilePost(dep_file_path);
6034 try man.addDiscoveredPath(.{ .discovered_path = .{ .unresolved = .initCwd(dep_file_path) } });
60596035 switch (comp.cache_use) {
60606036 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {
60616037 try whole.cache_manifest_mutex.lock(io);
60626038 defer whole.cache_manifest_mutex.unlock(io);
6063 try whole_cache_manifest.addFilePost(dep_file_path);
6039 try whole_cache_manifest.addDiscoveredPath(.{
6040 .discovered_path = .{ .unresolved = .initCwd(dep_file_path) },
6041 });
60646042 },
60656043 .incremental, .none => {},
60666044 }
src/Zcu.zig+2-2
......@@ -974,7 +974,7 @@ pub const File = struct {
974974 success,
975975 },
976976 /// Whether this is populated depends on `status`.
977 stat: Cache.File.Stat,
977 stat: Cache.Manifest.Stat,
978978
979979 /// Whether this file is the generated file of a "builtin" module. This matters because those
980980 /// files are generated and stored in-nemory rather than being read off-disk. The rest of the
......@@ -1246,7 +1246,7 @@ pub const EmbedFile = struct {
12461246 val: InternPool.Index,
12471247 /// If this is `null` and `val` is `.none`, the file has never been loaded.
12481248 err: ?(Io.File.OpenError || Io.File.StatError || Io.File.Reader.Error || error{UnexpectedEof}),
1249 stat: Cache.File.Stat,
1249 stat: Cache.Manifest.Stat,
12501250
12511251 pub const Index = enum(u32) {
12521252 _,
src/Zcu/PerThread.zig+17-21
......@@ -224,11 +224,12 @@ pub fn update(
224224 const result = res: {
225225 try whole.cache_manifest_mutex.lock(io);
226226 defer whole.cache_manifest_mutex.unlock(io);
227 if (file.source) |source| {
228 break :res file.path.addToCacheManifestPostHitContents(man, &comp.dirs, source, file.stat);
229 } else {
230 break :res file.path.addToCacheManifestPostHit(man, &comp.dirs);
231 }
227 break :res file.path.addToCacheManifestAsDiscovered(
228 man,
229 &comp.dirs,
230 file.source,
231 if (file.source != null) file.stat else null,
232 );
232233 };
233234 result catch |err| switch (err) {
234235 error.OutOfMemory => |e| return e,
......@@ -2835,26 +2836,21 @@ fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!struct
28352836 assert(mem.eql(u8, import_path, "std")); // the single import is of 'std'
28362837 }
28372838
2838 Builtin.updateFileOnDisk(file, comp) catch |err| comp.setMiscFailure(
2839 .write_builtin_zig,
2840 "unable to write '{f}': {s}",
2841 .{ file.path.fmt(comp), @errorName(err) },
2842 );
2839 Builtin.updateFileOnDisk(file, comp) catch |err|
2840 comp.setMiscFailure(.write_builtin_zig, "unable to write {qf}: {t}", .{ file.path.fmt(comp), err });
28432841 return .{
28442842 .file = file_index,
28452843 .module_root = mod,
28462844 };
28472845}
28482846
2847pub const EmbedFileError = error{ImportOutsideModulePath} || Allocator.Error || Io.Cancelable;
2848
28492849pub fn embedFile(
28502850 pt: Zcu.PerThread,
28512851 cur_file: *Zcu.File,
28522852 import_string: []const u8,
2853) error{
2854 OutOfMemory,
2855 Canceled,
2856 ImportOutsideModulePath,
2857}!Zcu.EmbedFile.Index {
2853) EmbedFileError!Zcu.EmbedFile.Index {
28582854 const zcu = pt.zcu;
28592855 const gpa = zcu.gpa;
28602856
......@@ -2937,7 +2933,7 @@ fn updateEmbedFileInner(
29372933 };
29382934 defer file.close(io);
29392935
2940 const stat: Cache.File.Stat = .fromFs(try file.stat(io));
2936 const stat: Cache.Manifest.Stat = .init(try file.stat(io));
29412937
29422938 if (ef.val != .none) {
29432939 const old_stat = ef.stat;
......@@ -2994,10 +2990,7 @@ fn updateEmbedFileInner(
29942990}
29952991
29962992/// Assumes that `path` is allocated into `gpa`. Takes ownership of `path` on success.
2997fn newEmbedFile(
2998 pt: Zcu.PerThread,
2999 path: Compilation.Path,
3000) !*Zcu.EmbedFile {
2993fn newEmbedFile(pt: Zcu.PerThread, path: Compilation.Path) EmbedFileError!*Zcu.EmbedFile {
30012994 const zcu = pt.zcu;
30022995 const comp = zcu.comp;
30032996 const io = comp.io;
......@@ -3034,7 +3027,10 @@ fn newEmbedFile(
30343027 try whole.cache_manifest_mutex.lock(io);
30353028 defer whole.cache_manifest_mutex.unlock(io);
30363029
3037 try path.addToCacheManifestPostHitContents(man, &comp.dirs, contents, new_file.stat);
3030 path.addToCacheManifestAsDiscovered(man, &comp.dirs, contents, new_file.stat) catch |err| switch (err) {
3031 error.FileSystemFailure => unreachable, // contents and stat are both provided
3032 else => |e| return e,
3033 };
30383034 }
30393035
30403036 return new_file;
src/libs/mingw.zig+5-7
......@@ -251,18 +251,16 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
251251 const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name});
252252 errdefer gpa.free(final_lib_basename);
253253
254 const is_hit = man.check(prog_node) catch |err| switch (err) {
254 const status = man.check(prog_node) catch |err| switch (err) {
255255 error.CacheCheckFailed => switch (man.diagnostic) {
256256 .none => unreachable,
257 .manifest_create, .manifest_read, .manifest_lock => |e| {
257 .manifest_create, .manifest_stat, .manifest_read, .manifest_lock => |e| {
258258 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {t} {t}", .{ man.diagnostic, e });
259259 return error.AlreadyReported;
260260 },
261261 .file_open, .file_stat, .file_read, .file_hash => |op| {
262 const pp = man.files.keys()[op.file_index].prefixed_path;
263 const prefix = man.cache.prefixes()[pp.prefix];
264 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {f}{s} {t} {t}", .{
265 prefix, pp.sub_path, man.diagnostic, op.err,
262 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {f} {t} {t}", .{
263 op.path(&man), man.diagnostic, op.err,
266264 });
267265 return error.AlreadyReported;
268266 },
......@@ -273,7 +271,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
273271 return error.AlreadyReported;
274272 },
275273 };
276 if (is_hit) {
274 if (status == .hit) {
277275 const digest = man.final();
278276 const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });
279277 errdefer gpa.free(sub_path);
src/link.zig+9-3
......@@ -1925,15 +1925,21 @@ pub fn hashInputs(man: *Cache.Manifest, link_inputs: []const Input) !void {
19251925 man.hash.add(@as(@typeInfo(Input).@"union".tag_type.?, link_input));
19261926 switch (link_input) {
19271927 .object, .archive => |obj| {
1928 _ = try man.addOpenedFile(obj.path, obj.file, null);
1928 _ = try man.addInputPath(obj.path, .{
1929 .handle = .{ .file = obj.file },
1930 });
19291931 man.hash.add(obj.must_link);
19301932 man.hash.add(obj.hidden);
19311933 },
19321934 .res => |res| {
1933 _ = try man.addOpenedFile(res.path, res.file, null);
1935 _ = try man.addInputPath(res.path, .{
1936 .handle = .{ .file = res.file },
1937 });
19341938 },
19351939 .dso => |dso| {
1936 _ = try man.addOpenedFile(dso.path, dso.file, null);
1940 _ = try man.addInputPath(dso.path, .{
1941 .handle = .{ .file = dso.file },
1942 });
19371943 man.hash.add(dso.needed);
19381944 man.hash.add(dso.weak);
19391945 man.hash.add(dso.reexport);
src/link/Elf.zig+2-2
......@@ -1120,7 +1120,7 @@ fn parseDso(
11201120
11211121 const handle = dso.file;
11221122
1123 const stat = Stat.fromFs(try handle.stat(io));
1123 const stat: Stat = .init(try handle.stat(io));
11241124 var header = try SharedObject.parseHeader(gpa, io, diags, dso.path, handle, stat, target);
11251125 defer header.deinit(gpa);
11261126
......@@ -4407,7 +4407,7 @@ const mem = std.mem;
44074407const Allocator = std.mem.Allocator;
44084408const Hash = std.hash.Wyhash;
44094409const Path = std.Build.Cache.Path;
4410const Stat = std.Build.Cache.File.Stat;
4410const Stat = std.Build.Cache.Manifest.Stat;
44114411
44124412const codegen = @import("../codegen.zig");
44134413const eh_frame = @import("Elf/eh_frame.zig");
src/link/Elf/SharedObject.zig+1-1
......@@ -7,7 +7,7 @@ const elf = std.elf;
77const log = std.log.scoped(.elf);
88const mem = std.mem;
99const Path = std.Build.Cache.Path;
10const Stat = std.Build.Cache.File.Stat;
10const Stat = std.Build.Cache.Manifest.Stat;
1111const Allocator = mem.Allocator;
1212
1313const Elf = @import("../Elf.zig");
src/main.zig+1-1
......@@ -4878,7 +4878,7 @@ fn cmdTranslateC(
48784878 Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err|
48794879 fatal("unable to process {q}: {t}", .{ c_source_file.src_path, err });
48804880
4881 const result: Compilation.TranslateCResult = if (try man.check(prog_node)) .{
4881 const result: Compilation.TranslateCResult = if (.hit == try man.check(prog_node)) .{
48824882 .digest = man.finalBin(),
48834883 .cache_hit = true,
48844884 .errors = std.zig.ErrorBundle.empty,