| author | |
| committer | |
| log | e8090258b5ca045d7b89fdf625115477514880e0 |
| tree | 9256ae8ba431623b995ea8ba49d6973a24b43ebe |
| parent | e4b624eb7663ff3f3e10bff48024e7955d92b204 |
When using Compilation.Path, we already know the path prefix, so just
use that directly instead of taking a detour through absolute paths.
Also, when using whole cache mode, don't call
`addModuleTableToCacheHash` because it is redundant with the logic
in `PerThread.update` which iterates over `zcu.alive_files` and adds
those files discovered via `@import` to the whole cache manifest.
That was causing files relative to cwd to be added to cache manifest
rather than being relative to build_root.5 files changed, 98 insertions(+), 35 deletions(-)
lib/std/Build/Cache.zig+23-14| ... | ... | @@ -1032,24 +1032,32 @@ pub const Manifest = struct { |
| 1032 | 1032 | |
| 1033 | 1033 | /// Like `addFilePost` but when the file contents have already been loaded from disk. |
| 1034 | 1034 | pub fn addFilePostContents( |
| 1035 | self: *Manifest, | |
| 1035 | man: *Manifest, | |
| 1036 | 1036 | file_path: []const u8, |
| 1037 | 1037 | bytes: []const u8, |
| 1038 | 1038 | stat: File.Stat, |
| 1039 | 1039 | ) !void { |
| 1040 | assert(self.manifest_file != null); | |
| 1041 | const gpa = self.cache.gpa; | |
| 1042 | ||
| 1043 | const prefixed_path = try self.cache.findPrefix(file_path); | |
| 1044 | errdefer gpa.free(prefixed_path.sub_path); | |
| 1040 | assert(man.manifest_file != null); | |
| 1041 | const gpa = man.cache.gpa; | |
| 1042 | const prefixed_path = try man.cache.findPrefix(file_path); | |
| 1043 | var keep = false; | |
| 1044 | defer if (!keep) gpa.free(prefixed_path.sub_path); | |
| 1045 | keep = try addPrefixedPathPostContents(man, prefixed_path, bytes, stat); | |
| 1046 | } | |
| 1045 | 1047 | |
| 1046 | const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{}); | |
| 1047 | errdefer _ = self.files.pop(); | |
| 1048 | /// Low level function. `prefixed_path` references cloned memory. Returns | |
| 1049 | /// whether or not `prefixed_path.sub_path` should be kept. | |
| 1050 | pub fn addPrefixedPathPostContents( | |
| 1051 | man: *Manifest, | |
| 1052 | prefixed_path: PrefixedPath, | |
| 1053 | bytes: []const u8, | |
| 1054 | stat: File.Stat, | |
| 1055 | ) !bool { | |
| 1056 | const gpa = man.cache.gpa; | |
| 1057 | const gop = try man.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{}); | |
| 1058 | errdefer _ = man.files.pop(); | |
| 1048 | 1059 | |
| 1049 | if (gop.found_existing) { | |
| 1050 | gpa.free(prefixed_path.sub_path); | |
| 1051 | return; | |
| 1052 | } | |
| 1060 | if (gop.found_existing) return false; | |
| 1053 | 1061 | |
| 1054 | 1062 | const new_file = gop.key_ptr; |
| 1055 | 1063 | |
| ... | ... | @@ -1062,7 +1070,7 @@ pub const Manifest = struct { |
| 1062 | 1070 | .contents = null, |
| 1063 | 1071 | }; |
| 1064 | 1072 | |
| 1065 | if (try self.isProblematicTimestamp(new_file.stat.mtime)) { | |
| 1073 | if (try man.isProblematicTimestamp(new_file.stat.mtime)) { | |
| 1066 | 1074 | // The actual file has an unreliable timestamp, force it to be hashed |
| 1067 | 1075 | new_file.stat.mtime = .zero; |
| 1068 | 1076 | new_file.stat.inode = 0; |
| ... | ... | @@ -1074,7 +1082,8 @@ pub const Manifest = struct { |
| 1074 | 1082 | hasher.final(&new_file.bin_digest); |
| 1075 | 1083 | } |
| 1076 | 1084 | |
| 1077 | self.hash.hasher.update(&new_file.bin_digest); | |
| 1085 | man.hash.hasher.update(&new_file.bin_digest); | |
| 1086 | return true; | |
| 1078 | 1087 | } |
| 1079 | 1088 | |
| 1080 | 1089 | pub fn addDepFilePost(self: *Manifest, dir: Io.Dir, dep_file_sub_path: []const u8) !void { |
src/Compilation.zig+69-9| ... | ... | @@ -506,10 +506,11 @@ pub const Path = struct { |
| 506 | 506 | // so that we prefer `.root = .local_cache` over `.root = .zig_lib`. The easiest way to do |
| 507 | 507 | // this is simply to prioritize the longest root path. |
| 508 | 508 | const PathAndRoot = struct { ?[]const u8, Root }; |
| 509 | var roots: [3]PathAndRoot = .{ | |
| 509 | var roots: [4]PathAndRoot = .{ | |
| 510 | 510 | .{ dirs.zig_lib.path, .zig_lib }, |
| 511 | 511 | .{ dirs.global_cache.path, .global_cache }, |
| 512 | 512 | .{ dirs.local_cache.path, .local_cache }, |
| 513 | .{ dirs.build_root.path, .build_root }, | |
| 513 | 514 | }; |
| 514 | 515 | // This must be a stable sort, because the global and local cache directories may be the same, in |
| 515 | 516 | // which case we need to make a consistent choice. |
| ... | ... | @@ -660,7 +661,7 @@ pub const Path = struct { |
| 660 | 661 | /// This should not be used for most of the compiler pipeline, but is useful when emitting |
| 661 | 662 | /// paths from the compilation (e.g. in debug info), because they will not depend on the cwd. |
| 662 | 663 | /// The returned path is owned by the caller and allocated into `gpa`. |
| 663 | pub fn toAbsolute(p: Path, dirs: std.zig.Directories, gpa: Allocator) Allocator.Error![]u8 { | |
| 664 | pub fn toAbsolute(p: Path, dirs: *const std.zig.Directories, gpa: Allocator) Allocator.Error![]u8 { | |
| 664 | 665 | const root_path: []const u8 = switch (p.root) { |
| 665 | 666 | .zig_lib => dirs.zig_lib.path orelse "", |
| 666 | 667 | .global_cache => dirs.global_cache.path orelse "", |
| ... | ... | @@ -701,6 +702,66 @@ pub const Path = struct { |
| 701 | 702 | .no, .different_roots => false, |
| 702 | 703 | }; |
| 703 | 704 | } |
| 705 | ||
| 706 | pub fn addToCacheManifestPostHit(p: Path, man: *Cache.Manifest, dirs: *const std.zig.Directories) !void { | |
| 707 | comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd)); | |
| 708 | comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib)); | |
| 709 | comptime assert(2 == @backingInt(std.zig.Server.Message.PathPrefix.local_cache)); | |
| 710 | comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache)); | |
| 711 | comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root)); | |
| 712 | comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5); | |
| 713 | const gpa = man.cache.gpa; | |
| 714 | const prefixed_path: Cache.PrefixedPath = .{ | |
| 715 | .prefix = switch (p.root) { | |
| 716 | .none => { | |
| 717 | const path = try p.toAbsolute(dirs, gpa); | |
| 718 | defer gpa.free(path); | |
| 719 | return man.addFilePost(path); | |
| 720 | }, | |
| 721 | .zig_lib => 1, | |
| 722 | .local_cache => 2, | |
| 723 | .global_cache => 3, | |
| 724 | .build_root => 4, | |
| 725 | }, | |
| 726 | .sub_path = try gpa.dupe(u8, p.sub_path), | |
| 727 | }; | |
| 728 | var keep = false; | |
| 729 | defer if (!keep) gpa.free(prefixed_path.sub_path); | |
| 730 | keep = try man.addPrefixedPathPost(prefixed_path); | |
| 731 | } | |
| 732 | ||
| 733 | pub fn addToCacheManifestPostHitContents( | |
| 734 | p: Path, | |
| 735 | man: *Cache.Manifest, | |
| 736 | dirs: *const std.zig.Directories, | |
| 737 | bytes: []const u8, | |
| 738 | stat: Cache.File.Stat, | |
| 739 | ) !void { | |
| 740 | comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd)); | |
| 741 | comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib)); | |
| 742 | comptime assert(2 == @backingInt(std.zig.Server.Message.PathPrefix.local_cache)); | |
| 743 | comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache)); | |
| 744 | comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root)); | |
| 745 | comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5); | |
| 746 | const gpa = man.cache.gpa; | |
| 747 | const prefixed_path: Cache.PrefixedPath = .{ | |
| 748 | .prefix = switch (p.root) { | |
| 749 | .none => { | |
| 750 | const path = try p.toAbsolute(dirs, gpa); | |
| 751 | defer gpa.free(path); | |
| 752 | return man.addFilePostContents(path, bytes, stat); | |
| 753 | }, | |
| 754 | .zig_lib => 1, | |
| 755 | .local_cache => 2, | |
| 756 | .global_cache => 3, | |
| 757 | .build_root => 4, | |
| 758 | }, | |
| 759 | .sub_path = try gpa.dupe(u8, p.sub_path), | |
| 760 | }; | |
| 761 | var keep = false; | |
| 762 | defer if (!keep) gpa.free(prefixed_path.sub_path); | |
| 763 | keep = try man.addPrefixedPathPostContents(prefixed_path, bytes, stat); | |
| 764 | } | |
| 704 | 765 | }; |
| 705 | 766 | |
| 706 | 767 | /// This small wrapper function just checks whether debug extensions are enabled before checking |
| ... | ... | @@ -2776,7 +2837,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2776 | 2837 | |
| 2777 | 2838 | man = comp.cache_parent.obtain(); |
| 2778 | 2839 | whole.cache_manifest = &man; |
| 2779 | try addNonIncrementalStuffToCacheManifest(comp, arena, &man); | |
| 2840 | try addNonIncrementalStuffToCacheManifest(comp, &man); | |
| 2780 | 2841 | |
| 2781 | 2842 | // Under `--time-report`, ignore cache hits; do the work anyway for those juicy numbers. |
| 2782 | 2843 | const ignore_hit = comp.time_report != null; |
| ... | ... | @@ -3328,15 +3389,14 @@ fn renameTmpIntoCache( |
| 3328 | 3389 | /// anything from the link cache manifest. |
| 3329 | 3390 | pub const link_hash_implementation_version = 14; |
| 3330 | 3391 | |
| 3331 | fn addNonIncrementalStuffToCacheManifest( | |
| 3332 | comp: *Compilation, | |
| 3333 | arena: Allocator, | |
| 3334 | man: *Cache.Manifest, | |
| 3335 | ) !void { | |
| 3392 | fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void { | |
| 3336 | 3393 | comptime assert(link_hash_implementation_version == 14); |
| 3337 | 3394 | |
| 3338 | 3395 | if (comp.zcu) |zcu| { |
| 3339 | try addModuleTableToCacheHash(zcu, arena, &man.hash, .{ .files = man }); | |
| 3396 | // No need to call `addModuleTableToCacheHash` here because it is | |
| 3397 | // redundant with the logic in `PerThread.update` which iterates over | |
| 3398 | // `zcu.alive_files` and adds those files discovered via `@import` to | |
| 3399 | // the whole cache manifest. | |
| 3340 | 3400 | |
| 3341 | 3401 | // Synchronize with other matching comments: ZigOnlyHashStuff |
| 3342 | 3402 | man.hash.addListOfBytes(comp.test_filters); |
src/Zcu/PerThread.zig+4-10| ... | ... | @@ -221,22 +221,19 @@ pub fn update( |
| 221 | 221 | .astgen_failure, .success => {}, // the file was read successfully |
| 222 | 222 | } |
| 223 | 223 | |
| 224 | const path = try file.path.toAbsolute(comp.dirs, gpa); | |
| 225 | defer gpa.free(path); | |
| 226 | ||
| 227 | 224 | const result = res: { |
| 228 | 225 | try whole.cache_manifest_mutex.lock(io); |
| 229 | 226 | defer whole.cache_manifest_mutex.unlock(io); |
| 230 | 227 | if (file.source) |source| { |
| 231 | break :res man.addFilePostContents(path, source, file.stat); | |
| 228 | break :res file.path.addToCacheManifestPostHitContents(man, &comp.dirs, source, file.stat); | |
| 232 | 229 | } else { |
| 233 | break :res man.addFilePost(path); | |
| 230 | break :res file.path.addToCacheManifestPostHit(man, &comp.dirs); | |
| 234 | 231 | } |
| 235 | 232 | }; |
| 236 | 233 | result catch |err| switch (err) { |
| 237 | 234 | error.OutOfMemory => |e| return e, |
| 238 | 235 | else => { |
| 239 | try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); | |
| 236 | try pt.reportRetryableFileError(file_index, "unable to update cache: {t}", .{err}); | |
| 240 | 237 | continue; |
| 241 | 238 | }, |
| 242 | 239 | }; |
| ... | ... | @@ -2965,13 +2962,10 @@ fn newEmbedFile( |
| 2965 | 2962 | const array_len = Value.fromInterned(new_file.val).typeOf(zcu).childType(zcu).arrayLen(zcu); |
| 2966 | 2963 | const contents = ip_str.toSlice(array_len, ip); |
| 2967 | 2964 | |
| 2968 | const path_str = try path.toAbsolute(comp.dirs, gpa); | |
| 2969 | defer gpa.free(path_str); | |
| 2970 | ||
| 2971 | 2965 | try whole.cache_manifest_mutex.lock(io); |
| 2972 | 2966 | defer whole.cache_manifest_mutex.unlock(io); |
| 2973 | 2967 | |
| 2974 | try man.addFilePostContents(path_str, contents, new_file.stat); | |
| 2968 | try path.addToCacheManifestPostHitContents(man, &comp.dirs, contents, new_file.stat); | |
| 2975 | 2969 | } |
| 2976 | 2970 | |
| 2977 | 2971 | return new_file; |
src/codegen/llvm.zig+1-1| ... | ... | @@ -481,7 +481,7 @@ pub const Object = struct { |
| 481 | 481 | // way already, but here we throw all that sweet information |
| 482 | 482 | // into the garbage can by converting into absolute paths. What |
| 483 | 483 | // a terrible tragedy. |
| 484 | const compile_unit_dir = try zcu.main_mod.root.toAbsolute(comp.dirs, arena); | |
| 484 | const compile_unit_dir = try zcu.main_mod.root.toAbsolute(&comp.dirs, arena); | |
| 485 | 485 | |
| 486 | 486 | const debug_file = try builder.debugFile( |
| 487 | 487 | try builder.metadataString(comp.root_name), |
src/link/Dwarf.zig+1-1| ... | ... | @@ -4735,7 +4735,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err |
| 4735 | 4735 | } |
| 4736 | 4736 | |
| 4737 | 4737 | for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| { |
| 4738 | const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, dwarf.gpa); | |
| 4738 | const root_dir_path = try mod.root.toAbsolute(&zcu.comp.dirs, dwarf.gpa); | |
| 4739 | 4739 | defer dwarf.gpa.free(root_dir_path); |
| 4740 | 4740 | mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path); |
| 4741 | 4741 | } |