From e567abb339e1edaf5a3c86fe632522a3b8005275 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 16 Oct 2024 12:14:19 -0700 Subject: rework linker inputs * Compilation.objects changes to Compilation.link_inputs which stores objects, archives, windows resources, shared objects, and strings intended to be put directly into the dynamic section. Order is now preserved between all of these kinds of linker inputs. If it is determined the order does not matter for a particular kind of linker input, that item should be moved to a different array. * rename system_libs to windows_libs * untangle library lookup from CLI types * when doing library lookup, instead of using access syscalls, go ahead and open the files and keep the handles around for passing to the cache system and the linker. * during library lookup and cache file hashing, use positioned reads to avoid affecting the file seek position. * library directories are opened in the CLI and converted to Directory objects, warnings emitted for those that cannot be opened. --- lib/std/Build/Cache.zig | 57 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 16 deletions(-) (limited to 'lib/std/Build/Cache.zig') diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index bd98634ba8..7f8a6d3159 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -142,6 +142,9 @@ pub const hasher_init: Hasher = Hasher.init(&[_]u8{ pub const File = struct { prefixed_path: PrefixedPath, max_file_size: ?usize, + /// Populated if the user calls `addOpenedFile`. + /// The handle is not owned here. + handle: ?fs.File, stat: Stat, bin_digest: BinDigest, contents: ?[]const u8, @@ -173,6 +176,11 @@ pub const File = struct { const new = new_max_size orelse return; file.max_file_size = if (file.max_file_size) |old| @max(old, new) else new; } + + pub fn updateHandle(file: *File, new_handle: ?fs.File) void { + const handle = new_handle orelse return; + file.handle = handle; + } }; pub const HashHelper = struct { @@ -363,15 +371,20 @@ pub const Manifest = struct { /// var file_contents = cache_hash.files.keys()[file_index].contents.?; /// ``` pub fn addFilePath(m: *Manifest, file_path: Path, max_file_size: ?usize) !usize { + return addOpenedFile(m, file_path, null, max_file_size); + } + + /// Same as `addFilePath` except the file has already been opened. + pub fn addOpenedFile(m: *Manifest, path: Path, handle: ?fs.File, max_file_size: ?usize) !usize { const gpa = m.cache.gpa; try m.files.ensureUnusedCapacity(gpa, 1); const resolved_path = try fs.path.resolve(gpa, &.{ - file_path.root_dir.path orelse ".", - file_path.subPathOrDot(), + path.root_dir.path orelse ".", + path.subPathOrDot(), }); errdefer gpa.free(resolved_path); const prefixed_path = try m.cache.findPrefixResolved(resolved_path); - return addFileInner(m, prefixed_path, max_file_size); + return addFileInner(m, prefixed_path, handle, max_file_size); } /// Deprecated; use `addFilePath`. @@ -383,13 +396,14 @@ pub const Manifest = struct { const prefixed_path = try self.cache.findPrefix(file_path); errdefer gpa.free(prefixed_path.sub_path); - return addFileInner(self, prefixed_path, max_file_size); + return addFileInner(self, prefixed_path, null, max_file_size); } - fn addFileInner(self: *Manifest, prefixed_path: PrefixedPath, max_file_size: ?usize) !usize { + fn addFileInner(self: *Manifest, prefixed_path: PrefixedPath, handle: ?fs.File, max_file_size: ?usize) usize { const gop = self.files.getOrPutAssumeCapacityAdapted(prefixed_path, FilesAdapter{}); if (gop.found_existing) { gop.key_ptr.updateMaxSize(max_file_size); + gop.key_ptr.updateHandle(handle); return gop.index; } gop.key_ptr.* = .{ @@ -398,6 +412,7 @@ pub const Manifest = struct { .max_file_size = max_file_size, .stat = undefined, .bin_digest = undefined, + .handle = handle, }; self.hash.add(prefixed_path.prefix); @@ -565,6 +580,7 @@ pub const Manifest = struct { }, .contents = null, .max_file_size = null, + .handle = null, .stat = .{ .size = stat_size, .inode = stat_inode, @@ -708,12 +724,19 @@ pub const Manifest = struct { } fn populateFileHash(self: *Manifest, ch_file: *File) !void { - const pp = ch_file.prefixed_path; - const dir = self.cache.prefixes()[pp.prefix].handle; - const file = try dir.openFile(pp.sub_path, .{}); - defer file.close(); + if (ch_file.handle) |handle| { + return populateFileHashHandle(self, ch_file, handle); + } else { + const pp = ch_file.prefixed_path; + const dir = self.cache.prefixes()[pp.prefix].handle; + const handle = try dir.openFile(pp.sub_path, .{}); + defer handle.close(); + return populateFileHashHandle(self, ch_file, handle); + } + } - const actual_stat = try file.stat(); + fn populateFileHashHandle(self: *Manifest, ch_file: *File, handle: fs.File) !void { + const actual_stat = try handle.stat(); ch_file.stat = .{ .size = actual_stat.size, .mtime = actual_stat.mtime, @@ -739,8 +762,7 @@ pub const Manifest = struct { var hasher = hasher_init; var off: usize = 0; while (true) { - // give me everything you've got, captain - const bytes_read = try file.read(contents[off..]); + const bytes_read = try handle.pread(contents[off..], off); if (bytes_read == 0) break; hasher.update(contents[off..][0..bytes_read]); off += bytes_read; @@ -749,7 +771,7 @@ pub const Manifest = struct { ch_file.contents = contents; } else { - try hashFile(file, &ch_file.bin_digest); + try hashFile(handle, &ch_file.bin_digest); } self.hash.hasher.update(&ch_file.bin_digest); @@ -813,6 +835,7 @@ pub const Manifest = struct { gop.key_ptr.* = .{ .prefixed_path = prefixed_path, .max_file_size = null, + .handle = null, .stat = undefined, .bin_digest = undefined, .contents = null, @@ -851,6 +874,7 @@ pub const Manifest = struct { new_file.* = .{ .prefixed_path = prefixed_path, .max_file_size = null, + .handle = null, .stat = stat, .bin_digest = undefined, .contents = null, @@ -1067,6 +1091,7 @@ pub const Manifest = struct { gop.key_ptr.* = .{ .prefixed_path = prefixed_path, .max_file_size = file.max_file_size, + .handle = file.handle, .stat = file.stat, .bin_digest = file.bin_digest, .contents = null, @@ -1103,14 +1128,14 @@ pub fn writeSmallFile(dir: fs.Dir, sub_path: []const u8, data: []const u8) !void fn hashFile(file: fs.File, bin_digest: *[Hasher.mac_length]u8) !void { var buf: [1024]u8 = undefined; - var hasher = hasher_init; + var off: u64 = 0; while (true) { - const bytes_read = try file.read(&buf); + const bytes_read = try file.pread(&buf, off); if (bytes_read == 0) break; hasher.update(buf[0..bytes_read]); + off += bytes_read; } - hasher.final(bin_digest); } -- cgit v1.2.3