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 {...@@ -1500,7 +1500,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
1500 if (config_man) |man| for (configuration.path_deps) |path_dep| {1500 if (config_man) |man| for (configuration.path_deps) |path_dep| {
1501 const path = try confPathDepToCachePath(arena, graph, &configuration, path_dep);1501 const path = try confPathDepToCachePath(arena, graph, &configuration, path_dep);
1502 try man.addDiscoveredPath(.{1502 try man.addDiscoveredPath(.{
1503 .path = .{ .unresolved = path },1503 .discovered_path = .{ .unresolved = path },
1504 .handle = if (path_dep.flags.is_directory) .{ .dir = null } else .{ .file = null },1504 .handle = if (path_dep.flags.is_directory) .{ .dir = null } else .{ .file = null },
1505 .metadata_only = path_dep.flags.metadata_only,1505 .metadata_only = path_dep.flags.metadata_only,
1506 });1506 });
lib/compiler/Maker/Step.zig+1-1
...@@ -753,7 +753,7 @@ fn failWithCacheError(...@@ -753,7 +753,7 @@ fn failWithCacheError(
753 switch (err) {753 switch (err) {
754 error.CacheCheckFailed => switch (man.diagnostic) {754 error.CacheCheckFailed => switch (man.diagnostic) {
755 .none => unreachable,755 .none => unreachable,
756 .manifest_create, .manifest_read, .manifest_lock => |e| {756 .manifest_create, .manifest_stat, .manifest_read, .manifest_lock => |e| {
757 return s.fail(maker, "failed checking cache: {t} {t}", .{ man.diagnostic, e });757 return s.fail(maker, "failed checking cache: {t} {t}", .{ man.diagnostic, e });
758 },758 },
759 .file_open, .file_stat, .file_read, .file_hash => |op| {759 .file_open, .file_stat, .file_read, .file_hash => |op| {
lib/std/Build/Cache.zig+96-33
...@@ -1104,25 +1104,45 @@ pub const Manifest = struct {...@@ -1104,25 +1104,45 @@ pub const Manifest = struct {
1104 return timestamp.nanoseconds >= man.recent_problematic_timestamp.nanoseconds;1104 return timestamp.nanoseconds >= man.recent_problematic_timestamp.nanoseconds;
1105 }1105 }
11061106
1107 pub const AddPathPostOptions = struct {1107 pub const AddDiscoveredPathOptions = struct {
1108 path: union(enum) {1108 discovered_path: DiscoveredPath,
1109 unresolved: Path,
1110 prefixed: PrefixedPath,
1111 },
1112 handle: PathHandle = .{ .file = null },1109 handle: PathHandle = .{ .file = null },
1113 stat: ?Stat = null,1110 stat: ?Stat = null,
1114 /// If it is a directory, there is a special encoding required for contents, which1111 /// If it is a directory, there is a special encoding required for contents, which
1115 /// is null-separated sorted entries, each one prefixed with `File.Kind`.1112 /// is null-separated sorted entries, each one prefixed with `File.Kind`.
1116 contents: ?[]const u8 = null,1113 contents: ?[]const u8 = null,
1117 metadata_only: bool = false,1114 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,
1118 };1132 };
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
1120 /// Add a file as a dependency of process being cached, after cache miss1140 /// Add a file as a dependency of process being cached, after cache miss
1121 /// occurs.1141 /// occurs.
1122 ///1142 ///
1123 /// See also:1143 /// See also:
1124 /// * `addInputPath`1144 /// * `addInputPath`
1125 pub fn addDiscoveredPath(m: *Manifest, options: AddPathPostOptions) !void {1145 pub fn addDiscoveredPath(m: *Manifest, options: AddDiscoveredPathOptions) AddDiscoveredPathError!void {
1126 assert(m.manifest_file != null);1146 assert(m.manifest_file != null);
1127 const cache = m.cache;1147 const cache = m.cache;
1128 const gpa = cache.gpa;1148 const gpa = cache.gpa;
...@@ -1135,7 +1155,7 @@ pub const Manifest = struct {...@@ -1135,7 +1155,7 @@ pub const Manifest = struct {
1135 try m.contents.appendNTimes(gpa, 0, @offsetOf(File, "path_start"));1155 try m.contents.appendNTimes(gpa, 0, @offsetOf(File, "path_start"));
1136 errdefer m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset));1156 errdefer m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset));
11371157
1138 const new_prefix = switch (options.path) {1158 const new_prefix = switch (options.discovered_path) {
1139 .unresolved => |unresolved| try cache.resolveAppendPath(&m.contents, unresolved),1159 .unresolved => |unresolved| try cache.resolveAppendPath(&m.contents, unresolved),
1140 .prefixed => |prefixed| try cache.appendPrefixedPath(&m.contents, prefixed),1160 .prefixed => |prefixed| try cache.appendPrefixedPath(&m.contents, prefixed),
1141 };1161 };
...@@ -1184,26 +1204,38 @@ pub const Manifest = struct {...@@ -1184,26 +1204,38 @@ pub const Manifest = struct {
11841204
1185 switch (options.handle) {1205 switch (options.handle) {
1186 .dir => |opt_handle| if (opt_handle) |handle| {1206 .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);
1188 } else {1208 } else {
1189 const dir = cache.prefixes()[prefix].handle;1209 const dir = cache.prefixes()[prefix].handle;
1190 const sub_path = filePath(m.contents.items, file_offset);1210 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, .{
1192 .access_sub_paths = false,1212 .access_sub_paths = false,
1193 .iterate = true,1213 .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 };
1195 defer handle.close(io);1221 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);
1197 },1223 },
11981224
1199 .file => |opt_handle| if (opt_handle) |handle| {1225 .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);
1201 } else {1227 } else {
1202 const dir = cache.prefixes()[prefix].handle;1228 const dir = cache.prefixes()[prefix].handle;
1203 const sub_path = filePath(m.contents.items, file_offset);1229 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 };
1205 defer handle.close(io);1237 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);
1207 },1239 },
1208 }1240 }
12091241
...@@ -1217,11 +1249,18 @@ pub const Manifest = struct {...@@ -1217,11 +1249,18 @@ pub const Manifest = struct {
1217 handle: Io.File,1249 handle: Io.File,
1218 contents: ?[]const u8,1250 contents: ?[]const u8,
1219 metadata_only: bool,1251 metadata_only: bool,
1220 ) !void {1252 diagnostic: ?*AddDiscoveredPathDiagnostic,
1253 ) AddDiscoveredPathError!void {
1221 const io = m.cache.io;1254 const io = m.cache.io;
12221255
1223 if (need_stat) {1256 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 };
1225 try file.setStat(m, .init(stat));1264 try file.setStat(m, .init(stat));
1226 }1265 }
1227 if (metadata_only) {1266 if (metadata_only) {
...@@ -1233,7 +1272,13 @@ pub const Manifest = struct {...@@ -1233,7 +1272,13 @@ pub const Manifest = struct {
1233 hasher.update(bytes);1272 hasher.update(bytes);
1234 hasher.final(&file.digest);1273 hasher.final(&file.digest);
1235 } else {1274 } 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 };
1237 }1282 }
1238 }1283 }
12391284
...@@ -1244,13 +1289,20 @@ pub const Manifest = struct {...@@ -1244,13 +1289,20 @@ pub const Manifest = struct {
1244 handle: Io.Dir,1289 handle: Io.Dir,
1245 contents: ?[]const u8,1290 contents: ?[]const u8,
1246 metadata_only: bool,1291 metadata_only: bool,
1247 ) !void {1292 diagnostic: ?*AddDiscoveredPathDiagnostic,
1293 ) AddDiscoveredPathError!void {
1248 const cache = m.cache;1294 const cache = m.cache;
1249 const io = cache.io;1295 const io = cache.io;
1250 const gpa = cache.gpa;1296 const gpa = cache.gpa;
12511297
1252 if (need_stat) {1298 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 };
1254 try file.setStat(m, .init(stat));1306 try file.setStat(m, .init(stat));
1255 }1307 }
1256 if (metadata_only) {1308 if (metadata_only) {
...@@ -1264,7 +1316,13 @@ pub const Manifest = struct {...@@ -1264,7 +1316,13 @@ pub const Manifest = struct {
1264 } else {1316 } else {
1265 const prev_contents_len = m.all_input_content.items.len;1317 const prev_contents_len = m.all_input_content.items.len;
1266 defer m.all_input_content.shrinkRetainingCapacity(prev_contents_len);1318 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 };
1268 }1326 }
1269 }1327 }
12701328
...@@ -1297,13 +1355,15 @@ pub const Manifest = struct {...@@ -1297,13 +1355,15 @@ pub const Manifest = struct {
1297 .target, .target_must_resolve => {},1355 .target, .target_must_resolve => {},
1298 .prereq => |file_path| if (self.manifest_file == null) {1356 .prereq => |file_path| if (self.manifest_file == null) {
1299 _ = try self.addInputPath(.initCwd(file_path), .{});1357 _ = 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) } }),
1301 .prereq_must_resolve => {1359 .prereq_must_resolve => {
1302 resolve_buf.clearRetainingCapacity();1360 resolve_buf.clearRetainingCapacity();
1303 try token.resolve(gpa, &resolve_buf);1361 try token.resolve(gpa, &resolve_buf);
1304 if (self.manifest_file == null) {1362 if (self.manifest_file == null) {
1305 _ = try self.addInputPath(.initCwd(resolve_buf.items), .{});1363 _ = 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 });
1307 },1367 },
1308 else => |err| {1368 else => |err| {
1309 try err.printError(gpa, &error_buf);1369 try err.printError(gpa, &error_buf);
...@@ -1456,10 +1516,12 @@ pub const Manifest = struct {...@@ -1456,10 +1516,12 @@ pub const Manifest = struct {
1456 const gpa = man.cache.gpa;1516 const gpa = man.cache.gpa;
1457 const files = man.files.keys();1517 const files = man.files.keys();
1458 if (files.len > 0) {1518 if (files.len > 0) {
1519 const contents = man.contents.items;
1459 for (files) |file| {1520 for (files) |file| {
1460 try buf.ensureUnusedCapacity(gpa, file.prefixed_path.sub_path.len + 2);1521 const file_path = filePath(contents, file);
1461 buf.appendAssumeCapacity(file.prefixed_path.prefix + 1);1522 try buf.ensureUnusedCapacity(gpa, file_path.len + 2);
1462 buf.appendSliceAssumeCapacity(file.prefixed_path.sub_path);1523 buf.appendAssumeCapacity(@as(u8, file.get(contents).flags.prefix) + 1);
1524 buf.appendSliceAssumeCapacity(file_path);
1463 buf.appendAssumeCapacity(0);1525 buf.appendAssumeCapacity(0);
1464 }1526 }
1465 // The null byte is a separator, not a terminator.1527 // The null byte is a separator, not a terminator.
...@@ -1476,12 +1538,12 @@ pub const Manifest = struct {...@@ -1476,12 +1538,12 @@ pub const Manifest = struct {
1476 const orig_files_len = other.files.count();1538 const orig_files_len = other.files.count();
1477 const orig_contents_len = other.contents.items.len;1539 const orig_contents_len = other.contents.items.len;
1478 errdefer {1540 errdefer {
1479 other.files.shrinkRetainingCapacity(orig_files_len);1541 other.files.shrinkRetainingCapacityContext(orig_files_len, .{ .contents = other.contents.items });
1480 other.contents.shrinkRetainingCapacity(orig_contents_len);1542 other.contents.shrinkRetainingCapacity(orig_contents_len);
1481 }1543 }
14821544
1483 for (man.files.keys(), 0..) |off, file_index| {1545 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
1486 const next_off = if (file_index < man.files.count())1548 const next_off = if (file_index < man.files.count())
1487 @backingInt(man.files.keys()[file_index + 1])1549 @backingInt(man.files.keys()[file_index + 1])
...@@ -1489,20 +1551,21 @@ pub const Manifest = struct {...@@ -1489,20 +1551,21 @@ pub const Manifest = struct {
1489 man.contents.items.len;1551 man.contents.items.len;
14901552
1491 const copy_bytes = man.contents.items[@backingInt(off)..next_off];1553 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));
1493 try other.contents.appendSlice(gpa, copy_bytes);1555 try other.contents.appendSlice(gpa, copy_bytes);
14941556
1495 const gop = other.files.getOrPutAssumeCapacityContext(@fromBackingInt(prev_contents_len), .{1557 const gop = other.files.getOrPutAssumeCapacityContext(prev_contents_len, .{
1496 .manifest = other,1558 .contents = other.contents.items,
1497 });1559 });
14981560
1499 if (gop.found_existing) {1561 if (gop.found_existing) {
1500 other.contents.shrinkRetainingCapacity(prev_contents_len);1562 other.contents.shrinkRetainingCapacity(@backingInt(prev_contents_len));
1501 continue;1563 continue;
1502 }1564 }
15031565
1504 const other_file = File.get(@fromBackingInt(prev_contents_len));1566 // Flags are already copied but the prefix is supposed to be filtered by `prefix_map`.
1505 other_file.prefix = prefix_map[other_file.prefix];1567 const other_file = prev_contents_len.get(other.contents.items);
1568 other_file.flags.prefix = @intCast(prefix_map[other_file.flags.prefix]);
1506 }1569 }
1507 }1570 }
15081571
lib/std/zig.zig+1-1
...@@ -1840,7 +1840,7 @@ pub fn buildExeSubprocess(...@@ -1840,7 +1840,7 @@ pub fn buildExeSubprocess(
1840 const prefix: Server.Message.PathPrefix = @fromBackingInt(@intCast(prefixed_path[0] - 1));1840 const prefix: Server.Message.PathPrefix = @fromBackingInt(@intCast(prefixed_path[0] - 1));
1841 const sub_path = prefixed_path[1..];1841 const sub_path = prefixed_path[1..];
1842 man.addDiscoveredPath(.{1842 man.addDiscoveredPath(.{
1843 .path = .{ .prefixed = .{1843 .discovered_path = .{ .prefixed = .{
1844 .prefix = @intCast(@backingInt(prefix)),1844 .prefix = @intCast(@backingInt(prefix)),
1845 .sub_path = sub_path,1845 .sub_path = sub_path,
1846 } },1846 } },
src/Compilation.zig+39-61
...@@ -701,39 +701,12 @@ pub const Path = struct {...@@ -701,39 +701,12 @@ pub const Path = struct {
701 };701 };
702 }702 }
703703
704 pub fn addToCacheManifestPostHit(p: Path, man: *Cache.Manifest, dirs: *const std.zig.Directories) !void {704 pub fn addToCacheManifestAsDiscovered(
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(
732 p: Path,705 p: Path,
733 man: *Cache.Manifest,706 man: *Cache.Manifest,
734 dirs: *const std.zig.Directories,707 dirs: *const std.zig.Directories,
735 bytes: []const u8,708 contents: ?[]const u8,
736 stat: Cache.File.Stat,709 stat: ?Cache.Manifest.Stat,
737 ) !void {710 ) !void {
738 comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd));711 comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd));
739 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));712 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));
...@@ -741,24 +714,29 @@ pub const Path = struct {...@@ -741,24 +714,29 @@ pub const Path = struct {
741 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));714 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));
742 comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root));715 comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root));
743 comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5);716 comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5);
744 const gpa = man.cache.gpa;717 try man.addDiscoveredPath(.{
745 const prefixed_path: Cache.PrefixedPath = .{718 .discovered_path = .{ .prefixed = .{
746 .prefix = switch (p.root) {719 .prefix = switch (p.root) {
747 .none => {720 .none => {
748 const path = try p.toAbsolute(dirs, gpa);721 const gpa = man.cache.gpa;
749 defer gpa.free(path);722 const path = try p.toAbsolute(dirs, gpa);
750 return man.addFilePostContents(path, bytes, stat);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,
751 },734 },
752 .zig_lib => 1,735 .sub_path = p.sub_path,
753 .local_cache => 2,736 } },
754 .global_cache => 3,737 .contents = contents,
755 .build_root => 4,738 .stat = stat,
756 },739 });
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);
762 }740 }
763};741};
764742
...@@ -2835,20 +2813,18 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -2835,20 +2813,18 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
2835 man.want_shared_lock = false;2813 man.want_shared_lock = false;
2836 }2814 }
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) {
2839 error.Canceled, error.OutOfMemory => |e| return e,2817 error.Canceled, error.OutOfMemory => |e| return e,
2840 error.CacheCheckFailed => switch (man.diagnostic) {2818 error.CacheCheckFailed => switch (man.diagnostic) {
2841 .none => unreachable,2819 .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(
2843 .check_whole_cache,2821 .check_whole_cache,
2844 "failed to check cache: {t} {t}",2822 "failed to check cache: {t} {t}",
2845 .{ man.diagnostic, e },2823 .{ man.diagnostic, e },
2846 ),2824 ),
2847 .file_open, .file_stat, .file_read, .file_hash => |op| {2825 .file_open, .file_stat, .file_read, .file_hash => |op| {
2848 const pp = man.files.keys()[op.file_index].prefixed_path;2826 return comp.setMiscFailure(.check_whole_cache, "failed to check cache: {f} {t} {t}", .{
2849 const prefix = man.cache.prefixes()[pp.prefix];2827 op.path(&man), man.diagnostic, op.err,
2850 return comp.setMiscFailure(.check_whole_cache, "failed to check cache: {f}{s} {t} {t}", .{
2851 prefix, pp.sub_path, man.diagnostic, op.err,
2852 });2828 });
2853 },2829 },
2854 },2830 },
...@@ -2858,7 +2834,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -2858,7 +2834,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
2858 .{},2834 .{},
2859 ),2835 ),
2860 };2836 };
2861 if (is_hit and !ignore_hit) {2837 if (status == .hit and !ignore_hit) {
2862 // In this case the cache hit contains the full set of file system inputs. Nice!2838 // In this case the cache hit contains the full set of file system inputs. Nice!
2863 if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);2839 if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
2864 if (comp.parent_whole_cache) |pwc| {2840 if (comp.parent_whole_cache) |pwc| {
...@@ -3454,8 +3430,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -3454,8 +3430,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
34543430
3455 const opts = comp.cache_use.whole.lf_open_opts;3431 const opts = comp.cache_use.whole.lf_open_opts;
34563432
3457 try man.addOptionalFilePath(opts.linker_script);3433 try man.addInputPathOptional(opts.linker_script, .{});
3458 try man.addOptionalFilePath(opts.version_script);3434 try man.addInputPathOptional(opts.version_script, .{});
3459 man.hash.add(opts.allow_undefined_version);3435 man.hash.add(opts.allow_undefined_version);
3460 man.hash.addOptional(opts.enable_new_dtags);3436 man.hash.addOptional(opts.enable_new_dtags);
34613437
...@@ -3514,7 +3490,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -3514,7 +3490,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
35143490
3515 // Mach-O specific stuff3491 // Mach-O specific stuff
3516 try link.File.MachO.hashAddFrameworks(man, opts.frameworks);3492 try link.File.MachO.hashAddFrameworks(man, opts.frameworks);
3517 try man.addOptionalFilePath(opts.entitlements);3493 try man.addInputPathOptional(opts.entitlements, .{});
3518 man.hash.addOptional(opts.pagezero_size);3494 man.hash.addOptional(opts.pagezero_size);
3519 man.hash.addOptional(opts.headerpad_size);3495 man.hash.addOptional(opts.headerpad_size);
3520 man.hash.add(opts.headerpad_max_install_names);3496 man.hash.add(opts.headerpad_max_install_names);
...@@ -5905,7 +5881,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5905,7 +5881,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5905 const rc_basename = try std.fmt.allocPrint(arena, "{s}.rc", .{src_basename});5881 const rc_basename = try std.fmt.allocPrint(arena, "{s}.rc", .{src_basename});
5906 const res_basename = try std.fmt.allocPrint(arena, "{s}.res", .{src_basename});5882 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: {
5909 // The digest only depends on the .manifest file, so we can5885 // The digest only depends on the .manifest file, so we can
5910 // get the digest now and write the .res directly to the cache5886 // get the digest now and write the .res directly to the cache
5911 const digest = man.final();5887 const digest = man.final();
...@@ -5998,7 +5974,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5998,7 +5974,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
59985974
5999 const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len];5975 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: {
6002 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{});5978 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{});
6003 defer zig_cache_tmp_dir.close(io);5979 defer zig_cache_tmp_dir.close(io);
60045980
...@@ -6055,12 +6031,14 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6055,12 +6031,14 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
6055 return comp.failWin32Resource(win32_resource, "depfile from zig rc has unexpected format", .{});6031 return comp.failWin32Resource(win32_resource, "depfile from zig rc has unexpected format", .{});
6056 }6032 }
6057 const dep_file_path = element.string;6033 const dep_file_path = element.string;
6058 try man.addFilePost(dep_file_path);6034 try man.addDiscoveredPath(.{ .discovered_path = .{ .unresolved = .initCwd(dep_file_path) } });
6059 switch (comp.cache_use) {6035 switch (comp.cache_use) {
6060 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {6036 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {
6061 try whole.cache_manifest_mutex.lock(io);6037 try whole.cache_manifest_mutex.lock(io);
6062 defer whole.cache_manifest_mutex.unlock(io);6038 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 });
6064 },6042 },
6065 .incremental, .none => {},6043 .incremental, .none => {},
6066 }6044 }
src/Zcu.zig+2-2
...@@ -974,7 +974,7 @@ pub const File = struct {...@@ -974,7 +974,7 @@ pub const File = struct {
974 success,974 success,
975 },975 },
976 /// Whether this is populated depends on `status`.976 /// Whether this is populated depends on `status`.
977 stat: Cache.File.Stat,977 stat: Cache.Manifest.Stat,
978978
979 /// Whether this file is the generated file of a "builtin" module. This matters because those979 /// Whether this file is the generated file of a "builtin" module. This matters because those
980 /// files are generated and stored in-nemory rather than being read off-disk. The rest of the980 /// 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 {...@@ -1246,7 +1246,7 @@ pub const EmbedFile = struct {
1246 val: InternPool.Index,1246 val: InternPool.Index,
1247 /// If this is `null` and `val` is `.none`, the file has never been loaded.1247 /// If this is `null` and `val` is `.none`, the file has never been loaded.
1248 err: ?(Io.File.OpenError || Io.File.StatError || Io.File.Reader.Error || error{UnexpectedEof}),1248 err: ?(Io.File.OpenError || Io.File.StatError || Io.File.Reader.Error || error{UnexpectedEof}),
1249 stat: Cache.File.Stat,1249 stat: Cache.Manifest.Stat,
12501250
1251 pub const Index = enum(u32) {1251 pub const Index = enum(u32) {
1252 _,1252 _,
src/Zcu/PerThread.zig+17-21
...@@ -224,11 +224,12 @@ pub fn update(...@@ -224,11 +224,12 @@ pub fn update(
224 const result = res: {224 const result = res: {
225 try whole.cache_manifest_mutex.lock(io);225 try whole.cache_manifest_mutex.lock(io);
226 defer whole.cache_manifest_mutex.unlock(io);226 defer whole.cache_manifest_mutex.unlock(io);
227 if (file.source) |source| {227 break :res file.path.addToCacheManifestAsDiscovered(
228 break :res file.path.addToCacheManifestPostHitContents(man, &comp.dirs, source, file.stat);228 man,
229 } else {229 &comp.dirs,
230 break :res file.path.addToCacheManifestPostHit(man, &comp.dirs);230 file.source,
231 }231 if (file.source != null) file.stat else null,
232 );
232 };233 };
233 result catch |err| switch (err) {234 result catch |err| switch (err) {
234 error.OutOfMemory => |e| return e,235 error.OutOfMemory => |e| return e,
...@@ -2835,26 +2836,21 @@ fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!struct...@@ -2835,26 +2836,21 @@ fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!struct
2835 assert(mem.eql(u8, import_path, "std")); // the single import is of 'std'2836 assert(mem.eql(u8, import_path, "std")); // the single import is of 'std'
2836 }2837 }
28372838
2838 Builtin.updateFileOnDisk(file, comp) catch |err| comp.setMiscFailure(2839 Builtin.updateFileOnDisk(file, comp) catch |err|
2839 .write_builtin_zig,2840 comp.setMiscFailure(.write_builtin_zig, "unable to write {qf}: {t}", .{ file.path.fmt(comp), err });
2840 "unable to write '{f}': {s}",
2841 .{ file.path.fmt(comp), @errorName(err) },
2842 );
2843 return .{2841 return .{
2844 .file = file_index,2842 .file = file_index,
2845 .module_root = mod,2843 .module_root = mod,
2846 };2844 };
2847}2845}
28482846
2847pub const EmbedFileError = error{ImportOutsideModulePath} || Allocator.Error || Io.Cancelable;
2848
2849pub fn embedFile(2849pub fn embedFile(
2850 pt: Zcu.PerThread,2850 pt: Zcu.PerThread,
2851 cur_file: *Zcu.File,2851 cur_file: *Zcu.File,
2852 import_string: []const u8,2852 import_string: []const u8,
2853) error{2853) EmbedFileError!Zcu.EmbedFile.Index {
2854 OutOfMemory,
2855 Canceled,
2856 ImportOutsideModulePath,
2857}!Zcu.EmbedFile.Index {
2858 const zcu = pt.zcu;2854 const zcu = pt.zcu;
2859 const gpa = zcu.gpa;2855 const gpa = zcu.gpa;
28602856
...@@ -2937,7 +2933,7 @@ fn updateEmbedFileInner(...@@ -2937,7 +2933,7 @@ fn updateEmbedFileInner(
2937 };2933 };
2938 defer file.close(io);2934 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
2942 if (ef.val != .none) {2938 if (ef.val != .none) {
2943 const old_stat = ef.stat;2939 const old_stat = ef.stat;
...@@ -2994,10 +2990,7 @@ fn updateEmbedFileInner(...@@ -2994,10 +2990,7 @@ fn updateEmbedFileInner(
2994}2990}
29952991
2996/// Assumes that `path` is allocated into `gpa`. Takes ownership of `path` on success.2992/// Assumes that `path` is allocated into `gpa`. Takes ownership of `path` on success.
2997fn newEmbedFile(2993fn newEmbedFile(pt: Zcu.PerThread, path: Compilation.Path) EmbedFileError!*Zcu.EmbedFile {
2998 pt: Zcu.PerThread,
2999 path: Compilation.Path,
3000) !*Zcu.EmbedFile {
3001 const zcu = pt.zcu;2994 const zcu = pt.zcu;
3002 const comp = zcu.comp;2995 const comp = zcu.comp;
3003 const io = comp.io;2996 const io = comp.io;
...@@ -3034,7 +3027,10 @@ fn newEmbedFile(...@@ -3034,7 +3027,10 @@ fn newEmbedFile(
3034 try whole.cache_manifest_mutex.lock(io);3027 try whole.cache_manifest_mutex.lock(io);
3035 defer whole.cache_manifest_mutex.unlock(io);3028 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 };
3038 }3034 }
30393035
3040 return new_file;3036 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...@@ -251,18 +251,16 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
251 const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name});251 const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name});
252 errdefer gpa.free(final_lib_basename);252 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) {
255 error.CacheCheckFailed => switch (man.diagnostic) {255 error.CacheCheckFailed => switch (man.diagnostic) {
256 .none => unreachable,256 .none => unreachable,
257 .manifest_create, .manifest_read, .manifest_lock => |e| {257 .manifest_create, .manifest_stat, .manifest_read, .manifest_lock => |e| {
258 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {t} {t}", .{ man.diagnostic, e });258 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {t} {t}", .{ man.diagnostic, e });
259 return error.AlreadyReported;259 return error.AlreadyReported;
260 },260 },
261 .file_open, .file_stat, .file_read, .file_hash => |op| {261 .file_open, .file_stat, .file_read, .file_hash => |op| {
262 const pp = man.files.keys()[op.file_index].prefixed_path;262 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {f} {t} {t}", .{
263 const prefix = man.cache.prefixes()[pp.prefix];263 op.path(&man), man.diagnostic, op.err,
264 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {f}{s} {t} {t}", .{
265 prefix, pp.sub_path, man.diagnostic, op.err,
266 });264 });
267 return error.AlreadyReported;265 return error.AlreadyReported;
268 },266 },
...@@ -273,7 +271,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P...@@ -273,7 +271,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
273 return error.AlreadyReported;271 return error.AlreadyReported;
274 },272 },
275 };273 };
276 if (is_hit) {274 if (status == .hit) {
277 const digest = man.final();275 const digest = man.final();
278 const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });276 const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });
279 errdefer gpa.free(sub_path);277 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 {...@@ -1925,15 +1925,21 @@ pub fn hashInputs(man: *Cache.Manifest, link_inputs: []const Input) !void {
1925 man.hash.add(@as(@typeInfo(Input).@"union".tag_type.?, link_input));1925 man.hash.add(@as(@typeInfo(Input).@"union".tag_type.?, link_input));
1926 switch (link_input) {1926 switch (link_input) {
1927 .object, .archive => |obj| {1927 .object, .archive => |obj| {
1928 _ = try man.addOpenedFile(obj.path, obj.file, null);1928 _ = try man.addInputPath(obj.path, .{
1929 .handle = .{ .file = obj.file },
1930 });
1929 man.hash.add(obj.must_link);1931 man.hash.add(obj.must_link);
1930 man.hash.add(obj.hidden);1932 man.hash.add(obj.hidden);
1931 },1933 },
1932 .res => |res| {1934 .res => |res| {
1933 _ = try man.addOpenedFile(res.path, res.file, null);1935 _ = try man.addInputPath(res.path, .{
1936 .handle = .{ .file = res.file },
1937 });
1934 },1938 },
1935 .dso => |dso| {1939 .dso => |dso| {
1936 _ = try man.addOpenedFile(dso.path, dso.file, null);1940 _ = try man.addInputPath(dso.path, .{
1941 .handle = .{ .file = dso.file },
1942 });
1937 man.hash.add(dso.needed);1943 man.hash.add(dso.needed);
1938 man.hash.add(dso.weak);1944 man.hash.add(dso.weak);
1939 man.hash.add(dso.reexport);1945 man.hash.add(dso.reexport);
src/link/Elf.zig+2-2
...@@ -1120,7 +1120,7 @@ fn parseDso(...@@ -1120,7 +1120,7 @@ fn parseDso(
11201120
1121 const handle = dso.file;1121 const handle = dso.file;
11221122
1123 const stat = Stat.fromFs(try handle.stat(io));1123 const stat: Stat = .init(try handle.stat(io));
1124 var header = try SharedObject.parseHeader(gpa, io, diags, dso.path, handle, stat, target);1124 var header = try SharedObject.parseHeader(gpa, io, diags, dso.path, handle, stat, target);
1125 defer header.deinit(gpa);1125 defer header.deinit(gpa);
11261126
...@@ -4407,7 +4407,7 @@ const mem = std.mem;...@@ -4407,7 +4407,7 @@ const mem = std.mem;
4407const Allocator = std.mem.Allocator;4407const Allocator = std.mem.Allocator;
4408const Hash = std.hash.Wyhash;4408const Hash = std.hash.Wyhash;
4409const Path = std.Build.Cache.Path;4409const Path = std.Build.Cache.Path;
4410const Stat = std.Build.Cache.File.Stat;4410const Stat = std.Build.Cache.Manifest.Stat;
44114411
4412const codegen = @import("../codegen.zig");4412const codegen = @import("../codegen.zig");
4413const eh_frame = @import("Elf/eh_frame.zig");4413const eh_frame = @import("Elf/eh_frame.zig");
src/link/Elf/SharedObject.zig+1-1
...@@ -7,7 +7,7 @@ const elf = std.elf;...@@ -7,7 +7,7 @@ const elf = std.elf;
7const log = std.log.scoped(.elf);7const log = std.log.scoped(.elf);
8const mem = std.mem;8const mem = std.mem;
9const Path = std.Build.Cache.Path;9const Path = std.Build.Cache.Path;
10const Stat = std.Build.Cache.File.Stat;10const Stat = std.Build.Cache.Manifest.Stat;
11const Allocator = mem.Allocator;11const Allocator = mem.Allocator;
1212
13const Elf = @import("../Elf.zig");13const Elf = @import("../Elf.zig");
src/main.zig+1-1
...@@ -4878,7 +4878,7 @@ fn cmdTranslateC(...@@ -4878,7 +4878,7 @@ fn cmdTranslateC(
4878 Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err|4878 Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err|
4879 fatal("unable to process {q}: {t}", .{ c_source_file.src_path, err });4879 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)) .{
4882 .digest = man.finalBin(),4882 .digest = man.finalBin(),
4883 .cache_hit = true,4883 .cache_hit = true,
4884 .errors = std.zig.ErrorBundle.empty,4884 .errors = std.zig.ErrorBundle.empty,