authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-08 19:25:07-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-16 13:12:47-07:00
log31b86e53aaa73c6acf522b4a193f600b56a07262
tree7aa3c764567a4df7cdba3eb529b0576c34f83ed8
parent0334f14a13c0d61c00a767e87499292d13ef2af1

std: update to new std.Build.Cache API


1 files changed, 63 insertions(+), 39 deletions(-)

lib/std/Build/Cache.zig+63-39
......@@ -275,10 +275,9 @@ pub const Manifest = struct {
275275 /// When this is null, `Manifest` is in "pre-check" phase. Otherwise it is in "post-check" phase.
276276 manifest_file: ?Io.File,
277277 manifest_dirty: bool,
278 /// Set this flag to true before calling hit() in order to indicate that
279 /// upon a cache hit, the code using the cache will not modify the files
280 /// within the cache directory. This allows multiple processes to utilize
281 /// the same cache directory at the same time.
278 /// Set this flag to true before calling `check` in order to indicate that upon a cache hit, the code
279 /// using the cache will not modify the files within the cache directory. This allows multiple processes
280 /// to utilize the same cache directory at the same time.
282281 want_shared_lock: bool = true,
283282 have_exclusive_lock: bool = false,
284283 // Indicate that we want isProblematicTimestamp to perform a filesystem write in
......@@ -347,12 +346,23 @@ pub const Manifest = struct {
347346 have_stat: bool,
348347 /// Determines whether `File.digest` is populated.
349348 have_digest: bool,
350 contents: enum(usize) {
351 requested = std.math.maxInt(u32) - 1,
352 not_requested = std.math.maxInt(u32),
353 /// Byte offset index into `Manifest.all_input_content`.
354 _,
355 },
349 contents: packed union(u64) {
350 status: enum(u64) {
351 unrequested = std.math.maxInt(u64) - 1,
352 requested = std.math.maxInt(u64),
353 _,
354 pub fn populated(this: @This()) bool {
355 return switch (this) {
356 .unrequested, .requested => false,
357 _ => true,
358 };
359 }
360 },
361 populated: packed struct(u64) {
362 off: u32,
363 len: u32,
364 },
365 } align(@alignOf(u32)),
356366 /// `have_handle` determines whether this is populated.
357367 handle: union {
358368 file: Io.File,
......@@ -362,6 +372,20 @@ pub const Manifest = struct {
362372 /// Index into `Manifest.input_paths`.
363373 pub const Index = enum(u32) {
364374 _,
375
376 pub fn get(i: @This(), manifest: *const Manifest) InputPath {
377 return manifest.input_paths.items[@backingInt(i)];
378 }
379
380 pub fn contents(i: @This(), manifest: *const Manifest) []const u8 {
381 const input_path = get(i, manifest);
382 const populated = switch (input_path.contents.status) {
383 .unrequested => unreachable, // Must request contents before calling `check`.
384 .requested => unreachable, // Must call `check` first.
385 _ => input_path.contents.populated,
386 };
387 return manifest.all_input_content.items[populated.off..][0..populated.len];
388 }
365389 };
366390 };
367391
......@@ -611,8 +635,8 @@ pub const Manifest = struct {
611635 existing_input_file.have_handle = true;
612636 },
613637 }
614 if (options.request_contents) switch (existing_input_file.contents) {
615 .requested, .not_requested => existing_input_file.contents = .requested,
638 if (options.request_contents) switch (existing_input_file.contents.status) {
639 .requested, .unrequested => existing_input_file.contents = .{ .status = .requested },
616640 _ => {},
617641 };
618642 const existing_header = m.files.keys()[gop.index].get(m.contents.items);
......@@ -636,7 +660,7 @@ pub const Manifest = struct {
636660 .file => |opt_file| if (opt_file) |file| .{ .file = file } else undefined,
637661 .dir => |opt_dir| if (opt_dir) |dir| .{ .dir = dir } else undefined,
638662 },
639 .contents = if (options.request_contents) .requested else .not_requested,
663 .contents = .{ .status = if (options.request_contents) .requested else .unrequested },
640664 .have_digest = false,
641665 .have_stat = options.stat != null,
642666 });
......@@ -931,7 +955,7 @@ pub const Manifest = struct {
931955 ) CheckFileError!void {
932956 if (input_path.have_handle) @panic("TODO");
933957 if (input_path.have_stat) @panic("TODO");
934 if (input_path.contents != .not_requested) @panic("TODO");
958 if (input_path.contents.status != .unrequested) @panic("TODO");
935959 if (input_path.request_handle) @panic("TODO");
936960 switch (try checkFile(m, c, file_off, file_path)) {
937961 .hit => {},
......@@ -1727,7 +1751,7 @@ test "cache file and then recall it" {
17271751 _ = try ch.addInputPath(.initCwd(temp_file), .{});
17281752
17291753 // There should be nothing in the cache
1730 try testing.expectEqual(false, try ch.hit(.none));
1754 try testing.expectEqual(.miss, try ch.check(.none));
17311755
17321756 digest1 = ch.final();
17331757 try ch.writeManifest();
......@@ -1742,7 +1766,7 @@ test "cache file and then recall it" {
17421766 _ = try ch.addInputPath(.initCwd(temp_file), .{});
17431767
17441768 // Cache hit! We just "built" the same file
1745 try testing.expect(try ch.hit(.none));
1769 try testing.expectEqual(.hit, try ch.check(.none));
17461770 digest2 = ch.final();
17471771
17481772 try testing.expectEqual(false, ch.have_exclusive_lock);
......@@ -1788,40 +1812,40 @@ test "check that changing a file makes cache fail" {
17881812 defer cache.manifest_dir.close(io);
17891813
17901814 {
1791 var ch = cache.obtain();
1792 defer ch.deinit();
1815 var man = cache.obtain();
1816 defer man.deinit();
17931817
1794 ch.hash.addBytes("1234");
1795 const temp_file_idx = try ch.addInputPath(.initCwd(temp_file), .{ .request_contents = true });
1818 man.hash.addBytes("1234");
1819 const temp_file_idx = try man.addInputPath(.initCwd(temp_file), .{ .request_contents = true });
17961820
17971821 // There should be nothing in the cache
1798 try testing.expectEqual(false, try ch.hit(.none));
1822 try testing.expectEqual(.miss, try man.check(.none));
17991823
1800 try testing.expect(mem.eql(u8, original_temp_file_contents, ch.files.keys()[temp_file_idx].contents.?));
1824 try testing.expectEqualStrings(original_temp_file_contents, temp_file_idx.contents(&man));
18011825
1802 digest1 = ch.final();
1826 digest1 = man.final();
18031827
1804 try ch.writeManifest();
1828 try man.writeManifest();
18051829 }
18061830
18071831 try tmp.dir.writeFile(io, .{ .sub_path = temp_file, .data = updated_temp_file_contents });
18081832
18091833 {
1810 var ch = cache.obtain();
1811 defer ch.deinit();
1834 var man = cache.obtain();
1835 defer man.deinit();
18121836
1813 ch.hash.addBytes("1234");
1814 const temp_file_idx = try ch.addInputPath(.initCwd(temp_file), .{ .request_contents = true });
1837 man.hash.addBytes("1234");
1838 const temp_file_idx = try man.addInputPath(.initCwd(temp_file), .{ .request_contents = true });
18151839
18161840 // A file that we depend on has been updated, so the cache should not contain an entry for it
1817 try testing.expectEqual(false, try ch.hit(.none));
1841 try testing.expectEqual(.miss, try man.check(.none));
18181842
18191843 // The cache system does not keep the contents of re-hashed input files.
1820 try testing.expect(ch.files.keys()[temp_file_idx].contents == null);
1844 try testing.expectEqual(false, temp_file_idx.get(&man).contents.status.populated());
18211845
1822 digest2 = ch.final();
1846 digest2 = man.final();
18231847
1824 try ch.writeManifest();
1848 try man.writeManifest();
18251849 }
18261850
18271851 try testing.expect(!mem.eql(u8, digest1[0..], digest2[0..]));
......@@ -1858,7 +1882,7 @@ test "no file inputs" {
18581882 man.hash.addBytes("1234");
18591883
18601884 // There should be nothing in the cache
1861 try testing.expectEqual(false, try man.check(.none));
1885 try testing.expectEqual(.miss, try man.check(.none));
18621886
18631887 digest1 = man.final();
18641888
......@@ -1870,7 +1894,7 @@ test "no file inputs" {
18701894
18711895 man.hash.addBytes("1234");
18721896
1873 try testing.expect(try man.check(.none));
1897 try testing.expectEqual(.hit, try man.check(.none));
18741898 digest2 = man.final();
18751899 try testing.expectEqual(false, man.have_exclusive_lock);
18761900 }
......@@ -1922,9 +1946,9 @@ test "Manifest with files added after initial hash work" {
19221946 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
19231947
19241948 // There should be nothing in the cache
1925 try testing.expectEqual(false, try ch.hit(.none));
1949 try testing.expectEqual(.miss, try ch.check(.none));
19261950
1927 _ = try ch.addDiscoveredPath(temp_file2);
1951 _ = try ch.addDiscoveredPath(.{ .discovered_path = .{ .unresolved = .initCwd(temp_file2) } });
19281952
19291953 digest1 = ch.final();
19301954 try ch.writeManifest();
......@@ -1936,7 +1960,7 @@ test "Manifest with files added after initial hash work" {
19361960 ch.hash.addBytes("1234");
19371961 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
19381962
1939 try testing.expect(try ch.hit(.none));
1963 try testing.expect(.hit == try ch.check(.none));
19401964 digest2 = ch.final();
19411965
19421966 try testing.expectEqual(false, ch.have_exclusive_lock);
......@@ -1960,9 +1984,9 @@ test "Manifest with files added after initial hash work" {
19601984 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
19611985
19621986 // A file that we depend on has been updated, so the cache should not contain an entry for it
1963 try testing.expectEqual(false, try ch.hit(.none));
1987 try testing.expectEqual(.miss, try ch.check(.none));
19641988
1965 _ = try ch.addDiscoveredPath(temp_file2);
1989 _ = try ch.addDiscoveredPath(.{ .discovered_path = .{ .unresolved = .initCwd(temp_file2) } });
19661990
19671991 digest3 = ch.final();
19681992