| ... | ... | @@ -166,11 +166,13 @@ error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 166 | 166 | |
| 167 | 167 | load_commands_dirty: bool = false, |
| 168 | 168 | sections_order_dirty: bool = false, |
| 169 | | |
| 170 | 169 | has_dices: bool = false, |
| 171 | 170 | has_stabs: bool = false, |
| 172 | | |
| 173 | | args_digest: [Cache.hex_digest_len]u8 = undefined, |
| 171 | /// A helper var to indicate if we are at the start of the incremental updates, or |
| 172 | /// already somewhere further along the update-and-run chain. |
| 173 | /// TODO once we add opening a prelinked output binary from file, this will become |
| 174 | /// obsolete as we will carry on where we left off. |
| 175 | cold_start: bool = false, |
| 174 | 176 | |
| 175 | 177 | section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, |
| 176 | 178 | |
| ... | ... | @@ -336,6 +338,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 336 | 338 | return self; |
| 337 | 339 | } |
| 338 | 340 | |
| 341 | // TODO Migrate DebugSymbols to the merged linker codepaths |
| 339 | 342 | // if (!options.strip and options.module != null) { |
| 340 | 343 | // // Create dSYM bundle. |
| 341 | 344 | // const dir = options.module.?.zig_cache_artifact_directory; |
| ... | ... | @@ -456,8 +459,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 456 | 459 | defer if (!self.base.options.disable_lld_caching) man.deinit(); |
| 457 | 460 | |
| 458 | 461 | var digest: [Cache.hex_digest_len]u8 = undefined; |
| 462 | var needs_full_relink = true; |
| 463 | |
| 464 | cache: { |
| 465 | if (use_stage1 and self.base.options.disable_lld_caching) break :cache; |
| 459 | 466 | |
| 460 | | if (!self.base.options.disable_lld_caching) { |
| 461 | 467 | man = comp.cache_parent.obtain(); |
| 462 | 468 | |
| 463 | 469 | // We are about to obtain this lock, so here we give other processes a chance first. |
| ... | ... | @@ -491,17 +497,36 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 491 | 497 | id_symlink_basename, |
| 492 | 498 | &prev_digest_buf, |
| 493 | 499 | ) catch |err| blk: { |
| 494 | | log.debug("MachO Zld new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) }); |
| 500 | log.debug("MachO Zld new_digest={s} error: {s}", .{ |
| 501 | std.fmt.fmtSliceHexLower(&digest), |
| 502 | @errorName(err), |
| 503 | }); |
| 495 | 504 | // Handle this as a cache miss. |
| 496 | 505 | break :blk prev_digest_buf[0..0]; |
| 497 | 506 | }; |
| 498 | 507 | if (mem.eql(u8, prev_digest, &digest)) { |
| 499 | | log.debug("MachO Zld digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)}); |
| 500 | 508 | // Hot diggity dog! The output binary is already there. |
| 501 | | self.base.lock = man.toOwnedLock(); |
| 502 | | return; |
| 509 | |
| 510 | if (use_stage1) { |
| 511 | log.debug("MachO Zld digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)}); |
| 512 | self.base.lock = man.toOwnedLock(); |
| 513 | return; |
| 514 | } else { |
| 515 | log.debug("MachO Zld digest={s} match", .{std.fmt.fmtSliceHexLower(&digest)}); |
| 516 | if (!self.cold_start) { |
| 517 | log.debug(" no need to relink objects", .{}); |
| 518 | needs_full_relink = false; |
| 519 | } else { |
| 520 | log.debug(" TODO parse prelinked binary and continue linking where we left off", .{}); |
| 521 | // TODO until such time however, perform a full relink of objects. |
| 522 | needs_full_relink = true; |
| 523 | } |
| 524 | } |
| 503 | 525 | } |
| 504 | | log.debug("MachO Zld prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) }); |
| 526 | log.debug("MachO Zld prev_digest={s} new_digest={s}", .{ |
| 527 | std.fmt.fmtSliceHexLower(prev_digest), |
| 528 | std.fmt.fmtSliceHexLower(&digest), |
| 529 | }); |
| 505 | 530 | |
| 506 | 531 | // We are about to change the output file to be different, so we invalidate the build hash now. |
| 507 | 532 | directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) { |
| ... | ... | @@ -509,7 +534,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 509 | 534 | else => |e| return e, |
| 510 | 535 | }; |
| 511 | 536 | } |
| 512 | | |
| 513 | 537 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); |
| 514 | 538 | |
| 515 | 539 | if (self.base.options.output_mode == .Obj) { |
| ... | ... | @@ -557,34 +581,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 557 | 581 | try self.strtab.append(self.base.allocator, 0); |
| 558 | 582 | } |
| 559 | 583 | |
| 560 | | const needs_full_relink = blk: { |
| 561 | | if (use_stage1) break :blk true; |
| 562 | | |
| 563 | | var hh: Cache.HashHelper = .{}; |
| 564 | | hh.addListOfBytes(self.base.options.objects); |
| 565 | | for (comp.c_object_table.keys()) |key| { |
| 566 | | hh.addBytes(key.status.success.object_path); |
| 567 | | } |
| 568 | | hh.addOptionalBytes(module_obj_path); |
| 569 | | if (comp.compiler_rt_static_lib) |lib| { |
| 570 | | hh.addBytes(lib.full_object_path); |
| 571 | | } |
| 572 | | if (self.base.options.link_libcpp) { |
| 573 | | hh.addBytes(comp.libcxxabi_static_lib.?.full_object_path); |
| 574 | | hh.addBytes(comp.libcxx_static_lib.?.full_object_path); |
| 575 | | } |
| 576 | | hh.addListOfBytes(self.base.options.lib_dirs); |
| 577 | | hh.addListOfBytes(self.base.options.framework_dirs); |
| 578 | | hh.addListOfBytes(self.base.options.frameworks); |
| 579 | | hh.addListOfBytes(self.base.options.rpath_list); |
| 580 | | hh.addStringSet(self.base.options.system_libs); |
| 581 | | hh.addOptionalBytes(self.base.options.sysroot); |
| 582 | | const new_digest = hh.final(); |
| 583 | | const needs_full_relink = !mem.eql(u8, &new_digest, &self.args_digest); |
| 584 | | mem.copy(u8, &self.args_digest, &new_digest); |
| 585 | | break :blk needs_full_relink; |
| 586 | | }; |
| 587 | | |
| 588 | 584 | if (needs_full_relink) { |
| 589 | 585 | self.objects.clearRetainingCapacity(); |
| 590 | 586 | self.archives.clearRetainingCapacity(); |
| ... | ... | @@ -848,22 +844,6 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 848 | 844 | try self.allocateGlobalSymbols(); |
| 849 | 845 | try self.writeAtoms(); |
| 850 | 846 | |
| 851 | | // log.warn("Locals:", .{}); |
| 852 | | // for (self.locals.items) |sym, i| { |
| 853 | | // log.warn(" => {d}: {s}, {}", .{ i, self.getString(sym.n_strx), sym }); |
| 854 | | // } |
| 855 | | // log.warn("Globals:", .{}); |
| 856 | | // for (self.globals.items) |sym, i| { |
| 857 | | // log.warn(" => {d}: {s} {}", .{ i, self.getString(sym.n_strx), sym }); |
| 858 | | // } |
| 859 | | // { |
| 860 | | // log.warn("Resolver:", .{}); |
| 861 | | // var it = self.symbol_resolver.iterator(); |
| 862 | | // while (it.next()) |entry| { |
| 863 | | // log.warn(" => {s}: {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* }); |
| 864 | | // } |
| 865 | | // } |
| 866 | | |
| 867 | 847 | if (self.bss_section_index) |idx| { |
| 868 | 848 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 869 | 849 | const sect = &seg.sections.items[idx]; |
| ... | ... | @@ -880,7 +860,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 880 | 860 | try self.flushModule(comp); |
| 881 | 861 | } |
| 882 | 862 | |
| 883 | | if (!self.base.options.disable_lld_caching) { |
| 863 | cache: { |
| 864 | if (use_stage1 and self.base.options.disable_lld_caching) break :cache; |
| 884 | 865 | // Update the file with the digest. If it fails we can continue; it only |
| 885 | 866 | // means that the next invocation will have an unnecessary cache miss. |
| 886 | 867 | Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| { |
| ... | ... | @@ -894,6 +875,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 894 | 875 | // other processes clobbering it. |
| 895 | 876 | self.base.lock = man.toOwnedLock(); |
| 896 | 877 | } |
| 878 | |
| 879 | self.cold_start = false; |
| 897 | 880 | } |
| 898 | 881 | |
| 899 | 882 | pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| ... | ... | @@ -3929,6 +3912,8 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3929 | 3912 | }); |
| 3930 | 3913 | self.load_commands_dirty = true; |
| 3931 | 3914 | } |
| 3915 | |
| 3916 | self.cold_start = true; |
| 3932 | 3917 | } |
| 3933 | 3918 | |
| 3934 | 3919 | const AllocateSectionOpts = struct { |