Commit 7f01b61679

Jakub Konka <kubkon@jakubkonka.com>
2024-02-06 14:09:51
macho: move static lib emitting logic to relocatable.zig
1 parent bdbb1db
Changed files (3)
src/link/MachO/Archive.zig
@@ -143,51 +143,15 @@ pub fn parse(self: *Archive, macho_file: *MachO, path: []const u8, handle_index:
     }
 }
 
-pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
-    const gpa = comp.gpa;
-
-    var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
-    defer positionals.deinit();
-
-    try positionals.ensureUnusedCapacity(comp.objects.len);
-    positionals.appendSliceAssumeCapacity(comp.objects);
-
-    for (comp.c_object_table.keys()) |key| {
-        try positionals.append(.{ .path = key.status.success.object_path });
-    }
-
-    if (module_obj_path) |path| try positionals.append(.{ .path = path });
-
-    for (positionals.items) |obj| {
-        // TODO: parse for archive meaning don't unpack objects
-        _ = obj;
-    }
-
-    if (comp.link_errors.items.len > 0) return error.FlushFailure;
-
-    // First, we flush relocatable object file generated with our backends.
-    if (macho_file.getZigObject()) |zo| {
-        zo.resolveSymbols(macho_file);
-        zo.asFile().claimUnresolvedRelocatable(macho_file);
-    }
-
-    var err = try macho_file.addErrorWithNotes(0);
-    try err.addMsg(macho_file, "TODO implement flushStaticLib", .{});
-
-    return error.FlushFailure;
-}
-
 const fat = @import("fat.zig");
 const link = @import("../../link.zig");
 const log = std.log.scoped(.link);
 const macho = std.macho;
 const mem = std.mem;
-const relocatable = @import("relocatable.zig");
 const std = @import("std");
 
 const Allocator = mem.Allocator;
 const Archive = @This();
-const Compilation = @import("../../Compilation.zig");
 const File = @import("file.zig").File;
 const MachO = @import("../MachO.zig");
 const Object = @import("Object.zig");
src/link/MachO/relocatable.zig
@@ -1,4 +1,4 @@
-pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
+pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
     const gpa = macho_file.base.comp.gpa;
 
     var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
@@ -86,6 +86,72 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
     try writeHeader(macho_file, ncmds, sizeofcmds);
 }
 
+pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
+    const gpa = comp.gpa;
+
+    var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
+    defer positionals.deinit();
+
+    try positionals.ensureUnusedCapacity(comp.objects.len);
+    positionals.appendSliceAssumeCapacity(comp.objects);
+
+    for (comp.c_object_table.keys()) |key| {
+        try positionals.append(.{ .path = key.status.success.object_path });
+    }
+
+    if (module_obj_path) |path| try positionals.append(.{ .path = path });
+
+    for (positionals.items) |obj| {
+        // TODO: parse for archive meaning don't unpack objects
+        _ = obj;
+    }
+
+    if (comp.link_errors.items.len > 0) return error.FlushFailure;
+
+    // First, we flush relocatable object file generated with our backends.
+    if (macho_file.getZigObject()) |zo| {
+        zo.resolveSymbols(macho_file);
+        zo.asFile().claimUnresolvedRelocatable(macho_file);
+        try macho_file.sortSections();
+        try macho_file.addAtomsToSections();
+        try calcSectionSizes(macho_file);
+        try createSegment(macho_file);
+        try allocateSections(macho_file);
+        allocateSegment(macho_file);
+
+        var off = off: {
+            const seg = macho_file.segments.items[0];
+            const off = math.cast(u32, seg.fileoff + seg.filesize) orelse return error.Overflow;
+            break :off mem.alignForward(u32, off, @alignOf(macho.relocation_info));
+        };
+        off = allocateSectionsRelocs(macho_file, off);
+
+        state_log.debug("{}", .{macho_file.dumpState()});
+
+        try macho_file.calcSymtabSize();
+        try writeAtoms(macho_file);
+
+        off = mem.alignForward(u32, off, @alignOf(u64));
+        off = try macho_file.writeDataInCode(0, off);
+        off = mem.alignForward(u32, off, @alignOf(u64));
+        off = try macho_file.writeSymtab(off);
+        off = mem.alignForward(u32, off, @alignOf(u64));
+        off = try macho_file.writeStrtab(off);
+
+        // In order to please Apple ld (and possibly other MachO linkers in the wild),
+        // we will now sanitize segment names of Zig-specific segments.
+        sanitizeZigSections(macho_file);
+
+        const ncmds, const sizeofcmds = try writeLoadCommands(macho_file);
+        try writeHeader(macho_file, ncmds, sizeofcmds);
+    }
+
+    var err = try macho_file.addErrorWithNotes(0);
+    try err.addMsg(macho_file, "TODO implement flushStaticLib", .{});
+
+    return error.FlushFailure;
+}
+
 fn markExports(macho_file: *MachO) void {
     if (macho_file.getZigObject()) |zo| {
         zo.asFile().markExportsRelocatable(macho_file);
src/link/MachO.zig
@@ -417,8 +417,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
     if (comp.verbose_link) try self.dumpArgv(comp);
 
     if (self.getZigObject()) |zo| try zo.flushModule(self);
-    if (self.base.isStaticLib()) return Archive.flush(self, comp, module_obj_path);
-    if (self.base.isObject()) return relocatable.flush(self, comp, module_obj_path);
+    if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);
+    if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);
 
     var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
     defer positionals.deinit();