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 {...@@ -275,10 +275,9 @@ pub const Manifest = struct {
275 /// When this is null, `Manifest` is in "pre-check" phase. Otherwise it is in "post-check" phase.275 /// When this is null, `Manifest` is in "pre-check" phase. Otherwise it is in "post-check" phase.
276 manifest_file: ?Io.File,276 manifest_file: ?Io.File,
277 manifest_dirty: bool,277 manifest_dirty: bool,
278 /// Set this flag to true before calling hit() in order to indicate that278 /// Set this flag to true before calling `check` in order to indicate that upon a cache hit, the code
279 /// upon a cache hit, the code using the cache will not modify the files279 /// using the cache will not modify the files within the cache directory. This allows multiple processes
280 /// within the cache directory. This allows multiple processes to utilize280 /// to utilize the same cache directory at the same time.
281 /// the same cache directory at the same time.
282 want_shared_lock: bool = true,281 want_shared_lock: bool = true,
283 have_exclusive_lock: bool = false,282 have_exclusive_lock: bool = false,
284 // Indicate that we want isProblematicTimestamp to perform a filesystem write in283 // Indicate that we want isProblematicTimestamp to perform a filesystem write in
...@@ -347,12 +346,23 @@ pub const Manifest = struct {...@@ -347,12 +346,23 @@ pub const Manifest = struct {
347 have_stat: bool,346 have_stat: bool,
348 /// Determines whether `File.digest` is populated.347 /// Determines whether `File.digest` is populated.
349 have_digest: bool,348 have_digest: bool,
350 contents: enum(usize) {349 contents: packed union(u64) {
351 requested = std.math.maxInt(u32) - 1,350 status: enum(u64) {
352 not_requested = std.math.maxInt(u32),351 unrequested = std.math.maxInt(u64) - 1,
353 /// Byte offset index into `Manifest.all_input_content`.352 requested = std.math.maxInt(u64),
354 _,353 _,
355 },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)),
356 /// `have_handle` determines whether this is populated.366 /// `have_handle` determines whether this is populated.
357 handle: union {367 handle: union {
358 file: Io.File,368 file: Io.File,
...@@ -362,6 +372,20 @@ pub const Manifest = struct {...@@ -362,6 +372,20 @@ pub const Manifest = struct {
362 /// Index into `Manifest.input_paths`.372 /// Index into `Manifest.input_paths`.
363 pub const Index = enum(u32) {373 pub const Index = enum(u32) {
364 _,374 _,
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 }
365 };389 };
366 };390 };
367391
...@@ -611,8 +635,8 @@ pub const Manifest = struct {...@@ -611,8 +635,8 @@ pub const Manifest = struct {
611 existing_input_file.have_handle = true;635 existing_input_file.have_handle = true;
612 },636 },
613 }637 }
614 if (options.request_contents) switch (existing_input_file.contents) {638 if (options.request_contents) switch (existing_input_file.contents.status) {
615 .requested, .not_requested => existing_input_file.contents = .requested,639 .requested, .unrequested => existing_input_file.contents = .{ .status = .requested },
616 _ => {},640 _ => {},
617 };641 };
618 const existing_header = m.files.keys()[gop.index].get(m.contents.items);642 const existing_header = m.files.keys()[gop.index].get(m.contents.items);
...@@ -636,7 +660,7 @@ pub const Manifest = struct {...@@ -636,7 +660,7 @@ pub const Manifest = struct {
636 .file => |opt_file| if (opt_file) |file| .{ .file = file } else undefined,660 .file => |opt_file| if (opt_file) |file| .{ .file = file } else undefined,
637 .dir => |opt_dir| if (opt_dir) |dir| .{ .dir = dir } else undefined,661 .dir => |opt_dir| if (opt_dir) |dir| .{ .dir = dir } else undefined,
638 },662 },
639 .contents = if (options.request_contents) .requested else .not_requested,663 .contents = .{ .status = if (options.request_contents) .requested else .unrequested },
640 .have_digest = false,664 .have_digest = false,
641 .have_stat = options.stat != null,665 .have_stat = options.stat != null,
642 });666 });
...@@ -931,7 +955,7 @@ pub const Manifest = struct {...@@ -931,7 +955,7 @@ pub const Manifest = struct {
931 ) CheckFileError!void {955 ) CheckFileError!void {
932 if (input_path.have_handle) @panic("TODO");956 if (input_path.have_handle) @panic("TODO");
933 if (input_path.have_stat) @panic("TODO");957 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");
935 if (input_path.request_handle) @panic("TODO");959 if (input_path.request_handle) @panic("TODO");
936 switch (try checkFile(m, c, file_off, file_path)) {960 switch (try checkFile(m, c, file_off, file_path)) {
937 .hit => {},961 .hit => {},
...@@ -1727,7 +1751,7 @@ test "cache file and then recall it" {...@@ -1727,7 +1751,7 @@ test "cache file and then recall it" {
1727 _ = try ch.addInputPath(.initCwd(temp_file), .{});1751 _ = try ch.addInputPath(.initCwd(temp_file), .{});
17281752
1729 // There should be nothing in the cache1753 // 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
1732 digest1 = ch.final();1756 digest1 = ch.final();
1733 try ch.writeManifest();1757 try ch.writeManifest();
...@@ -1742,7 +1766,7 @@ test "cache file and then recall it" {...@@ -1742,7 +1766,7 @@ test "cache file and then recall it" {
1742 _ = try ch.addInputPath(.initCwd(temp_file), .{});1766 _ = try ch.addInputPath(.initCwd(temp_file), .{});
17431767
1744 // Cache hit! We just "built" the same file1768 // 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));
1746 digest2 = ch.final();1770 digest2 = ch.final();
17471771
1748 try testing.expectEqual(false, ch.have_exclusive_lock);1772 try testing.expectEqual(false, ch.have_exclusive_lock);
...@@ -1788,40 +1812,40 @@ test "check that changing a file makes cache fail" {...@@ -1788,40 +1812,40 @@ test "check that changing a file makes cache fail" {
1788 defer cache.manifest_dir.close(io);1812 defer cache.manifest_dir.close(io);
17891813
1790 {1814 {
1791 var ch = cache.obtain();1815 var man = cache.obtain();
1792 defer ch.deinit();1816 defer man.deinit();
17931817
1794 ch.hash.addBytes("1234");1818 man.hash.addBytes("1234");
1795 const temp_file_idx = try ch.addInputPath(.initCwd(temp_file), .{ .request_contents = true });1819 const temp_file_idx = try man.addInputPath(.initCwd(temp_file), .{ .request_contents = true });
17961820
1797 // There should be nothing in the cache1821 // 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();
1805 }1829 }
18061830
1807 try tmp.dir.writeFile(io, .{ .sub_path = temp_file, .data = updated_temp_file_contents });1831 try tmp.dir.writeFile(io, .{ .sub_path = temp_file, .data = updated_temp_file_contents });
18081832
1809 {1833 {
1810 var ch = cache.obtain();1834 var man = cache.obtain();
1811 defer ch.deinit();1835 defer man.deinit();
18121836
1813 ch.hash.addBytes("1234");1837 man.hash.addBytes("1234");
1814 const temp_file_idx = try ch.addInputPath(.initCwd(temp_file), .{ .request_contents = true });1838 const temp_file_idx = try man.addInputPath(.initCwd(temp_file), .{ .request_contents = true });
18151839
1816 // A file that we depend on has been updated, so the cache should not contain an entry for it1840 // 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
1819 // The cache system does not keep the contents of re-hashed input files.1843 // 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();
1825 }1849 }
18261850
1827 try testing.expect(!mem.eql(u8, digest1[0..], digest2[0..]));1851 try testing.expect(!mem.eql(u8, digest1[0..], digest2[0..]));
...@@ -1858,7 +1882,7 @@ test "no file inputs" {...@@ -1858,7 +1882,7 @@ test "no file inputs" {
1858 man.hash.addBytes("1234");1882 man.hash.addBytes("1234");
18591883
1860 // There should be nothing in the cache1884 // 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
1863 digest1 = man.final();1887 digest1 = man.final();
18641888
...@@ -1870,7 +1894,7 @@ test "no file inputs" {...@@ -1870,7 +1894,7 @@ test "no file inputs" {
18701894
1871 man.hash.addBytes("1234");1895 man.hash.addBytes("1234");
18721896
1873 try testing.expect(try man.check(.none));1897 try testing.expectEqual(.hit, try man.check(.none));
1874 digest2 = man.final();1898 digest2 = man.final();
1875 try testing.expectEqual(false, man.have_exclusive_lock);1899 try testing.expectEqual(false, man.have_exclusive_lock);
1876 }1900 }
...@@ -1922,9 +1946,9 @@ test "Manifest with files added after initial hash work" {...@@ -1922,9 +1946,9 @@ test "Manifest with files added after initial hash work" {
1922 _ = try ch.addInputPath(.initCwd(temp_file1), .{});1946 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
19231947
1924 // There should be nothing in the cache1948 // 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
1929 digest1 = ch.final();1953 digest1 = ch.final();
1930 try ch.writeManifest();1954 try ch.writeManifest();
...@@ -1936,7 +1960,7 @@ test "Manifest with files added after initial hash work" {...@@ -1936,7 +1960,7 @@ test "Manifest with files added after initial hash work" {
1936 ch.hash.addBytes("1234");1960 ch.hash.addBytes("1234");
1937 _ = try ch.addInputPath(.initCwd(temp_file1), .{});1961 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
19381962
1939 try testing.expect(try ch.hit(.none));1963 try testing.expect(.hit == try ch.check(.none));
1940 digest2 = ch.final();1964 digest2 = ch.final();
19411965
1942 try testing.expectEqual(false, ch.have_exclusive_lock);1966 try testing.expectEqual(false, ch.have_exclusive_lock);
...@@ -1960,9 +1984,9 @@ test "Manifest with files added after initial hash work" {...@@ -1960,9 +1984,9 @@ test "Manifest with files added after initial hash work" {
1960 _ = try ch.addInputPath(.initCwd(temp_file1), .{});1984 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
19611985
1962 // A file that we depend on has been updated, so the cache should not contain an entry for it1986 // 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
1967 digest3 = ch.final();1991 digest3 = ch.final();
19681992