From fc1d90e2a1fdc92c020c3d1d6af6a3f768d8a9d2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 3 Sep 2026 15:02:32 -0700 Subject: [PATCH] std.Build.Cache: fix some compilation errors from rewrite --- lib/compiler/Maker.zig | 20 +- lib/compiler/Maker/Step.zig | 36 ++- lib/compiler/Maker/Step/ObjCopy.zig | 2 +- lib/compiler/Maker/Step/Options.zig | 2 +- lib/compiler/Maker/Step/Run.zig | 10 +- lib/compiler/Maker/Step/WriteFile.zig | 4 +- lib/std/Build/Cache.zig | 330 +++++++++++++++----------- lib/std/Build/Configuration.zig | 2 +- lib/std/Io/Reader.zig | 1 + src/Compilation.zig | 28 +-- src/libs/freebsd.zig | 8 +- src/libs/glibc.zig | 8 +- src/libs/mingw.zig | 4 +- src/libs/netbsd.zig | 8 +- src/libs/openbsd.zig | 8 +- src/link/MachO.zig | 2 +- src/main.zig | 2 +- 17 files changed, 269 insertions(+), 206 deletions(-) diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index 6038cad96d84e824b062749abcc63d44625a0451..d5cde77ae631f5cad9a297429a5b045a4046e610 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -702,8 +702,8 @@ pub fn main(init: process.Init.Minimal) !void { configure: while (true) { // Set of files that, if modified, imply that recompiling and rerunning // configurer is needed. - var configure_source_files: Cache.Manifest.Files = .empty; - defer Cache.Manifest.freeFiles(gpa, &configure_source_files); + var configure_source_files: Cache.Manifest.SelfContainedFiles = .empty; + defer configure_source_files.deinit(gpa); // If this fails, we can still start the server and wait for user // to request a rebuild. If it returns error.FailedButCacheIntact @@ -1043,7 +1043,7 @@ const ConfigureOptions = struct { fetch_only: bool, print_configuration: PrintConfiguration, forks: []Fork, - src_files: *Cache.Manifest.Files, + src_files: *Cache.Manifest.SelfContainedFiles, }; fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { @@ -1398,7 +1398,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { defer compile_prog_node.end(); if (config_man) |man| { - if (try man.hit(compile_prog_node)) { + if (.hit == try man.check(compile_prog_node)) { const digest = man.final(); const path: Path = .{ .root_dir = graph.local_cache_root, @@ -1497,11 +1497,11 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { } if (config_man) |man| for (configuration.path_deps) |path_dep| { - switch (path_dep.flags.mode) { - .directory => {}, // TODO - .contents => try man.addPathPost(try confPathDepToCachePath(arena, graph, &configuration, path_dep)), - .metadata => {}, // TODO - } + const path = try confPathDepToCachePath(arena, graph, &configuration, path_dep); + try man.addPathPost(path, .{ + .handle = if (path_dep.flags.is_directory) .{ .dir = null } else .{ .file = null }, + .metadata_only = path_dep.flags.metadata_only, + }); }; // 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 fn prepare( maker: *Maker, step_indices: []const Configuration.Step.Index, - configure_source_files: *const Cache.Manifest.Files, + configure_source_files: *const Cache.Manifest.SelfContainedFiles, ) !void { const gpa = maker.gpa; const graph = maker.graph; diff --git a/lib/compiler/Maker/Step.zig b/lib/compiler/Maker/Step.zig index 0fd82226cce06989c0acea46f4f22e4dcd6d6e58..690afd2e0fb403fad83d0c2f9b0a747ffed9a088 100644 --- a/lib/compiler/Maker/Step.zig +++ b/lib/compiler/Maker/Step.zig @@ -726,8 +726,9 @@ pub fn handleChildProcessTerm(s: *Step, maker: *Maker, term: std.process.Child.T /// Prefer `cacheHitWatched` unless you already added watch inputs /// separately from using the cache system. pub fn cacheHit(s: *Step, maker: *Maker, man: *Cache.Manifest, parent_progress_node: std.Progress.Node) !bool { - s.result_cached = man.hit(parent_progress_node) catch |err| return failWithCacheError(s, maker, man, err); - return s.result_cached; + const hit = .hit == (man.check(parent_progress_node) catch |err| return failWithCacheError(s, maker, man, err)); + s.result_cached = hit; + return hit; } /// 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 /// /// Must be accompanied with `writeManifestAndWatch`. pub fn cacheHitWatched(s: *Step, maker: *Maker, man: *Cache.Manifest, parent_progress_node: std.Progress.Node) !bool { - const is_hit = man.hit(parent_progress_node) catch |err| return failWithCacheError(s, maker, man, err); - s.result_cached = is_hit; + const hit = .hit == (man.check(parent_progress_node) catch |err| return failWithCacheError(s, maker, man, err)); + s.result_cached = hit; // The above call to hit() populates the manifest with files, so in case of // a hit, we need to populate watch inputs. - if (is_hit) try setWatchInputsFromManifest(s, maker, man); - return is_hit; + if (hit) try setWatchInputsFromManifest(s, maker, man); + return hit; } fn failWithCacheError( s: *Step, maker: *Maker, man: *const Cache.Manifest, - err: Cache.Manifest.HitError, + err: Cache.Manifest.Check.Error, ) error{ OutOfMemory, Canceled, MakeFailed } { switch (err) { error.CacheCheckFailed => switch (man.diagnostic) { .none => unreachable, - .manifest_create, .manifest_read, .manifest_lock => |e| return s.fail(maker, "failed checking cache: {t} {t}", .{ - man.diagnostic, e, - }), + .manifest_create, .manifest_read, .manifest_lock => |e| { + return s.fail(maker, "failed checking cache: {t} {t}", .{ man.diagnostic, e }); + }, .file_open, .file_stat, .file_read, .file_hash => |op| { - const pp = man.files.keys()[op.file_index].prefixed_path; - const prefix = man.cache.prefixes()[pp.prefix].path orelse ""; - return s.fail(maker, "failed checking cache: {s}{c}{s} {t} {t}", .{ - prefix, Dir.path.sep, pp.sub_path, man.diagnostic, op.err, - }); + const path = op.path(man); + return s.fail(maker, "failed checking cache: {f} {t} {t}", .{ path, man.diagnostic, op.err }); }, }, error.OutOfMemory, error.Canceled => |e| return e, @@ -795,17 +793,17 @@ pub fn setWatchInputsFromManifest(s: *Step, maker: *Maker, man: *Cache.Manifest) pub fn setWatchInputsFromManifestFiles( s: *Step, maker: *Maker, - files: *const Cache.Manifest.Files, + scf: *const Cache.Manifest.SelfContainedFiles, prefixes: []const Cache.Directory, ) !void { const graph = maker.graph; const arena = graph.arena; // TODO don't leak into process arena clearWatchInputs(s, maker); - for (files.keys()) |file| { + for (scf.files.keys()) |file_offset| { // The file path data is freed when the cache manifest is cleaned up at the end of `make`. - const sub_path = try arena.dupe(u8, file.prefixed_path.sub_path); + const sub_path = try arena.dupe(u8, scf.path(file_offset)); try addWatchInputFromPath(s, maker, .{ - .root_dir = prefixes[file.prefixed_path.prefix], + .root_dir = prefixes[file_offset.get(scf.contents.items).flags.prefix], .sub_path = Dir.path.dirname(sub_path) orelse "", }, Dir.path.basename(sub_path)); } diff --git a/lib/compiler/Maker/Step/ObjCopy.zig b/lib/compiler/Maker/Step/ObjCopy.zig index 49424d4b35daea41bb6a485e1fb2a37acfe5e468..7924b21c683866a3536bf72e2bf9b04f3850f3c5 100644 --- a/lib/compiler/Maker/Step/ObjCopy.zig +++ b/lib/compiler/Maker/Step/ObjCopy.zig @@ -34,7 +34,7 @@ pub fn make( defer man.deinit(); const input_path = try maker.resolveLazyPath(arena, input_lazy_path, step_index); - _ = try man.addFilePath(input_path, null); + _ = try man.addInputPath(input_path, .{}); man.hash.addOptionalBytes(only_section); man.hash.addOptionalBytes(opt_basename); man.hash.addOptionalBytes(opt_debug_basename); diff --git a/lib/compiler/Maker/Step/Options.zig b/lib/compiler/Maker/Step/Options.zig index 7c31f144d59a20f70f1e6550320b8f8c05237276..e0812402e1b976b98cc9e15f42d77afd04c4f326 100644 --- a/lib/compiler/Maker/Step/Options.zig +++ b/lib/compiler/Maker/Step/Options.zig @@ -42,7 +42,7 @@ pub fn make( const lazy_path = arg.path.get(conf); try step.addWatchInput(maker, arena, lazy_path); const arg_path = try maker.resolveLazyPath(arena, lazy_path, step_index); - _ = try man.addFilePath(arg_path, null); + _ = try man.addInputPath(arg_path, .{}); try args_bytes.print(arena, "pub const {f}: []const u8 = \"{f}\";\n", .{ std.zig.fmtId(name), arg_path.fmtEscapeString(), }); diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig index c8219543c2891c24ee5003f76a81efdf91f0d5a1..04b5764d04a191ace28403be0737635f047019fb 100644 --- a/lib/compiler/Maker/Step/Run.zig +++ b/lib/compiler/Maker/Step/Run.zig @@ -97,7 +97,7 @@ pub fn make( man.hash.add(arg.flags.make_absolute); man.hash.addBytesZ(prefix); man.hash.addBytesZ(suffix); - _ = try man.addFilePath(file_path, null); + _ = try man.addInputPath(file_path, .{}); }, .path_directory => { const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; @@ -135,7 +135,7 @@ pub fn make( argv_list.appendAssumeCapacity(result.written()); man.hash.addBytesZ(prefix); man.hash.addBytesZ(suffix); - _ = try man.addFilePath(file_path, null); + _ = try man.addInputPath(file_path, .{}); }, .artifact => { const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; @@ -155,7 +155,7 @@ pub fn make( man.hash.add(arg.flags.make_absolute); man.hash.addBytesZ(prefix); man.hash.addBytesZ(suffix); - _ = try man.addFilePath(file_path, null); + _ = try man.addInputPath(file_path, .{}); }, .output_file, .output_directory => { const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; @@ -211,7 +211,7 @@ pub fn make( }, .lazy_path => |lazy_path| { const file_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index); - _ = try man.addFilePath(file_path, null); + _ = try man.addInputPath(file_path, .{}); }, .none => {}, } @@ -240,7 +240,7 @@ pub fn make( for (conf_run.file_inputs.slice) |lazy_path| { const file_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index); - _ = try man.addFilePath(file_path, null); + _ = try man.addInputPath(file_path, .{}); } if (conf_run.cwd.value) |lazy_path| { diff --git a/lib/compiler/Maker/Step/WriteFile.zig b/lib/compiler/Maker/Step/WriteFile.zig index 65b19bdbae8137e94b407fded33c31af71805bc2..afea7de96ea7d9598cd2d4f2e55febc40cbad0d1 100644 --- a/lib/compiler/Maker/Step/WriteFile.zig +++ b/lib/compiler/Maker/Step/WriteFile.zig @@ -55,7 +55,7 @@ pub fn make( man.hash.addBytes(copy.sub_path.slice(conf)); const src_lazy_path = copy.src_file.get(conf); const source_path = try maker.resolveLazyPath(arena, src_lazy_path, step_index); - _ = try man.addFilePath(source_path, null); + _ = try man.addInputPath(source_path, .{}); try step.addWatchInput(maker, arena, src_lazy_path); } @@ -96,7 +96,7 @@ pub fn make( }, .file => { const entry_path = try src_dir_path.join(arena, entry.path); - _ = try man.addFilePath(entry_path, null); + _ = try man.addInputPath(entry_path, .{}); total_items += 1; }, else => continue, diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index a3069f48dc21adaa1f985c7fcb1d7b5c591e3fae..da90f0954d2e0e11db5ec9323721f2226ed89c01 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -294,7 +294,7 @@ pub const Manifest = struct { files: Files = .empty, /// Indexes line up with `files`, but only up until `hit` is called. Uses /// `Cache.gpa`. - input_files: std.ArrayList(InputFile) = .empty, + input_paths: std.ArrayList(InputPath) = .empty, diagnostic: Diagnostic = .none, /// Keeps track of the last time we performed a file system write to observe /// what time the file system thinks it is, according to its own granularity. @@ -304,11 +304,11 @@ pub const Manifest = struct { /// final terminating byte can be added without allocation. Uses /// `Cache.gpa`. contents: std.ArrayList(u8) = .empty, - /// All contents from all `input_files` whose contents were requested, + /// All contents from all `input_paths` whose contents were requested, /// concatenated. Total byte size will be less than `max_input_content_len` /// otherwise an error is returned. /// - /// Data is invalidated when `addFilePost` is called. + /// Data is invalidated when `addPathPost` is called. all_input_content: std.ArrayList(u8) = .empty, max_input_content_len: usize = std.math.maxInt(u32), @@ -328,23 +328,24 @@ pub const Manifest = struct { InvalidFormat, } || Allocator.Error || Io.Cancelable; - fn fail(c: *Check, m: *Manifest, diagnostic: Diagnostic) void { - if (!@atomicRmw(bool, &c.diagnostic_lock, .Xchg, true, .unordered)) { + fn fail(c: *Check, m: *Manifest, diagnostic: Diagnostic) error{CacheCheckFailed} { + if (!@atomicRmw(bool, &c.diagnostic_lock, .Xchg, true, .monotonic)) { m.diagnostic = diagnostic; } + return error.CacheCheckFailed; } }; pub const Files = std.array_hash_map.Custom(File.Offset, void, File.HashContext, false); - /// Source files whose prefix and relative path are included when computing - /// the cache manifest digest. It's the information needed to lazily hash - /// the input files only when a cache miss occurs. + /// Source files and directories whose prefix and relative path are + /// included when computing the cache manifest digest. It's the information + /// needed to lazily hash the input files only when a cache miss occurs. /// /// `File.prefix`, `File.path`, and `File.mode` will be always populated, /// but the other fields of `File` will be populated depending on the - /// fields of `InputFile`. - pub const InputFile = struct { + /// fields of `InputPath`. + pub const InputPath = struct { request_handle: bool, have_handle: bool, /// Determines whether `File.size`, `File.inode`, and `File.mtime` are populated. @@ -360,7 +361,7 @@ pub const Manifest = struct { /// `have_handle` determines whether this is populated. handle: Io.File, - /// Index into `Manifest.input_files`. + /// Index into `Manifest.input_paths`. pub const Index = enum(u32) { _, }; @@ -406,13 +407,13 @@ pub const Manifest = struct { pub const Offset = enum(u32) { _, - pub fn get(offset: Offset, m: *const Manifest) *File { - return @ptrCast(m.contents.items[@backingInt(offset)..][0..@sizeOf(File)]); + pub fn get(offset: Offset, contents: []u8) *File { + return @ptrCast(@alignCast(contents.items[@backingInt(offset)..][0..@sizeOf(File)])); } - pub fn getFallible(offset: Offset, m: *const Manifest) error{EndOfStream}!*File { - if (@backingInt(offset) + @sizeOf(File) >= m.contents.len) return error.EndOfStream; - return get(offset, m); + pub fn getFallible(offset: Offset, contents: []u8) error{InvalidFormat}!*File { + if (@backingInt(offset) + @sizeOf(File) >= contents.items.len) return error.InvalidFormat; + return get(offset, contents); } }; @@ -432,25 +433,6 @@ pub const Manifest = struct { } }; - pub fn path(file: *const File) [:0]const u8 { - return pathFallible(file) catch unreachable; - } - - pub fn pathFallible(file: *const File) error{EndOfStream}![:0]const u8 { - const ptr: [*]u8 = &file.path_start; - const len = mem.findScalar(u8, ptr, 0) orelse return error.EndOfStream; - return ptr[0..len :0]; - } - - fn manifestDigestHash(file: *const File, hasher: *Hasher) void { - const path_ptr: [*]u8 = &file.path_start; - const path_len = mem.findScalar(u8, path_ptr, 0).?; - comptime assert(@offsetOf(File, "path_start") - @offsetOf(File, "flags") == 1); - // Includes flags and sentinel. - const hash_string = (path_ptr - 1)[0 .. path_len + 2]; - hasher.update(hash_string); - } - fn setStat(file: *File, m: *Manifest, stat: Stat) Io.Cancelable!void { file.size = stat.size; file.inode = stat.inode; @@ -490,6 +472,16 @@ pub const Manifest = struct { pub const FileOp = struct { file_offset: File.Offset, err: anyerror, + + /// Returned `Path` references `Manifest.contents`. + pub fn path(fo: FileOp, manifest: *const Manifest) Path { + const contents = manifest.contents.items; + const prefix = fo.file_offset.get(contents).flags.prefix; + return .{ + .root_dir = manifest.cache.prefixes()[prefix], + .sub_path = filePath(contents, fo.file_offset), + }; + } }; }; @@ -499,42 +491,49 @@ pub const Manifest = struct { mtime: Io.Timestamp, }; - pub const AddInputFileOptions = struct { - /// If `is_directory` is true, this handle must be opened with - /// iteration capability. - handle: ?Io.File = null, + pub const PathHandle = union(enum) { + file: ?Io.File, + /// If provided, this handle must be opened with iteration capability. + dir: ?Io.Dir, + }; + + pub const AddInputPathOptions = struct { + handle: PathHandle = .{ .file = null }, stat: ?Stat = null, request_handle: bool = false, - /// Can request file or directory contents depending on `is_directory`. + /// Can request file or directory contents depending on `handle`. request_contents: bool = false, - /// Contents of a directory are considered to be the sorted list of - /// file names of direct entries, separated by null byte. Each file name - /// is prefixed by `Io.File.Kind` byte, +1 so that the zero tag is - /// not aliased by the entry separator. - is_directory: bool = false, /// Content hashing skipped; any difference in metadata implies cache /// miss. metadata_only: bool = false, }; - pub const AddInputFileError = error{ + pub const AddInputPathError = error{ /// The same file path has been added to the cache manifest both as a /// directory and as a normal file, making the intended caching /// behavior ambiguous. IsDirectoryAmbiguous, } || Allocator.Error; - /// Add a file as a dependency of process being cached. When `hit` is - /// called, the file's contents will be checked to ensure that it matches - /// the contents from previous times. + /// Add a file or directory path as a dependency of process being cached. + /// When `hit` is called, the contents will be checked to ensure + /// that it matches the contents from previous times. /// /// The contents of the input file may be requested and subsequently - /// obtained via methods of the returned `InputFile.Index` after calling + /// obtained via methods of the returned `InputPath.Index` after calling /// `hit`. - pub fn addInputFile(m: *Manifest, path: Path, options: AddInputFileOptions) Allocator.Error!InputFile.Index { + /// + /// Contents of a directory are considered to be the sorted list of file + /// names of direct entries, separated by null byte. Each file name is + /// prefixed by `Io.File.Kind` byte, +1 so that the zero tag is not aliased + /// by the entry separator. + /// + /// See also: + /// * `addPathPost` + pub fn addInputPath(m: *Manifest, path: Path, options: AddInputPathOptions) AddInputPathError!InputPath.Index { const gpa = m.cache.gpa; try m.files.ensureUnusedCapacity(gpa, 1); - try m.input_files.ensureUnusedCapacity(gpa, 1); + try m.input_paths.ensureUnusedCapacity(gpa, 1); const prev_contents_len = m.contents.items.len; const header: *File = @ptrCast(try m.contents.addManyAsSlice(gpa, @sizeOf(File))); @@ -558,7 +557,7 @@ pub const Manifest = struct { }); if (gop.found_existing) { m.contents.shrinkRetainingCapacity(prev_contents_len); - const existing_input_file = &m.input_files.items[gop.index]; + const existing_input_file = &m.input_paths.items[gop.index]; if (options.handle) |handle| { existing_input_file.handle = handle; existing_input_file.have_handle = true; @@ -579,7 +578,7 @@ pub const Manifest = struct { if (!options.metadata_only) existing_header.flags.metadata_only = false; } else { - m.input_files.appendAssumeCapacity(.{ + m.input_paths.appendAssumeCapacity(.{ .request_handle = options.request_handle, .have_handle = options.handle != null, .handle = if (options.handle) |handle| handle else undefined, @@ -587,7 +586,7 @@ pub const Manifest = struct { .have_digest = false, .have_stat = options.stat != null, }); - assert(m.input_files.items.len - 1 == gop.index); + assert(m.input_paths.items.len - 1 == gop.index); if (options.stat) |stat| { header.size = stat.size; header.inode = stat.inode; @@ -597,9 +596,9 @@ pub const Manifest = struct { return @fromBackingInt(gop.index); } - pub fn addInputFileOptional(m: *Manifest, opt_path: ?Path, options: AddInputFileOptions) Allocator.Error!void { + pub fn addInputFileOptional(m: *Manifest, opt_path: ?Path, options: AddInputPathOptions) Allocator.Error!void { m.hash.add(opt_path != null); - _ = try addInputFile(m, opt_path orelse return, options); + _ = try addInputPath(m, opt_path orelse return, options); } /// Check the cache to see if the input exists in it. @@ -623,8 +622,8 @@ pub const Manifest = struct { pub fn checkProgressless(man: *Manifest) Check.Error!Check.Status { assert(man.manifest_file == null); - for (man.files.keys()[0..man.input_files.items.len]) |file_off| { - file_off.get(man).manifestDigestHash(&man.hash.hasher); + for (man.files.keys()[0..man.input_paths.items.len]) |file_off| { + man.digestHash(file_off, &man.hash.hasher); } man.diagnostic = .none; @@ -709,16 +708,16 @@ pub const Manifest = struct { // We're going to construct a second hash. Its input will begin with the digest we've // already computed (`bin_digest`), and then it'll have the digests of each input file, - // including "post" files (see `addFilePost`). If this is a hit, we learn the set of "post" + // including "post" files (see `addPathPost`). If this is a hit, we learn the set of "post" // files from the manifest on disk. If this is a miss, we'll learn those from future calls - // to `addFilePost` etc. As such, the state of `man.hash.hasher` after this function + // to `addPathPost` etc. As such, the state of `man.hash.hasher` after this function // depends on whether this is a hit or a miss. // // If we return `CacheStatus.hit`, then `man.hash.hasher` must already include // the digests of the "post" files, so the caller can call `final`. Otherwise, on a cache // miss, `man.hash.hasher` will include the digests of all non-"post" files -- that is, // the ones we've already been told about. The rest will be discovered through calls to - // `addFilePost` etc, which will update the hasher. After all files are added, the user can + // `addPathPost` etc, which will update the hasher. After all files are added, the user can // use `final`, and will at some point `writeManifest` the file list to disk. man.hash.hasher = hasher_init; @@ -762,11 +761,11 @@ pub const Manifest = struct { } fn shrinkFilesToInput(m: *Manifest) void { - if (m.files.count() <= m.input_files.items.len) return; - const off = m.files.keys()[m.input_files.items.len]; + if (m.files.count() <= m.input_paths.items.len) return; + const off = m.files.keys()[m.input_paths.items.len]; m.contents.shrinkRetainingCapacity(@backingInt(off)); - assert(m.contents.len % @alignOf(File) == 0); - m.files.shrinkRetainingCapacity(m.input_files.items.len); + assert(m.contents.items.len % @alignOf(File) == 0); + m.files.shrinkRetainingCapacity(m.input_paths.items.len); } /// Assumes that `self.hash.hasher` has been updated only with the original digest and that @@ -784,59 +783,70 @@ pub const Manifest = struct { return error.CacheCheckFailed; }, }; + const contents = m.contents.items; - // Guess number of files based on manifest contents len to reduce allocations. - try m.files.ensureUnusedCapacity(gpa, m.contents.len / (@sizeOf(File) + 32)); + var off: u32 = 0; + var c: Check = .{}; - var file_index: usize = 0; - var off: usize = 0; - - // This group we always want to compute the hash digests, even on a cache miss. + // This group we always want to compute the hash digests, even on a + // cache miss, because they will be used in the manifest digest. var input_group: Io.Group = .init; defer input_group.cancel(io); + // First the input files section, which must match our input files, + // otherwise it's invalid format. + for (m.input_paths.items, m.files.keys()[0..m.input_paths.items.len]) |*input_path, input_file_off| { + if (off + 1 >= contents.len) return error.InvalidFormat; + const file_off: File.Offset = @fromBackingInt(off); + const file = try file_off.getFallible(contents); + if (file.flags.prefix >= m.cache.prefixes_len) return error.InvalidFormat; + const path = try filePathFallible(contents, file_off); + if (path.len == 0) return error.InvalidFormat; + if (input_file_off != file_off) return error.InvalidFormat; + + input_group.async(io, checkInputFile, .{ m, &c, file_off, path, input_path }); + + off = @intCast(@as(usize, off) + @sizeOf(File) + path.len + 1); + } + + // Guess number of files based on manifest contents len to reduce allocations. + // This is not an upper bound; subsequent insertions may potentially allocate. + try m.files.ensureUnusedCapacity(gpa, contents.len / (@sizeOf(File) + 32)); + // This group we would like to cancel as soon as a cache miss is discovered. const PostResult = union(enum) { checkFile: Check.Status, }; var post_select_buffer: [10]PostResult = undefined; - var post_select: Io.Select(PostResult) = .init(&post_select_buffer); + var post_select: Io.Select(PostResult) = .init(io, &post_select_buffer); var post_select_remaining: usize = 0; - var c: Check = .{}; - defer post_select.cancel(io); + defer post_select.cancelDiscard(); - while (off + 1 < m.contents.len) { + while (off + 1 < contents.len) { const file_off: File.Offset = @fromBackingInt(off); - const file = try File.getFallible(file_off, m); + const file = try file_off.getFallible(m); if (file.flags.prefix >= m.cache.prefixes_len) return error.InvalidFormat; - const path = try file.pathFallible(); + const path = try filePathFallible(contents, file_off); if (path.len == 0) return error.InvalidFormat; - if (file_index < m.input_files.items.len) { - if (m.files.keys()[file_index] != file_off) return error.InvalidFormat; + try m.files.put(gpa, file_off, {}); - input_group.async(io, checkInputFile, .{ m, &c, file_off, path }); - } else { - try m.files.put(gpa, file_off); + post_select.async(.checkFile, checkFile, .{ m, &c, file_off, path }); + post_select_remaining += 1; - post_select.async(.checkFile, checkFile, .{ m, &c, file_off, path }); - post_select_remaining += 1; - } - - file_index += 1; - off += @sizeOf(File) + path.len + 1; + off = @intCast(@as(usize, off) + @sizeOf(File) + path.len + 1); } // Final terminating zero byte to distinguish empty manifest file from // manifest with zero files. - const file_valid = off + 1 == m.contents.len and m.contents[off] == 0; - if (!file_valid or file_index < m.input_files.items.len) { + const file_valid = off + 1 == contents.len and contents[off] == 0; + if (!file_valid) { try input_group.await(io); return .miss; } // Don't track the trailing zero byte in contents. - m.contents.len -= 1; + m.contents.items.len -= 1; var post_await_buffer: [10]PostResult = undefined; while (post_select_remaining > 0) { @@ -880,11 +890,17 @@ pub const Manifest = struct { return .hit; } - fn checkInputFile(m: *Manifest, c: *Check, file_off: File.Offset, file_path: [:0]const u8) Io.Cancelable!void { - // TODO use already open handle - // TODO use already provided stat - // TODO implement request_handle - // TODO implement request_contents + fn checkInputFile( + m: *Manifest, + c: *Check, + file_off: File.Offset, + file_path: [:0]const u8, + input_path: *InputPath, + ) Io.Cancelable!void { + if (input_path.have_handle) @panic("TODO"); + if (input_path.have_stat) @panic("TODO"); + if (input_path.contents != .not_requested) @panic("TODO"); + if (input_path.request_handle) @panic("TODO"); switch (try checkFile(m, c, file_off, file_path)) { .hit => return, .miss => @atomicStore(Check.Status, &c.status, .miss, .unordered), @@ -897,7 +913,7 @@ pub const Manifest = struct { c: *Check, file_off: File.Offset, file_path: [:0]const u8, - ) Io.Cancelable!Check.Status { + ) error{ Canceled, CacheCheckFailed }!Check.Status { const file = file_off.get(m); const cache = m.cache; const gpa = cache.gpa; @@ -905,7 +921,7 @@ pub const Manifest = struct { const parent_dir = cache.prefixes()[file.flags.prefix].handle; if (file.flags.metadata_only) { - const actual_stat = parent_dir.statFile() catch |err| switch (err) { + const actual_stat = parent_dir.statFile(io, file_path, .{}) catch |err| switch (err) { error.FileNotFound => return .miss, error.Canceled => |e| return e, else => |e| return c.fail(m, .{ .file_stat = .{ @@ -999,10 +1015,10 @@ pub const Manifest = struct { /// not including post files). /// /// Assumes that `bin_digest` is populated for all input files. - pub fn unhit(man: *Manifest, bin_digest: BinDigest) void { + pub fn unhit(man: *Manifest, bin_digest: *const BinDigest) void { // Reset the hash. man.hash.hasher = hasher_init; - man.hash.hasher.update(&bin_digest); + man.hash.hasher.update(bin_digest); man.shrinkFilesToInput(); for (man.files.keys()) |off| { const file = off.get(man); @@ -1053,11 +1069,8 @@ pub const Manifest = struct { return timestamp.nanoseconds >= man.recent_problematic_timestamp.nanoseconds; } - pub const AddFilePostOptions = struct { - handle: union(enum) { - file: ?Io.File, - dir: ?Io.Dir, - } = .{ .file = null }, + pub const AddPathPostOptions = struct { + handle: PathHandle = .{ .file = null }, stat: ?Stat = null, /// If it is a directory, there is a special encoding required for contents, which /// is null-separated sorted entries, each one prefixed with `File.Kind`. @@ -1065,7 +1078,7 @@ pub const Manifest = struct { metadata_only: bool = false, }; - pub const AddFilePostError = error{ + pub const AddPathPostError = error{ /// The same file path has been added to the cache manifest both as a /// directory and as a normal file, making the intended caching /// behavior ambiguous. @@ -1074,7 +1087,10 @@ pub const Manifest = struct { /// Add a file as a dependency of process being cached, after cache miss /// occurs. - pub fn addFilePost(m: *Manifest, path: Path, options: AddFilePostOptions) AddFilePostError!void { + /// + /// See also: + /// * `addInputPath` + pub fn addPathPost(m: *Manifest, path: Path, options: AddPathPostOptions) AddPathPostError!void { assert(m.manifest_file != null); const cache = m.cache; const gpa = cache.gpa; @@ -1236,14 +1252,14 @@ pub const Manifest = struct { // Clang is invoked in single-source mode but other programs may not .target, .target_must_resolve => {}, .prereq => |file_path| if (self.manifest_file == null) { - _ = try self.addFilePath(.initCwd(file_path), null); - } else try self.addFilePost(file_path), + _ = try self.addInputPath(.initCwd(file_path), .{}); + } else try self.addPathPost(file_path), .prereq_must_resolve => { resolve_buf.clearRetainingCapacity(); try token.resolve(gpa, &resolve_buf); if (self.manifest_file == null) { - _ = try self.addFilePath(.initCwd(resolve_buf.items), null); - } else try self.addFilePost(resolve_buf.items); + _ = try self.addInputPath(.initCwd(resolve_buf.items), .{}); + } else try self.addPathPost(resolve_buf.items); }, else => |err| { try err.printError(gpa, &error_buf); @@ -1336,25 +1352,45 @@ pub const Manifest = struct { return .{ .manifest_file = self.manifest_file.? }; } - pub fn takeFiles(man: *Manifest) Files { - defer man.files = .empty; - return man.files; - } - - pub fn freeFiles(gpa: Allocator, files: *Files) void { - for (files.keys()) |*file| file.deinit(gpa); - files.deinit(gpa); + pub const SelfContainedFiles = struct { + /// References memory inside `contents`. + files: Files, + contents: std.ArrayList(u8), + + pub const empty: @This() = .{ + .files = .empty, + .contents = .empty, + }; + + pub fn deinit(scf: *SelfContainedFiles, gpa: Allocator) void { + scf.files.deinit(gpa); + scf.contents.deinit(gpa); + scf.* = undefined; + } + + pub fn path(scf: *const SelfContainedFiles, file_offset: File.Offset) [:0]const u8 { + return filePath(scf.contents.items, file_offset); + } + }; + + pub fn takeFiles(m: *Manifest) SelfContainedFiles { + defer m.files = .empty; + defer m.contents = .empty; + return .{ + .files = m.files, + .contents = m.contents, + }; } /// Releases the manifest file and frees any memory the Manifest was using. /// `Manifest.hit` must be called first. /// /// Don't forget to call `writeManifest` before this! - pub fn deinit(man: *Manifest) void { - const io = man.cache.io; - const gpa = man.cache.gpa; + pub fn deinit(m: *Manifest) void { + const io = m.cache.io; + const gpa = m.cache.gpa; - if (man.manifest_file) |file| { + if (m.manifest_file) |file| { if (builtin.os.tag == .windows) { // See Lock.release for why this is required on Windows file.unlock(io); @@ -1362,8 +1398,9 @@ pub const Manifest = struct { file.close(io); } - freeFiles(gpa, &man.files); - man.* = undefined; + m.files.deinit(gpa); + m.contents.deinit(gpa); + m.* = undefined; } pub fn populateFileSystemInputs(man: *Manifest, buf: *std.ArrayList(u8)) Allocator.Error!void { @@ -1497,6 +1534,25 @@ pub const Manifest = struct { hasher.update(contents.items[contents_start..][0..contents_len]); hasher.final(bin_digest); } + + fn digestHash(m: *const Manifest, off: File.Offset, hasher: *Hasher) void { + const contents = m.contents.items; + const flags_off = @offsetOf(File, "flags"); + comptime assert(@offsetOf(File, "path_start") - flags_off == 1); + const hash_start = @backingInt(off) + flags_off; + const hash_end = mem.findScalarPos(u8, contents, hash_start, 0).?; + hasher.update(contents[hash_start..hash_end]); + } + + fn filePathFallible(contents: []const u8, off: File.Offset) error{InvalidFormat}![:0]const u8 { + const path_start = @backingInt(off) + @offsetOf(File, "path_start"); + const path_end = mem.findScalarPos(u8, contents, path_start, 0) orelse return error.InvalidFormat; + return contents[path_start..path_end :0]; + } + + fn filePath(contents: []const u8, off: File.Offset) [:0]const u8 { + return filePathFallible(contents, off) catch unreachable; + } }; /// Create/Write a file, close it, then grab its stat.mtime timestamp. @@ -1555,7 +1611,7 @@ test "cache file and then recall it" { ch.hash.add(true); ch.hash.add(@as(u16, 1234)); ch.hash.addBytes("1234"); - _ = try ch.addFilePath(.initCwd(temp_file), null); + _ = try ch.addInputPath(.initCwd(temp_file), .{}); // There should be nothing in the cache try testing.expectEqual(false, try ch.hit(.none)); @@ -1570,7 +1626,7 @@ test "cache file and then recall it" { ch.hash.add(true); ch.hash.add(@as(u16, 1234)); ch.hash.addBytes("1234"); - _ = try ch.addFilePath(.initCwd(temp_file), null); + _ = try ch.addInputPath(.initCwd(temp_file), .{}); // Cache hit! We just "built" the same file try testing.expect(try ch.hit(.none)); @@ -1623,7 +1679,7 @@ test "check that changing a file makes cache fail" { defer ch.deinit(); ch.hash.addBytes("1234"); - const temp_file_idx = try ch.addFilePath(.initCwd(temp_file), 100); + const temp_file_idx = try ch.addInputPath(.initCwd(temp_file), .{ .request_contents = true }); // There should be nothing in the cache try testing.expectEqual(false, try ch.hit(.none)); @@ -1642,7 +1698,7 @@ test "check that changing a file makes cache fail" { defer ch.deinit(); ch.hash.addBytes("1234"); - const temp_file_idx = try ch.addFilePath(.initCwd(temp_file), 100); + const temp_file_idx = try ch.addInputPath(.initCwd(temp_file), .{ .request_contents = true }); // A file that we depend on has been updated, so the cache should not contain an entry for it try testing.expectEqual(false, try ch.hit(.none)); @@ -1689,7 +1745,7 @@ test "no file inputs" { man.hash.addBytes("1234"); // There should be nothing in the cache - try testing.expectEqual(false, try man.hit(.none)); + try testing.expectEqual(false, try man.check(.none)); digest1 = man.final(); @@ -1701,7 +1757,7 @@ test "no file inputs" { man.hash.addBytes("1234"); - try testing.expect(try man.hit(.none)); + try testing.expect(try man.check(.none)); digest2 = man.final(); try testing.expectEqual(false, man.have_exclusive_lock); } @@ -1750,12 +1806,12 @@ test "Manifest with files added after initial hash work" { defer ch.deinit(); ch.hash.addBytes("1234"); - _ = try ch.addFilePath(.initCwd(temp_file1), null); + _ = try ch.addInputPath(.initCwd(temp_file1), .{}); // There should be nothing in the cache try testing.expectEqual(false, try ch.hit(.none)); - _ = try ch.addFilePost(temp_file2); + _ = try ch.addPathPost(temp_file2); digest1 = ch.final(); try ch.writeManifest(); @@ -1765,7 +1821,7 @@ test "Manifest with files added after initial hash work" { defer ch.deinit(); ch.hash.addBytes("1234"); - _ = try ch.addFilePath(.initCwd(temp_file1), null); + _ = try ch.addInputPath(.initCwd(temp_file1), .{}); try testing.expect(try ch.hit(.none)); digest2 = ch.final(); @@ -1788,12 +1844,12 @@ test "Manifest with files added after initial hash work" { defer ch.deinit(); ch.hash.addBytes("1234"); - _ = try ch.addFilePath(.initCwd(temp_file1), null); + _ = try ch.addInputPath(.initCwd(temp_file1), .{}); // A file that we depend on has been updated, so the cache should not contain an entry for it try testing.expectEqual(false, try ch.hit(.none)); - _ = try ch.addFilePost(temp_file2); + _ = try ch.addPathPost(temp_file2); digest3 = ch.final(); diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig index 5634870483539bba2fd03b63ffc579967bc84710..19c26c404927671ace37a6082e42c4524f2b0717 100644 --- a/lib/std/Build/Configuration.zig +++ b/lib/std/Build/Configuration.zig @@ -1875,7 +1875,7 @@ pub const PathDep = extern struct { is_directory: bool, metadata_only: bool, base: LazyPath.Relative.Base, - _: u16 = 0, + _: u22 = 0, }; }; diff --git a/lib/std/Io/Reader.zig b/lib/std/Io/Reader.zig index da1894cc83b5e01e685cfce8cd96242ec943dcc1..d6508cef02a6c7e3b15a2eeac7ae19281fae6a35 100644 --- a/lib/std/Io/Reader.zig +++ b/lib/std/Io/Reader.zig @@ -393,6 +393,7 @@ pub fn appendRemainingAligned( pub const UnlimitedAllocError = Allocator.Error || ShortError; pub fn appendRemainingUnlimited(r: *Reader, gpa: Allocator, list: *ArrayList(u8)) UnlimitedAllocError!void { + list.pointer_stability.assertUnlocked(); var a: std.Io.Writer.Allocating = .initOwnedSlice(gpa, list.allocatedSlice()); a.writer.end = list.items.len; list.* = .empty; diff --git a/src/Compilation.zig b/src/Compilation.zig index 711b434c57d85cd9f6ae6df784f4b73a529b4b1e..fa8689ac273d744b1e85cbd1f6a86dfca1df6e24 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1340,19 +1340,19 @@ pub const cache_helpers = struct { } } - pub fn hashCSource(self: *Cache.Manifest, c_source: CSourceFile) !void { - _ = try self.addFilePath(.initCwd(c_source.src_path), null); + pub fn hashCSource(man: *Cache.Manifest, c_source: CSourceFile) !void { + _ = try man.addInputPath(.initCwd(c_source.src_path), .{}); // Hash the extra flags, with special care to call addFile for file parameters. // TODO this logic can likely be improved by utilizing clang_options_data.zig. const file_args = [_][]const u8{"-include"}; var arg_i: usize = 0; while (arg_i < c_source.extra_flags.len) : (arg_i += 1) { const arg = c_source.extra_flags[arg_i]; - self.hash.addBytes(arg); + man.hash.addBytes(arg); for (file_args) |file_arg| { if (mem.eql(u8, file_arg, arg) and arg_i + 1 < c_source.extra_flags.len) { arg_i += 1; - _ = try self.addFilePath(.initCwd(c_source.extra_flags[arg_i]), null); + _ = try man.addInputPath(.initCwd(c_source.extra_flags[arg_i]), .{}); } } } @@ -2830,7 +2830,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE man.want_shared_lock = false; } - const is_hit = man.hit(main_progress_node) catch |err| switch (err) { + const is_hit = man.check(main_progress_node) catch |err| switch (err) { error.Canceled, error.OutOfMemory => |e| return e, error.CacheCheckFailed => switch (man.diagnostic) { .none => unreachable, @@ -3394,7 +3394,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes try link.hashInputs(man, comp.link_inputs); for (comp.c_objects.items) |c_object| { - _ = try man.addFilePath(.initCwd(c_object.src.src_path), null); + _ = try man.addInputPath(.initCwd(c_object.src.src_path), .{}); man.hash.addOptional(c_object.src.ext); man.hash.addListOfBytes(c_object.src.extra_flags); } @@ -3402,11 +3402,11 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes for (comp.win32_resources.items) |win32_resource| { switch (win32_resource.src) { .rc => |rc_src| { - _ = try man.addFilePath(.initCwd(rc_src.src_path), null); + _ = try man.addInputPath(.initCwd(rc_src.src_path), .{}); man.hash.addListOfBytes(rc_src.extra_flags); }, .manifest => |manifest_path| { - _ = try man.addFilePath(.initCwd(manifest_path), null); + _ = try man.addInputPath(.initCwd(manifest_path), .{}); }, } } @@ -5540,7 +5540,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr const target = comp.getTarget(); assert(target.ofmt != .c); const o_ext = target.ofmt.fileExt(target.cpu.arch); - const digest = if (!comp.disable_c_depfile and try man.hit(child_progress_node)) man.final() else blk: { + const digest = if (!comp.disable_c_depfile and try man.check(child_progress_node)) man.final() else blk: { var argv: std.array_list.Managed([]const u8) = .init(gpa); defer argv.deinit(); @@ -5801,7 +5801,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr } // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. - if (comp.disable_c_depfile) _ = try man.hit(child_progress_node); + if (comp.disable_c_depfile) _ = try man.check(child_progress_node); // Rename into place. const digest = man.final(); @@ -5884,12 +5884,12 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // the XML data as a RT_MANIFEST resource. This means we can skip preprocessing, // include paths, CLI options, etc. if (win32_resource.src == .manifest) { - _ = try man.addFilePath(.initCwd(src_path), null); + _ = try man.addInputPath(.initCwd(src_path), .{}); const rc_basename = try std.fmt.allocPrint(arena, "{s}.rc", .{src_basename}); const res_basename = try std.fmt.allocPrint(arena, "{s}.res", .{src_basename}); - const digest = if (try man.hit(child_progress_node)) man.final() else blk: { + const digest = if (try man.check(child_progress_node)) man.final() else blk: { // The digest only depends on the .manifest file, so we can // get the digest now and write the .res directly to the cache const digest = man.final(); @@ -5977,12 +5977,12 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // We now know that we're compiling an .rc file const rc_src = win32_resource.src.rc; - _ = try man.addFilePath(.initCwd(rc_src.src_path), null); + _ = try man.addInputPath(.initCwd(rc_src.src_path), .{}); man.hash.addListOfBytes(rc_src.extra_flags); const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len]; - const digest = if (try man.hit(child_progress_node)) man.final() else blk: { + const digest = if (try man.check(child_progress_node)) man.final() else blk: { var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{}); defer zig_cache_tmp_dir.close(io); diff --git a/src/libs/freebsd.zig b/src/libs/freebsd.zig index d7b53387347e27ab502c13282dc99f8c75763df4..bda03f2787e4ff60e19e920ee3a43ab246366193 100644 --- a/src/libs/freebsd.zig +++ b/src/libs/freebsd.zig @@ -458,12 +458,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye man.hash.add(target.abi); man.hash.add(target_os_version); - const abilists_index = try man.addFilePath(.{ + const abilists_index = try man.addInputPath(.{ .root_dir = comp.dirs.zig_lib, .sub_path = abilists_path, - }, abilists_max_size); + }, .{ + .request_contents = true, + }); - if (try man.hit(prog_node)) { + if (try man.check(prog_node)) { const digest = man.final(); return queueSharedObjects(comp, .{ diff --git a/src/libs/glibc.zig b/src/libs/glibc.zig index ebc36af06304aa28b760477167ce0b04570abac3..67dd70eae78487ab5473c06a63bab226b91c6205 100644 --- a/src/libs/glibc.zig +++ b/src/libs/glibc.zig @@ -698,12 +698,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye man.hash.add(target.abi); man.hash.add(target_version); - const abilists_index = try man.addFilePath(.{ + const abilists_index = try man.addInputPath(.{ .root_dir = comp.dirs.zig_lib, .sub_path = abilists_path, - }, abilists_max_size); + }, .{ + .request_contents = true, + }); - if (try man.hit(prog_node)) { + if (try man.check(prog_node)) { const digest = man.final(); return queueSharedObjects(comp, .{ diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index a91c24291d0a395b189712c4d8f199bf13cd57d0..63c1e5ad16ccf7a745256242f528203d5a5cbdcf 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -246,12 +246,12 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P var man = cache.obtain(); defer man.deinit(); - _ = try man.addFilePath(def_file_path, null); + _ = try man.addInputPath(def_file_path, .{}); const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name}); errdefer gpa.free(final_lib_basename); - const is_hit = man.hit(prog_node) catch |err| switch (err) { + const is_hit = man.check(prog_node) catch |err| switch (err) { error.CacheCheckFailed => switch (man.diagnostic) { .none => unreachable, .manifest_create, .manifest_read, .manifest_lock => |e| { diff --git a/src/libs/netbsd.zig b/src/libs/netbsd.zig index b0fd269b22279b860426781e41a21e5297989c75..8cafe51563f5d6e32971fb77035f4f7e54d65409 100644 --- a/src/libs/netbsd.zig +++ b/src/libs/netbsd.zig @@ -406,12 +406,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye man.hash.add(target.abi); man.hash.add(target_version); - const abilists_index = try man.addFilePath(.{ + const abilists_index = try man.addInputPath(.{ .root_dir = comp.dirs.zig_lib, .sub_path = abilists_path, - }, abilists_max_size); + }, .{ + .request_contents = true, + }); - if (try man.hit(prog_node)) { + if (try man.check(prog_node)) { const digest = man.final(); return queueSharedObjects(comp, .{ diff --git a/src/libs/openbsd.zig b/src/libs/openbsd.zig index ba65dd46943a10fc8e61f2216e6762debf549e4a..dea2c5c3350afcced2f7c8c005a1ceb24a102f8d 100644 --- a/src/libs/openbsd.zig +++ b/src/libs/openbsd.zig @@ -327,12 +327,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye man.hash.add(target.abi); man.hash.add(target_version); - const abilists_index = try man.addFilePath(.{ + const abilists_index = try man.addInputPath(.{ .root_dir = comp.dirs.zig_lib, .sub_path = abilists_path, - }, abilists_max_size); + }, .{ + .request_contents = true, + }); - if (try man.hit(prog_node)) { + if (try man.check(prog_node)) { const digest = man.final(); return queueSharedObjects(comp, .{ diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 72e34b943e1d565e6c3360cfd017b4d9c7ba3f5e..c32301b826482026993bfb7e8763357cd57dbf06 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -155,7 +155,7 @@ pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { for (hm) |value| { man.hash.add(value.needed); man.hash.add(value.weak); - _ = try man.addFilePath(value.path, null); + _ = try man.addInputPath(value.path, .{}); } } diff --git a/src/main.zig b/src/main.zig index ea09d77f914ff36cea3d6e84738a84b0e189f093..46f81a0ba26b56251c1795626320ad8b542c3392 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4862,7 +4862,7 @@ fn cmdTranslateC( Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| fatal("unable to process {q}: {t}", .{ c_source_file.src_path, err }); - const result: Compilation.TranslateCResult = if (try man.hit(prog_node)) .{ + const result: Compilation.TranslateCResult = if (try man.check(prog_node)) .{ .digest = man.finalBin(), .cache_hit = true, .errors = std.zig.ErrorBundle.empty, -- 2.54.0