authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-03 15:02:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-04 17:42:21-07:00
logfc1d90e2a1fdc92c020c3d1d6af6a3f768d8a9d2
tree2101c70c57bc6324a36563e8272e502864efbc2c
parent8ba8b0af6bfa93760ae325734a347670b815ab42

std.Build.Cache: fix some compilation errors from rewrite


17 files changed, 268 insertions(+), 205 deletions(-)

lib/compiler/Maker.zig+10-10
......@@ -702,8 +702,8 @@ pub fn main(init: process.Init.Minimal) !void {
702702 configure: while (true) {
703703 // Set of files that, if modified, imply that recompiling and rerunning
704704 // configurer is needed.
705 var configure_source_files: Cache.Manifest.Files = .empty;
706 defer Cache.Manifest.freeFiles(gpa, &configure_source_files);
705 var configure_source_files: Cache.Manifest.SelfContainedFiles = .empty;
706 defer configure_source_files.deinit(gpa);
707707
708708 // If this fails, we can still start the server and wait for user
709709 // to request a rebuild. If it returns error.FailedButCacheIntact
......@@ -1043,7 +1043,7 @@ const ConfigureOptions = struct {
10431043 fetch_only: bool,
10441044 print_configuration: PrintConfiguration,
10451045 forks: []Fork,
1046 src_files: *Cache.Manifest.Files,
1046 src_files: *Cache.Manifest.SelfContainedFiles,
10471047};
10481048
10491049fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
......@@ -1398,7 +1398,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
13981398 defer compile_prog_node.end();
13991399
14001400 if (config_man) |man| {
1401 if (try man.hit(compile_prog_node)) {
1401 if (.hit == try man.check(compile_prog_node)) {
14021402 const digest = man.final();
14031403 const path: Path = .{
14041404 .root_dir = graph.local_cache_root,
......@@ -1497,11 +1497,11 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
14971497 }
14981498
14991499 if (config_man) |man| for (configuration.path_deps) |path_dep| {
1500 switch (path_dep.flags.mode) {
1501 .directory => {}, // TODO
1502 .contents => try man.addPathPost(try confPathDepToCachePath(arena, graph, &configuration, path_dep)),
1503 .metadata => {}, // TODO
1504 }
1500 const path = try confPathDepToCachePath(arena, graph, &configuration, path_dep);
1501 try man.addPathPost(path, .{
1502 .handle = if (path_dep.flags.is_directory) .{ .dir = null } else .{ .file = null },
1503 .metadata_only = path_dep.flags.metadata_only,
1504 });
15051505 };
15061506
15071507 // If it is poisoned, there is no point in moving it to cached
......@@ -2220,7 +2220,7 @@ fn resolveTopLevelSteps(maker: *Maker, step_names: []const []const u8) ![]const
22202220fn prepare(
22212221 maker: *Maker,
22222222 step_indices: []const Configuration.Step.Index,
2223 configure_source_files: *const Cache.Manifest.Files,
2223 configure_source_files: *const Cache.Manifest.SelfContainedFiles,
22242224) !void {
22252225 const gpa = maker.gpa;
22262226 const graph = maker.graph;
lib/compiler/Maker/Step.zig+17-19
......@@ -726,8 +726,9 @@ pub fn handleChildProcessTerm(s: *Step, maker: *Maker, term: std.process.Child.T
726726/// Prefer `cacheHitWatched` unless you already added watch inputs
727727/// separately from using the cache system.
728728pub fn cacheHit(s: *Step, maker: *Maker, man: *Cache.Manifest, parent_progress_node: std.Progress.Node) !bool {
729 s.result_cached = man.hit(parent_progress_node) catch |err| return failWithCacheError(s, maker, man, err);
730 return s.result_cached;
729 const hit = .hit == (man.check(parent_progress_node) catch |err| return failWithCacheError(s, maker, man, err));
730 s.result_cached = hit;
731 return hit;
731732}
732733
733734/// Clears previous watch inputs, if any, and then populates watch inputs from
......@@ -735,32 +736,29 @@ pub fn cacheHit(s: *Step, maker: *Maker, man: *Cache.Manifest, parent_progress_n
735736///
736737/// Must be accompanied with `writeManifestAndWatch`.
737738pub fn cacheHitWatched(s: *Step, maker: *Maker, man: *Cache.Manifest, parent_progress_node: std.Progress.Node) !bool {
738 const is_hit = man.hit(parent_progress_node) catch |err| return failWithCacheError(s, maker, man, err);
739 s.result_cached = is_hit;
739 const hit = .hit == (man.check(parent_progress_node) catch |err| return failWithCacheError(s, maker, man, err));
740 s.result_cached = hit;
740741 // The above call to hit() populates the manifest with files, so in case of
741742 // a hit, we need to populate watch inputs.
742 if (is_hit) try setWatchInputsFromManifest(s, maker, man);
743 return is_hit;
743 if (hit) try setWatchInputsFromManifest(s, maker, man);
744 return hit;
744745}
745746
746747fn failWithCacheError(
747748 s: *Step,
748749 maker: *Maker,
749750 man: *const Cache.Manifest,
750 err: Cache.Manifest.HitError,
751 err: Cache.Manifest.Check.Error,
751752) error{ OutOfMemory, Canceled, MakeFailed } {
752753 switch (err) {
753754 error.CacheCheckFailed => switch (man.diagnostic) {
754755 .none => unreachable,
755 .manifest_create, .manifest_read, .manifest_lock => |e| return s.fail(maker, "failed checking cache: {t} {t}", .{
756 man.diagnostic, e,
757 }),
756 .manifest_create, .manifest_read, .manifest_lock => |e| {
757 return s.fail(maker, "failed checking cache: {t} {t}", .{ man.diagnostic, e });
758 },
758759 .file_open, .file_stat, .file_read, .file_hash => |op| {
759 const pp = man.files.keys()[op.file_index].prefixed_path;
760 const prefix = man.cache.prefixes()[pp.prefix].path orelse "";
761 return s.fail(maker, "failed checking cache: {s}{c}{s} {t} {t}", .{
762 prefix, Dir.path.sep, pp.sub_path, man.diagnostic, op.err,
763 });
760 const path = op.path(man);
761 return s.fail(maker, "failed checking cache: {f} {t} {t}", .{ path, man.diagnostic, op.err });
764762 },
765763 },
766764 error.OutOfMemory, error.Canceled => |e| return e,
......@@ -795,17 +793,17 @@ pub fn setWatchInputsFromManifest(s: *Step, maker: *Maker, man: *Cache.Manifest)
795793pub fn setWatchInputsFromManifestFiles(
796794 s: *Step,
797795 maker: *Maker,
798 files: *const Cache.Manifest.Files,
796 scf: *const Cache.Manifest.SelfContainedFiles,
799797 prefixes: []const Cache.Directory,
800798) !void {
801799 const graph = maker.graph;
802800 const arena = graph.arena; // TODO don't leak into process arena
803801 clearWatchInputs(s, maker);
804 for (files.keys()) |file| {
802 for (scf.files.keys()) |file_offset| {
805803 // The file path data is freed when the cache manifest is cleaned up at the end of `make`.
806 const sub_path = try arena.dupe(u8, file.prefixed_path.sub_path);
804 const sub_path = try arena.dupe(u8, scf.path(file_offset));
807805 try addWatchInputFromPath(s, maker, .{
808 .root_dir = prefixes[file.prefixed_path.prefix],
806 .root_dir = prefixes[file_offset.get(scf.contents.items).flags.prefix],
809807 .sub_path = Dir.path.dirname(sub_path) orelse "",
810808 }, Dir.path.basename(sub_path));
811809 }
lib/compiler/Maker/Step/ObjCopy.zig+1-1
......@@ -34,7 +34,7 @@ pub fn make(
3434 defer man.deinit();
3535
3636 const input_path = try maker.resolveLazyPath(arena, input_lazy_path, step_index);
37 _ = try man.addFilePath(input_path, null);
37 _ = try man.addInputPath(input_path, .{});
3838 man.hash.addOptionalBytes(only_section);
3939 man.hash.addOptionalBytes(opt_basename);
4040 man.hash.addOptionalBytes(opt_debug_basename);
lib/compiler/Maker/Step/Options.zig+1-1
......@@ -42,7 +42,7 @@ pub fn make(
4242 const lazy_path = arg.path.get(conf);
4343 try step.addWatchInput(maker, arena, lazy_path);
4444 const arg_path = try maker.resolveLazyPath(arena, lazy_path, step_index);
45 _ = try man.addFilePath(arg_path, null);
45 _ = try man.addInputPath(arg_path, .{});
4646 try args_bytes.print(arena, "pub const {f}: []const u8 = \"{f}\";\n", .{
4747 std.zig.fmtId(name), arg_path.fmtEscapeString(),
4848 });
lib/compiler/Maker/Step/Run.zig+5-5
......@@ -97,7 +97,7 @@ pub fn make(
9797 man.hash.add(arg.flags.make_absolute);
9898 man.hash.addBytesZ(prefix);
9999 man.hash.addBytesZ(suffix);
100 _ = try man.addFilePath(file_path, null);
100 _ = try man.addInputPath(file_path, .{});
101101 },
102102 .path_directory => {
103103 const prefix = if (arg.prefix.value) |p| p.slice(conf) else "";
......@@ -135,7 +135,7 @@ pub fn make(
135135 argv_list.appendAssumeCapacity(result.written());
136136 man.hash.addBytesZ(prefix);
137137 man.hash.addBytesZ(suffix);
138 _ = try man.addFilePath(file_path, null);
138 _ = try man.addInputPath(file_path, .{});
139139 },
140140 .artifact => {
141141 const prefix = if (arg.prefix.value) |p| p.slice(conf) else "";
......@@ -155,7 +155,7 @@ pub fn make(
155155 man.hash.add(arg.flags.make_absolute);
156156 man.hash.addBytesZ(prefix);
157157 man.hash.addBytesZ(suffix);
158 _ = try man.addFilePath(file_path, null);
158 _ = try man.addInputPath(file_path, .{});
159159 },
160160 .output_file, .output_directory => {
161161 const prefix = if (arg.prefix.value) |p| p.slice(conf) else "";
......@@ -211,7 +211,7 @@ pub fn make(
211211 },
212212 .lazy_path => |lazy_path| {
213213 const file_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index);
214 _ = try man.addFilePath(file_path, null);
214 _ = try man.addInputPath(file_path, .{});
215215 },
216216 .none => {},
217217 }
......@@ -240,7 +240,7 @@ pub fn make(
240240
241241 for (conf_run.file_inputs.slice) |lazy_path| {
242242 const file_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index);
243 _ = try man.addFilePath(file_path, null);
243 _ = try man.addInputPath(file_path, .{});
244244 }
245245
246246 if (conf_run.cwd.value) |lazy_path| {
lib/compiler/Maker/Step/WriteFile.zig+2-2
......@@ -55,7 +55,7 @@ pub fn make(
5555 man.hash.addBytes(copy.sub_path.slice(conf));
5656 const src_lazy_path = copy.src_file.get(conf);
5757 const source_path = try maker.resolveLazyPath(arena, src_lazy_path, step_index);
58 _ = try man.addFilePath(source_path, null);
58 _ = try man.addInputPath(source_path, .{});
5959 try step.addWatchInput(maker, arena, src_lazy_path);
6060 }
6161
......@@ -96,7 +96,7 @@ pub fn make(
9696 },
9797 .file => {
9898 const entry_path = try src_dir_path.join(arena, entry.path);
99 _ = try man.addFilePath(entry_path, null);
99 _ = try man.addInputPath(entry_path, .{});
100100 total_items += 1;
101101 },
102102 else => continue,
lib/std/Build/Cache.zig+192-136
......@@ -294,7 +294,7 @@ pub const Manifest = struct {
294294 files: Files = .empty,
295295 /// Indexes line up with `files`, but only up until `hit` is called. Uses
296296 /// `Cache.gpa`.
297 input_files: std.ArrayList(InputFile) = .empty,
297 input_paths: std.ArrayList(InputPath) = .empty,
298298 diagnostic: Diagnostic = .none,
299299 /// Keeps track of the last time we performed a file system write to observe
300300 /// what time the file system thinks it is, according to its own granularity.
......@@ -304,11 +304,11 @@ pub const Manifest = struct {
304304 /// final terminating byte can be added without allocation. Uses
305305 /// `Cache.gpa`.
306306 contents: std.ArrayList(u8) = .empty,
307 /// All contents from all `input_files` whose contents were requested,
307 /// All contents from all `input_paths` whose contents were requested,
308308 /// concatenated. Total byte size will be less than `max_input_content_len`
309309 /// otherwise an error is returned.
310310 ///
311 /// Data is invalidated when `addFilePost` is called.
311 /// Data is invalidated when `addPathPost` is called.
312312 all_input_content: std.ArrayList(u8) = .empty,
313313 max_input_content_len: usize = std.math.maxInt(u32),
314314
......@@ -328,23 +328,24 @@ pub const Manifest = struct {
328328 InvalidFormat,
329329 } || Allocator.Error || Io.Cancelable;
330330
331 fn fail(c: *Check, m: *Manifest, diagnostic: Diagnostic) void {
332 if (!@atomicRmw(bool, &c.diagnostic_lock, .Xchg, true, .unordered)) {
331 fn fail(c: *Check, m: *Manifest, diagnostic: Diagnostic) error{CacheCheckFailed} {
332 if (!@atomicRmw(bool, &c.diagnostic_lock, .Xchg, true, .monotonic)) {
333333 m.diagnostic = diagnostic;
334334 }
335 return error.CacheCheckFailed;
335336 }
336337 };
337338
338339 pub const Files = std.array_hash_map.Custom(File.Offset, void, File.HashContext, false);
339340
340 /// Source files whose prefix and relative path are included when computing
341 /// the cache manifest digest. It's the information needed to lazily hash
342 /// the input files only when a cache miss occurs.
341 /// Source files and directories whose prefix and relative path are
342 /// included when computing the cache manifest digest. It's the information
343 /// needed to lazily hash the input files only when a cache miss occurs.
343344 ///
344345 /// `File.prefix`, `File.path`, and `File.mode` will be always populated,
345346 /// but the other fields of `File` will be populated depending on the
346 /// fields of `InputFile`.
347 pub const InputFile = struct {
347 /// fields of `InputPath`.
348 pub const InputPath = struct {
348349 request_handle: bool,
349350 have_handle: bool,
350351 /// Determines whether `File.size`, `File.inode`, and `File.mtime` are populated.
......@@ -360,7 +361,7 @@ pub const Manifest = struct {
360361 /// `have_handle` determines whether this is populated.
361362 handle: Io.File,
362363
363 /// Index into `Manifest.input_files`.
364 /// Index into `Manifest.input_paths`.
364365 pub const Index = enum(u32) {
365366 _,
366367 };
......@@ -406,13 +407,13 @@ pub const Manifest = struct {
406407 pub const Offset = enum(u32) {
407408 _,
408409
409 pub fn get(offset: Offset, m: *const Manifest) *File {
410 return @ptrCast(m.contents.items[@backingInt(offset)..][0..@sizeOf(File)]);
410 pub fn get(offset: Offset, contents: []u8) *File {
411 return @ptrCast(@alignCast(contents.items[@backingInt(offset)..][0..@sizeOf(File)]));
411412 }
412413
413 pub fn getFallible(offset: Offset, m: *const Manifest) error{EndOfStream}!*File {
414 if (@backingInt(offset) + @sizeOf(File) >= m.contents.len) return error.EndOfStream;
415 return get(offset, m);
414 pub fn getFallible(offset: Offset, contents: []u8) error{InvalidFormat}!*File {
415 if (@backingInt(offset) + @sizeOf(File) >= contents.items.len) return error.InvalidFormat;
416 return get(offset, contents);
416417 }
417418 };
418419
......@@ -432,25 +433,6 @@ pub const Manifest = struct {
432433 }
433434 };
434435
435 pub fn path(file: *const File) [:0]const u8 {
436 return pathFallible(file) catch unreachable;
437 }
438
439 pub fn pathFallible(file: *const File) error{EndOfStream}![:0]const u8 {
440 const ptr: [*]u8 = &file.path_start;
441 const len = mem.findScalar(u8, ptr, 0) orelse return error.EndOfStream;
442 return ptr[0..len :0];
443 }
444
445 fn manifestDigestHash(file: *const File, hasher: *Hasher) void {
446 const path_ptr: [*]u8 = &file.path_start;
447 const path_len = mem.findScalar(u8, path_ptr, 0).?;
448 comptime assert(@offsetOf(File, "path_start") - @offsetOf(File, "flags") == 1);
449 // Includes flags and sentinel.
450 const hash_string = (path_ptr - 1)[0 .. path_len + 2];
451 hasher.update(hash_string);
452 }
453
454436 fn setStat(file: *File, m: *Manifest, stat: Stat) Io.Cancelable!void {
455437 file.size = stat.size;
456438 file.inode = stat.inode;
......@@ -490,6 +472,16 @@ pub const Manifest = struct {
490472 pub const FileOp = struct {
491473 file_offset: File.Offset,
492474 err: anyerror,
475
476 /// Returned `Path` references `Manifest.contents`.
477 pub fn path(fo: FileOp, manifest: *const Manifest) Path {
478 const contents = manifest.contents.items;
479 const prefix = fo.file_offset.get(contents).flags.prefix;
480 return .{
481 .root_dir = manifest.cache.prefixes()[prefix],
482 .sub_path = filePath(contents, fo.file_offset),
483 };
484 }
493485 };
494486 };
495487
......@@ -499,42 +491,49 @@ pub const Manifest = struct {
499491 mtime: Io.Timestamp,
500492 };
501493
502 pub const AddInputFileOptions = struct {
503 /// If `is_directory` is true, this handle must be opened with
504 /// iteration capability.
505 handle: ?Io.File = null,
494 pub const PathHandle = union(enum) {
495 file: ?Io.File,
496 /// If provided, this handle must be opened with iteration capability.
497 dir: ?Io.Dir,
498 };
499
500 pub const AddInputPathOptions = struct {
501 handle: PathHandle = .{ .file = null },
506502 stat: ?Stat = null,
507503 request_handle: bool = false,
508 /// Can request file or directory contents depending on `is_directory`.
504 /// Can request file or directory contents depending on `handle`.
509505 request_contents: bool = false,
510 /// Contents of a directory are considered to be the sorted list of
511 /// file names of direct entries, separated by null byte. Each file name
512 /// is prefixed by `Io.File.Kind` byte, +1 so that the zero tag is
513 /// not aliased by the entry separator.
514 is_directory: bool = false,
515506 /// Content hashing skipped; any difference in metadata implies cache
516507 /// miss.
517508 metadata_only: bool = false,
518509 };
519510
520 pub const AddInputFileError = error{
511 pub const AddInputPathError = error{
521512 /// The same file path has been added to the cache manifest both as a
522513 /// directory and as a normal file, making the intended caching
523514 /// behavior ambiguous.
524515 IsDirectoryAmbiguous,
525516 } || Allocator.Error;
526517
527 /// Add a file as a dependency of process being cached. When `hit` is
528 /// called, the file's contents will be checked to ensure that it matches
529 /// the contents from previous times.
518 /// Add a file or directory path as a dependency of process being cached.
519 /// When `hit` is called, the contents will be checked to ensure
520 /// that it matches the contents from previous times.
530521 ///
531522 /// The contents of the input file may be requested and subsequently
532 /// obtained via methods of the returned `InputFile.Index` after calling
523 /// obtained via methods of the returned `InputPath.Index` after calling
533524 /// `hit`.
534 pub fn addInputFile(m: *Manifest, path: Path, options: AddInputFileOptions) Allocator.Error!InputFile.Index {
525 ///
526 /// Contents of a directory are considered to be the sorted list of file
527 /// names of direct entries, separated by null byte. Each file name is
528 /// prefixed by `Io.File.Kind` byte, +1 so that the zero tag is not aliased
529 /// by the entry separator.
530 ///
531 /// See also:
532 /// * `addPathPost`
533 pub fn addInputPath(m: *Manifest, path: Path, options: AddInputPathOptions) AddInputPathError!InputPath.Index {
535534 const gpa = m.cache.gpa;
536535 try m.files.ensureUnusedCapacity(gpa, 1);
537 try m.input_files.ensureUnusedCapacity(gpa, 1);
536 try m.input_paths.ensureUnusedCapacity(gpa, 1);
538537
539538 const prev_contents_len = m.contents.items.len;
540539 const header: *File = @ptrCast(try m.contents.addManyAsSlice(gpa, @sizeOf(File)));
......@@ -558,7 +557,7 @@ pub const Manifest = struct {
558557 });
559558 if (gop.found_existing) {
560559 m.contents.shrinkRetainingCapacity(prev_contents_len);
561 const existing_input_file = &m.input_files.items[gop.index];
560 const existing_input_file = &m.input_paths.items[gop.index];
562561 if (options.handle) |handle| {
563562 existing_input_file.handle = handle;
564563 existing_input_file.have_handle = true;
......@@ -579,7 +578,7 @@ pub const Manifest = struct {
579578 if (!options.metadata_only)
580579 existing_header.flags.metadata_only = false;
581580 } else {
582 m.input_files.appendAssumeCapacity(.{
581 m.input_paths.appendAssumeCapacity(.{
583582 .request_handle = options.request_handle,
584583 .have_handle = options.handle != null,
585584 .handle = if (options.handle) |handle| handle else undefined,
......@@ -587,7 +586,7 @@ pub const Manifest = struct {
587586 .have_digest = false,
588587 .have_stat = options.stat != null,
589588 });
590 assert(m.input_files.items.len - 1 == gop.index);
589 assert(m.input_paths.items.len - 1 == gop.index);
591590 if (options.stat) |stat| {
592591 header.size = stat.size;
593592 header.inode = stat.inode;
......@@ -597,9 +596,9 @@ pub const Manifest = struct {
597596 return @fromBackingInt(gop.index);
598597 }
599598
600 pub fn addInputFileOptional(m: *Manifest, opt_path: ?Path, options: AddInputFileOptions) Allocator.Error!void {
599 pub fn addInputFileOptional(m: *Manifest, opt_path: ?Path, options: AddInputPathOptions) Allocator.Error!void {
601600 m.hash.add(opt_path != null);
602 _ = try addInputFile(m, opt_path orelse return, options);
601 _ = try addInputPath(m, opt_path orelse return, options);
603602 }
604603
605604 /// Check the cache to see if the input exists in it.
......@@ -623,8 +622,8 @@ pub const Manifest = struct {
623622 pub fn checkProgressless(man: *Manifest) Check.Error!Check.Status {
624623 assert(man.manifest_file == null);
625624
626 for (man.files.keys()[0..man.input_files.items.len]) |file_off| {
627 file_off.get(man).manifestDigestHash(&man.hash.hasher);
625 for (man.files.keys()[0..man.input_paths.items.len]) |file_off| {
626 man.digestHash(file_off, &man.hash.hasher);
628627 }
629628
630629 man.diagnostic = .none;
......@@ -709,16 +708,16 @@ pub const Manifest = struct {
709708
710709 // We're going to construct a second hash. Its input will begin with the digest we've
711710 // already computed (`bin_digest`), and then it'll have the digests of each input file,
712 // including "post" files (see `addFilePost`). If this is a hit, we learn the set of "post"
711 // including "post" files (see `addPathPost`). If this is a hit, we learn the set of "post"
713712 // files from the manifest on disk. If this is a miss, we'll learn those from future calls
714 // to `addFilePost` etc. As such, the state of `man.hash.hasher` after this function
713 // to `addPathPost` etc. As such, the state of `man.hash.hasher` after this function
715714 // depends on whether this is a hit or a miss.
716715 //
717716 // If we return `CacheStatus.hit`, then `man.hash.hasher` must already include
718717 // the digests of the "post" files, so the caller can call `final`. Otherwise, on a cache
719718 // miss, `man.hash.hasher` will include the digests of all non-"post" files -- that is,
720719 // the ones we've already been told about. The rest will be discovered through calls to
721 // `addFilePost` etc, which will update the hasher. After all files are added, the user can
720 // `addPathPost` etc, which will update the hasher. After all files are added, the user can
722721 // use `final`, and will at some point `writeManifest` the file list to disk.
723722
724723 man.hash.hasher = hasher_init;
......@@ -762,11 +761,11 @@ pub const Manifest = struct {
762761 }
763762
764763 fn shrinkFilesToInput(m: *Manifest) void {
765 if (m.files.count() <= m.input_files.items.len) return;
766 const off = m.files.keys()[m.input_files.items.len];
764 if (m.files.count() <= m.input_paths.items.len) return;
765 const off = m.files.keys()[m.input_paths.items.len];
767766 m.contents.shrinkRetainingCapacity(@backingInt(off));
768 assert(m.contents.len % @alignOf(File) == 0);
769 m.files.shrinkRetainingCapacity(m.input_files.items.len);
767 assert(m.contents.items.len % @alignOf(File) == 0);
768 m.files.shrinkRetainingCapacity(m.input_paths.items.len);
770769 }
771770
772771 /// Assumes that `self.hash.hasher` has been updated only with the original digest and that
......@@ -784,59 +783,70 @@ pub const Manifest = struct {
784783 return error.CacheCheckFailed;
785784 },
786785 };
786 const contents = m.contents.items;
787787
788 // Guess number of files based on manifest contents len to reduce allocations.
789 try m.files.ensureUnusedCapacity(gpa, m.contents.len / (@sizeOf(File) + 32));
790
791 var file_index: usize = 0;
792 var off: usize = 0;
788 var off: u32 = 0;
789 var c: Check = .{};
793790
794 // This group we always want to compute the hash digests, even on a cache miss.
791 // This group we always want to compute the hash digests, even on a
792 // cache miss, because they will be used in the manifest digest.
795793 var input_group: Io.Group = .init;
796794 defer input_group.cancel(io);
797795
796 // First the input files section, which must match our input files,
797 // otherwise it's invalid format.
798 for (m.input_paths.items, m.files.keys()[0..m.input_paths.items.len]) |*input_path, input_file_off| {
799 if (off + 1 >= contents.len) return error.InvalidFormat;
800 const file_off: File.Offset = @fromBackingInt(off);
801 const file = try file_off.getFallible(contents);
802 if (file.flags.prefix >= m.cache.prefixes_len) return error.InvalidFormat;
803 const path = try filePathFallible(contents, file_off);
804 if (path.len == 0) return error.InvalidFormat;
805 if (input_file_off != file_off) return error.InvalidFormat;
806
807 input_group.async(io, checkInputFile, .{ m, &c, file_off, path, input_path });
808
809 off = @intCast(@as(usize, off) + @sizeOf(File) + path.len + 1);
810 }
811
812 // Guess number of files based on manifest contents len to reduce allocations.
813 // This is not an upper bound; subsequent insertions may potentially allocate.
814 try m.files.ensureUnusedCapacity(gpa, contents.len / (@sizeOf(File) + 32));
815
798816 // This group we would like to cancel as soon as a cache miss is discovered.
799817 const PostResult = union(enum) {
800818 checkFile: Check.Status,
801819 };
802820 var post_select_buffer: [10]PostResult = undefined;
803 var post_select: Io.Select(PostResult) = .init(&post_select_buffer);
821 var post_select: Io.Select(PostResult) = .init(io, &post_select_buffer);
804822 var post_select_remaining: usize = 0;
805 var c: Check = .{};
806 defer post_select.cancel(io);
823 defer post_select.cancelDiscard();
807824
808 while (off + 1 < m.contents.len) {
825 while (off + 1 < contents.len) {
809826 const file_off: File.Offset = @fromBackingInt(off);
810 const file = try File.getFallible(file_off, m);
827 const file = try file_off.getFallible(m);
811828 if (file.flags.prefix >= m.cache.prefixes_len) return error.InvalidFormat;
812 const path = try file.pathFallible();
829 const path = try filePathFallible(contents, file_off);
813830 if (path.len == 0) return error.InvalidFormat;
814831
815 if (file_index < m.input_files.items.len) {
816 if (m.files.keys()[file_index] != file_off) return error.InvalidFormat;
817
818 input_group.async(io, checkInputFile, .{ m, &c, file_off, path });
819 } else {
820 try m.files.put(gpa, file_off);
832 try m.files.put(gpa, file_off, {});
821833
822 post_select.async(.checkFile, checkFile, .{ m, &c, file_off, path });
823 post_select_remaining += 1;
824 }
834 post_select.async(.checkFile, checkFile, .{ m, &c, file_off, path });
835 post_select_remaining += 1;
825836
826 file_index += 1;
827 off += @sizeOf(File) + path.len + 1;
837 off = @intCast(@as(usize, off) + @sizeOf(File) + path.len + 1);
828838 }
829839
830840 // Final terminating zero byte to distinguish empty manifest file from
831841 // manifest with zero files.
832 const file_valid = off + 1 == m.contents.len and m.contents[off] == 0;
833 if (!file_valid or file_index < m.input_files.items.len) {
842 const file_valid = off + 1 == contents.len and contents[off] == 0;
843 if (!file_valid) {
834844 try input_group.await(io);
835845 return .miss;
836846 }
837847
838848 // Don't track the trailing zero byte in contents.
839 m.contents.len -= 1;
849 m.contents.items.len -= 1;
840850
841851 var post_await_buffer: [10]PostResult = undefined;
842852 while (post_select_remaining > 0) {
......@@ -880,11 +890,17 @@ pub const Manifest = struct {
880890 return .hit;
881891 }
882892
883 fn checkInputFile(m: *Manifest, c: *Check, file_off: File.Offset, file_path: [:0]const u8) Io.Cancelable!void {
884 // TODO use already open handle
885 // TODO use already provided stat
886 // TODO implement request_handle
887 // TODO implement request_contents
893 fn checkInputFile(
894 m: *Manifest,
895 c: *Check,
896 file_off: File.Offset,
897 file_path: [:0]const u8,
898 input_path: *InputPath,
899 ) Io.Cancelable!void {
900 if (input_path.have_handle) @panic("TODO");
901 if (input_path.have_stat) @panic("TODO");
902 if (input_path.contents != .not_requested) @panic("TODO");
903 if (input_path.request_handle) @panic("TODO");
888904 switch (try checkFile(m, c, file_off, file_path)) {
889905 .hit => return,
890906 .miss => @atomicStore(Check.Status, &c.status, .miss, .unordered),
......@@ -897,7 +913,7 @@ pub const Manifest = struct {
897913 c: *Check,
898914 file_off: File.Offset,
899915 file_path: [:0]const u8,
900 ) Io.Cancelable!Check.Status {
916 ) error{ Canceled, CacheCheckFailed }!Check.Status {
901917 const file = file_off.get(m);
902918 const cache = m.cache;
903919 const gpa = cache.gpa;
......@@ -905,7 +921,7 @@ pub const Manifest = struct {
905921 const parent_dir = cache.prefixes()[file.flags.prefix].handle;
906922
907923 if (file.flags.metadata_only) {
908 const actual_stat = parent_dir.statFile() catch |err| switch (err) {
924 const actual_stat = parent_dir.statFile(io, file_path, .{}) catch |err| switch (err) {
909925 error.FileNotFound => return .miss,
910926 error.Canceled => |e| return e,
911927 else => |e| return c.fail(m, .{ .file_stat = .{
......@@ -999,10 +1015,10 @@ pub const Manifest = struct {
9991015 /// not including post files).
10001016 ///
10011017 /// Assumes that `bin_digest` is populated for all input files.
1002 pub fn unhit(man: *Manifest, bin_digest: BinDigest) void {
1018 pub fn unhit(man: *Manifest, bin_digest: *const BinDigest) void {
10031019 // Reset the hash.
10041020 man.hash.hasher = hasher_init;
1005 man.hash.hasher.update(&bin_digest);
1021 man.hash.hasher.update(bin_digest);
10061022 man.shrinkFilesToInput();
10071023 for (man.files.keys()) |off| {
10081024 const file = off.get(man);
......@@ -1053,11 +1069,8 @@ pub const Manifest = struct {
10531069 return timestamp.nanoseconds >= man.recent_problematic_timestamp.nanoseconds;
10541070 }
10551071
1056 pub const AddFilePostOptions = struct {
1057 handle: union(enum) {
1058 file: ?Io.File,
1059 dir: ?Io.Dir,
1060 } = .{ .file = null },
1072 pub const AddPathPostOptions = struct {
1073 handle: PathHandle = .{ .file = null },
10611074 stat: ?Stat = null,
10621075 /// If it is a directory, there is a special encoding required for contents, which
10631076 /// is null-separated sorted entries, each one prefixed with `File.Kind`.
......@@ -1065,7 +1078,7 @@ pub const Manifest = struct {
10651078 metadata_only: bool = false,
10661079 };
10671080
1068 pub const AddFilePostError = error{
1081 pub const AddPathPostError = error{
10691082 /// The same file path has been added to the cache manifest both as a
10701083 /// directory and as a normal file, making the intended caching
10711084 /// behavior ambiguous.
......@@ -1074,7 +1087,10 @@ pub const Manifest = struct {
10741087
10751088 /// Add a file as a dependency of process being cached, after cache miss
10761089 /// occurs.
1077 pub fn addFilePost(m: *Manifest, path: Path, options: AddFilePostOptions) AddFilePostError!void {
1090 ///
1091 /// See also:
1092 /// * `addInputPath`
1093 pub fn addPathPost(m: *Manifest, path: Path, options: AddPathPostOptions) AddPathPostError!void {
10781094 assert(m.manifest_file != null);
10791095 const cache = m.cache;
10801096 const gpa = cache.gpa;
......@@ -1236,14 +1252,14 @@ pub const Manifest = struct {
12361252 // Clang is invoked in single-source mode but other programs may not
12371253 .target, .target_must_resolve => {},
12381254 .prereq => |file_path| if (self.manifest_file == null) {
1239 _ = try self.addFilePath(.initCwd(file_path), null);
1240 } else try self.addFilePost(file_path),
1255 _ = try self.addInputPath(.initCwd(file_path), .{});
1256 } else try self.addPathPost(file_path),
12411257 .prereq_must_resolve => {
12421258 resolve_buf.clearRetainingCapacity();
12431259 try token.resolve(gpa, &resolve_buf);
12441260 if (self.manifest_file == null) {
1245 _ = try self.addFilePath(.initCwd(resolve_buf.items), null);
1246 } else try self.addFilePost(resolve_buf.items);
1261 _ = try self.addInputPath(.initCwd(resolve_buf.items), .{});
1262 } else try self.addPathPost(resolve_buf.items);
12471263 },
12481264 else => |err| {
12491265 try err.printError(gpa, &error_buf);
......@@ -1336,25 +1352,45 @@ pub const Manifest = struct {
13361352 return .{ .manifest_file = self.manifest_file.? };
13371353 }
13381354
1339 pub fn takeFiles(man: *Manifest) Files {
1340 defer man.files = .empty;
1341 return man.files;
1342 }
1355 pub const SelfContainedFiles = struct {
1356 /// References memory inside `contents`.
1357 files: Files,
1358 contents: std.ArrayList(u8),
1359
1360 pub const empty: @This() = .{
1361 .files = .empty,
1362 .contents = .empty,
1363 };
1364
1365 pub fn deinit(scf: *SelfContainedFiles, gpa: Allocator) void {
1366 scf.files.deinit(gpa);
1367 scf.contents.deinit(gpa);
1368 scf.* = undefined;
1369 }
1370
1371 pub fn path(scf: *const SelfContainedFiles, file_offset: File.Offset) [:0]const u8 {
1372 return filePath(scf.contents.items, file_offset);
1373 }
1374 };
13431375
1344 pub fn freeFiles(gpa: Allocator, files: *Files) void {
1345 for (files.keys()) |*file| file.deinit(gpa);
1346 files.deinit(gpa);
1376 pub fn takeFiles(m: *Manifest) SelfContainedFiles {
1377 defer m.files = .empty;
1378 defer m.contents = .empty;
1379 return .{
1380 .files = m.files,
1381 .contents = m.contents,
1382 };
13471383 }
13481384
13491385 /// Releases the manifest file and frees any memory the Manifest was using.
13501386 /// `Manifest.hit` must be called first.
13511387 ///
13521388 /// Don't forget to call `writeManifest` before this!
1353 pub fn deinit(man: *Manifest) void {
1354 const io = man.cache.io;
1355 const gpa = man.cache.gpa;
1389 pub fn deinit(m: *Manifest) void {
1390 const io = m.cache.io;
1391 const gpa = m.cache.gpa;
13561392
1357 if (man.manifest_file) |file| {
1393 if (m.manifest_file) |file| {
13581394 if (builtin.os.tag == .windows) {
13591395 // See Lock.release for why this is required on Windows
13601396 file.unlock(io);
......@@ -1362,8 +1398,9 @@ pub const Manifest = struct {
13621398
13631399 file.close(io);
13641400 }
1365 freeFiles(gpa, &man.files);
1366 man.* = undefined;
1401 m.files.deinit(gpa);
1402 m.contents.deinit(gpa);
1403 m.* = undefined;
13671404 }
13681405
13691406 pub fn populateFileSystemInputs(man: *Manifest, buf: *std.ArrayList(u8)) Allocator.Error!void {
......@@ -1497,6 +1534,25 @@ pub const Manifest = struct {
14971534 hasher.update(contents.items[contents_start..][0..contents_len]);
14981535 hasher.final(bin_digest);
14991536 }
1537
1538 fn digestHash(m: *const Manifest, off: File.Offset, hasher: *Hasher) void {
1539 const contents = m.contents.items;
1540 const flags_off = @offsetOf(File, "flags");
1541 comptime assert(@offsetOf(File, "path_start") - flags_off == 1);
1542 const hash_start = @backingInt(off) + flags_off;
1543 const hash_end = mem.findScalarPos(u8, contents, hash_start, 0).?;
1544 hasher.update(contents[hash_start..hash_end]);
1545 }
1546
1547 fn filePathFallible(contents: []const u8, off: File.Offset) error{InvalidFormat}![:0]const u8 {
1548 const path_start = @backingInt(off) + @offsetOf(File, "path_start");
1549 const path_end = mem.findScalarPos(u8, contents, path_start, 0) orelse return error.InvalidFormat;
1550 return contents[path_start..path_end :0];
1551 }
1552
1553 fn filePath(contents: []const u8, off: File.Offset) [:0]const u8 {
1554 return filePathFallible(contents, off) catch unreachable;
1555 }
15001556};
15011557
15021558/// Create/Write a file, close it, then grab its stat.mtime timestamp.
......@@ -1555,7 +1611,7 @@ test "cache file and then recall it" {
15551611 ch.hash.add(true);
15561612 ch.hash.add(@as(u16, 1234));
15571613 ch.hash.addBytes("1234");
1558 _ = try ch.addFilePath(.initCwd(temp_file), null);
1614 _ = try ch.addInputPath(.initCwd(temp_file), .{});
15591615
15601616 // There should be nothing in the cache
15611617 try testing.expectEqual(false, try ch.hit(.none));
......@@ -1570,7 +1626,7 @@ test "cache file and then recall it" {
15701626 ch.hash.add(true);
15711627 ch.hash.add(@as(u16, 1234));
15721628 ch.hash.addBytes("1234");
1573 _ = try ch.addFilePath(.initCwd(temp_file), null);
1629 _ = try ch.addInputPath(.initCwd(temp_file), .{});
15741630
15751631 // Cache hit! We just "built" the same file
15761632 try testing.expect(try ch.hit(.none));
......@@ -1623,7 +1679,7 @@ test "check that changing a file makes cache fail" {
16231679 defer ch.deinit();
16241680
16251681 ch.hash.addBytes("1234");
1626 const temp_file_idx = try ch.addFilePath(.initCwd(temp_file), 100);
1682 const temp_file_idx = try ch.addInputPath(.initCwd(temp_file), .{ .request_contents = true });
16271683
16281684 // There should be nothing in the cache
16291685 try testing.expectEqual(false, try ch.hit(.none));
......@@ -1642,7 +1698,7 @@ test "check that changing a file makes cache fail" {
16421698 defer ch.deinit();
16431699
16441700 ch.hash.addBytes("1234");
1645 const temp_file_idx = try ch.addFilePath(.initCwd(temp_file), 100);
1701 const temp_file_idx = try ch.addInputPath(.initCwd(temp_file), .{ .request_contents = true });
16461702
16471703 // A file that we depend on has been updated, so the cache should not contain an entry for it
16481704 try testing.expectEqual(false, try ch.hit(.none));
......@@ -1689,7 +1745,7 @@ test "no file inputs" {
16891745 man.hash.addBytes("1234");
16901746
16911747 // There should be nothing in the cache
1692 try testing.expectEqual(false, try man.hit(.none));
1748 try testing.expectEqual(false, try man.check(.none));
16931749
16941750 digest1 = man.final();
16951751
......@@ -1701,7 +1757,7 @@ test "no file inputs" {
17011757
17021758 man.hash.addBytes("1234");
17031759
1704 try testing.expect(try man.hit(.none));
1760 try testing.expect(try man.check(.none));
17051761 digest2 = man.final();
17061762 try testing.expectEqual(false, man.have_exclusive_lock);
17071763 }
......@@ -1750,12 +1806,12 @@ test "Manifest with files added after initial hash work" {
17501806 defer ch.deinit();
17511807
17521808 ch.hash.addBytes("1234");
1753 _ = try ch.addFilePath(.initCwd(temp_file1), null);
1809 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
17541810
17551811 // There should be nothing in the cache
17561812 try testing.expectEqual(false, try ch.hit(.none));
17571813
1758 _ = try ch.addFilePost(temp_file2);
1814 _ = try ch.addPathPost(temp_file2);
17591815
17601816 digest1 = ch.final();
17611817 try ch.writeManifest();
......@@ -1765,7 +1821,7 @@ test "Manifest with files added after initial hash work" {
17651821 defer ch.deinit();
17661822
17671823 ch.hash.addBytes("1234");
1768 _ = try ch.addFilePath(.initCwd(temp_file1), null);
1824 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
17691825
17701826 try testing.expect(try ch.hit(.none));
17711827 digest2 = ch.final();
......@@ -1788,12 +1844,12 @@ test "Manifest with files added after initial hash work" {
17881844 defer ch.deinit();
17891845
17901846 ch.hash.addBytes("1234");
1791 _ = try ch.addFilePath(.initCwd(temp_file1), null);
1847 _ = try ch.addInputPath(.initCwd(temp_file1), .{});
17921848
17931849 // A file that we depend on has been updated, so the cache should not contain an entry for it
17941850 try testing.expectEqual(false, try ch.hit(.none));
17951851
1796 _ = try ch.addFilePost(temp_file2);
1852 _ = try ch.addPathPost(temp_file2);
17971853
17981854 digest3 = ch.final();
17991855
lib/std/Build/Configuration.zig+1-1
......@@ -1875,7 +1875,7 @@ pub const PathDep = extern struct {
18751875 is_directory: bool,
18761876 metadata_only: bool,
18771877 base: LazyPath.Relative.Base,
1878 _: u16 = 0,
1878 _: u22 = 0,
18791879 };
18801880};
18811881
lib/std/Io/Reader.zig+1
......@@ -393,6 +393,7 @@ pub fn appendRemainingAligned(
393393pub const UnlimitedAllocError = Allocator.Error || ShortError;
394394
395395pub fn appendRemainingUnlimited(r: *Reader, gpa: Allocator, list: *ArrayList(u8)) UnlimitedAllocError!void {
396 list.pointer_stability.assertUnlocked();
396397 var a: std.Io.Writer.Allocating = .initOwnedSlice(gpa, list.allocatedSlice());
397398 a.writer.end = list.items.len;
398399 list.* = .empty;
src/Compilation.zig+14-14
......@@ -1340,19 +1340,19 @@ pub const cache_helpers = struct {
13401340 }
13411341 }
13421342
1343 pub fn hashCSource(self: *Cache.Manifest, c_source: CSourceFile) !void {
1344 _ = try self.addFilePath(.initCwd(c_source.src_path), null);
1343 pub fn hashCSource(man: *Cache.Manifest, c_source: CSourceFile) !void {
1344 _ = try man.addInputPath(.initCwd(c_source.src_path), .{});
13451345 // Hash the extra flags, with special care to call addFile for file parameters.
13461346 // TODO this logic can likely be improved by utilizing clang_options_data.zig.
13471347 const file_args = [_][]const u8{"-include"};
13481348 var arg_i: usize = 0;
13491349 while (arg_i < c_source.extra_flags.len) : (arg_i += 1) {
13501350 const arg = c_source.extra_flags[arg_i];
1351 self.hash.addBytes(arg);
1351 man.hash.addBytes(arg);
13521352 for (file_args) |file_arg| {
13531353 if (mem.eql(u8, file_arg, arg) and arg_i + 1 < c_source.extra_flags.len) {
13541354 arg_i += 1;
1355 _ = try self.addFilePath(.initCwd(c_source.extra_flags[arg_i]), null);
1355 _ = try man.addInputPath(.initCwd(c_source.extra_flags[arg_i]), .{});
13561356 }
13571357 }
13581358 }
......@@ -2830,7 +2830,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
28302830 man.want_shared_lock = false;
28312831 }
28322832
2833 const is_hit = man.hit(main_progress_node) catch |err| switch (err) {
2833 const is_hit = man.check(main_progress_node) catch |err| switch (err) {
28342834 error.Canceled, error.OutOfMemory => |e| return e,
28352835 error.CacheCheckFailed => switch (man.diagnostic) {
28362836 .none => unreachable,
......@@ -3394,7 +3394,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
33943394 try link.hashInputs(man, comp.link_inputs);
33953395
33963396 for (comp.c_objects.items) |c_object| {
3397 _ = try man.addFilePath(.initCwd(c_object.src.src_path), null);
3397 _ = try man.addInputPath(.initCwd(c_object.src.src_path), .{});
33983398 man.hash.addOptional(c_object.src.ext);
33993399 man.hash.addListOfBytes(c_object.src.extra_flags);
34003400 }
......@@ -3402,11 +3402,11 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
34023402 for (comp.win32_resources.items) |win32_resource| {
34033403 switch (win32_resource.src) {
34043404 .rc => |rc_src| {
3405 _ = try man.addFilePath(.initCwd(rc_src.src_path), null);
3405 _ = try man.addInputPath(.initCwd(rc_src.src_path), .{});
34063406 man.hash.addListOfBytes(rc_src.extra_flags);
34073407 },
34083408 .manifest => |manifest_path| {
3409 _ = try man.addFilePath(.initCwd(manifest_path), null);
3409 _ = try man.addInputPath(.initCwd(manifest_path), .{});
34103410 },
34113411 }
34123412 }
......@@ -5540,7 +5540,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
55405540 const target = comp.getTarget();
55415541 assert(target.ofmt != .c);
55425542 const o_ext = target.ofmt.fileExt(target.cpu.arch);
5543 const digest = if (!comp.disable_c_depfile and try man.hit(child_progress_node)) man.final() else blk: {
5543 const digest = if (!comp.disable_c_depfile and try man.check(child_progress_node)) man.final() else blk: {
55445544 var argv: std.array_list.Managed([]const u8) = .init(gpa);
55455545 defer argv.deinit();
55465546
......@@ -5801,7 +5801,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
58015801 }
58025802
58035803 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
5804 if (comp.disable_c_depfile) _ = try man.hit(child_progress_node);
5804 if (comp.disable_c_depfile) _ = try man.check(child_progress_node);
58055805
58065806 // Rename into place.
58075807 const digest = man.final();
......@@ -5884,12 +5884,12 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
58845884 // the XML data as a RT_MANIFEST resource. This means we can skip preprocessing,
58855885 // include paths, CLI options, etc.
58865886 if (win32_resource.src == .manifest) {
5887 _ = try man.addFilePath(.initCwd(src_path), null);
5887 _ = try man.addInputPath(.initCwd(src_path), .{});
58885888
58895889 const rc_basename = try std.fmt.allocPrint(arena, "{s}.rc", .{src_basename});
58905890 const res_basename = try std.fmt.allocPrint(arena, "{s}.res", .{src_basename});
58915891
5892 const digest = if (try man.hit(child_progress_node)) man.final() else blk: {
5892 const digest = if (try man.check(child_progress_node)) man.final() else blk: {
58935893 // The digest only depends on the .manifest file, so we can
58945894 // get the digest now and write the .res directly to the cache
58955895 const digest = man.final();
......@@ -5977,12 +5977,12 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
59775977 // We now know that we're compiling an .rc file
59785978 const rc_src = win32_resource.src.rc;
59795979
5980 _ = try man.addFilePath(.initCwd(rc_src.src_path), null);
5980 _ = try man.addInputPath(.initCwd(rc_src.src_path), .{});
59815981 man.hash.addListOfBytes(rc_src.extra_flags);
59825982
59835983 const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len];
59845984
5985 const digest = if (try man.hit(child_progress_node)) man.final() else blk: {
5985 const digest = if (try man.check(child_progress_node)) man.final() else blk: {
59865986 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{});
59875987 defer zig_cache_tmp_dir.close(io);
59885988
src/libs/freebsd.zig+5-3
......@@ -458,12 +458,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
458458 man.hash.add(target.abi);
459459 man.hash.add(target_os_version);
460460
461 const abilists_index = try man.addFilePath(.{
461 const abilists_index = try man.addInputPath(.{
462462 .root_dir = comp.dirs.zig_lib,
463463 .sub_path = abilists_path,
464 }, abilists_max_size);
464 }, .{
465 .request_contents = true,
466 });
465467
466 if (try man.hit(prog_node)) {
468 if (try man.check(prog_node)) {
467469 const digest = man.final();
468470
469471 return queueSharedObjects(comp, .{
src/libs/glibc.zig+5-3
......@@ -698,12 +698,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
698698 man.hash.add(target.abi);
699699 man.hash.add(target_version);
700700
701 const abilists_index = try man.addFilePath(.{
701 const abilists_index = try man.addInputPath(.{
702702 .root_dir = comp.dirs.zig_lib,
703703 .sub_path = abilists_path,
704 }, abilists_max_size);
704 }, .{
705 .request_contents = true,
706 });
705707
706 if (try man.hit(prog_node)) {
708 if (try man.check(prog_node)) {
707709 const digest = man.final();
708710
709711 return queueSharedObjects(comp, .{
src/libs/mingw.zig+2-2
......@@ -246,12 +246,12 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
246246 var man = cache.obtain();
247247 defer man.deinit();
248248
249 _ = try man.addFilePath(def_file_path, null);
249 _ = try man.addInputPath(def_file_path, .{});
250250
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.hit(prog_node) catch |err| switch (err) {
254 const is_hit = man.check(prog_node) catch |err| switch (err) {
255255 error.CacheCheckFailed => switch (man.diagnostic) {
256256 .none => unreachable,
257257 .manifest_create, .manifest_read, .manifest_lock => |e| {
src/libs/netbsd.zig+5-3
......@@ -406,12 +406,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
406406 man.hash.add(target.abi);
407407 man.hash.add(target_version);
408408
409 const abilists_index = try man.addFilePath(.{
409 const abilists_index = try man.addInputPath(.{
410410 .root_dir = comp.dirs.zig_lib,
411411 .sub_path = abilists_path,
412 }, abilists_max_size);
412 }, .{
413 .request_contents = true,
414 });
413415
414 if (try man.hit(prog_node)) {
416 if (try man.check(prog_node)) {
415417 const digest = man.final();
416418
417419 return queueSharedObjects(comp, .{
src/libs/openbsd.zig+5-3
......@@ -327,12 +327,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
327327 man.hash.add(target.abi);
328328 man.hash.add(target_version);
329329
330 const abilists_index = try man.addFilePath(.{
330 const abilists_index = try man.addInputPath(.{
331331 .root_dir = comp.dirs.zig_lib,
332332 .sub_path = abilists_path,
333 }, abilists_max_size);
333 }, .{
334 .request_contents = true,
335 });
334336
335 if (try man.hit(prog_node)) {
337 if (try man.check(prog_node)) {
336338 const digest = man.final();
337339
338340 return queueSharedObjects(comp, .{
src/link/MachO.zig+1-1
......@@ -155,7 +155,7 @@ pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void {
155155 for (hm) |value| {
156156 man.hash.add(value.needed);
157157 man.hash.add(value.weak);
158 _ = try man.addFilePath(value.path, null);
158 _ = try man.addInputPath(value.path, .{});
159159 }
160160}
161161
src/main.zig+1-1
......@@ -4862,7 +4862,7 @@ fn cmdTranslateC(
48624862 Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err|
48634863 fatal("unable to process {q}: {t}", .{ c_source_file.src_path, err });
48644864
4865 const result: Compilation.TranslateCResult = if (try man.hit(prog_node)) .{
4865 const result: Compilation.TranslateCResult = if (try man.check(prog_node)) .{
48664866 .digest = man.finalBin(),
48674867 .cache_hit = true,
48684868 .errors = std.zig.ErrorBundle.empty,