Commit 7007684984

Jakub Konka <kubkon@jakubkonka.com>
2021-08-05 16:57:59
macho: swap out VERSION_MIN for BUILD_VERSION
this makes the app successfully run on the iOS simluator!
1 parent ace9b3d
Changed files (4)
lib/std/macho.zig
@@ -116,6 +116,21 @@ pub const build_tool_version = extern struct {
     version: u32,
 };
 
+pub const PLATFORM_MACOS: u32 = 0x1;
+pub const PLATFORM_IOS: u32 = 0x2;
+pub const PLATFORM_TVOS: u32 = 0x3;
+pub const PLATFORM_WATCHOS: u32 = 0x4;
+pub const PLATFORM_BRIDGEOS: u32 = 0x5;
+pub const PLATFORM_MACCATALYST: u32 = 0x6;
+pub const PLATFORM_IOSSIMULATOR: u32 = 0x7;
+pub const PLATFORM_TVOSSIMULATOR: u32 = 0x8;
+pub const PLATFORM_WATCHOSSIMULATOR: u32 = 0x9;
+pub const PLATFORM_DRIVERKIT: u32 = 0x10;
+
+pub const TOOL_CLANG: u32 = 0x1;
+pub const TOOL_SWIFT: u32 = 0x2;
+pub const TOOL_LD: u32 = 0x3;
+
 /// The entry_point_command is a replacement for thread_command.
 /// It is used for main executables to specify the location (file offset)
 /// of main(). If -stack_size was used at link time, the stacksize
src/link/MachO/commands.zig
@@ -43,6 +43,7 @@ pub const LoadCommand = union(enum) {
     Main: macho.entry_point_command,
     VersionMin: macho.version_min_command,
     SourceVersion: macho.source_version_command,
+    BuildVersion: GenericCommandWithData(macho.build_version_command),
     Uuid: macho.uuid_command,
     LinkeditData: macho.linkedit_data_command,
     Rpath: GenericCommandWithData(macho.rpath_command),
@@ -97,6 +98,9 @@ pub const LoadCommand = union(enum) {
             macho.LC_SOURCE_VERSION => LoadCommand{
                 .SourceVersion = try stream.reader().readStruct(macho.source_version_command),
             },
+            macho.LC_BUILD_VERSION => LoadCommand{
+                .BuildVersion = try GenericCommandWithData(macho.build_version_command).read(allocator, stream.reader()),
+            },
             macho.LC_UUID => LoadCommand{
                 .Uuid = try stream.reader().readStruct(macho.uuid_command),
             },
@@ -129,6 +133,7 @@ pub const LoadCommand = union(enum) {
             .Dylinker => |x| x.write(writer),
             .Dylib => |x| x.write(writer),
             .Rpath => |x| x.write(writer),
+            .BuildVersion => |x| x.write(writer),
             .Unknown => |x| x.write(writer),
         };
     }
@@ -147,6 +152,7 @@ pub const LoadCommand = union(enum) {
             .Dylinker => |x| x.inner.cmd,
             .Dylib => |x| x.inner.cmd,
             .Rpath => |x| x.inner.cmd,
+            .BuildVersion => |x| x.inner.cmd,
             .Unknown => |x| x.inner.cmd,
         };
     }
@@ -165,6 +171,7 @@ pub const LoadCommand = union(enum) {
             .Dylinker => |x| x.inner.cmdsize,
             .Dylib => |x| x.inner.cmdsize,
             .Rpath => |x| x.inner.cmdsize,
+            .BuildVersion => |x| x.inner.cmdsize,
             .Unknown => |x| x.inner.cmdsize,
         };
     }
@@ -193,6 +200,7 @@ pub const LoadCommand = union(enum) {
             .Main => |x| meta.eql(x, other.Main),
             .VersionMin => |x| meta.eql(x, other.VersionMin),
             .SourceVersion => |x| meta.eql(x, other.SourceVersion),
+            .BuildVersion => |x| x.eql(other.BuildVersion),
             .Uuid => |x| meta.eql(x, other.Uuid),
             .LinkeditData => |x| meta.eql(x, other.LinkeditData),
             .Segment => |x| x.eql(other.Segment),
src/link/MachO/Dylib.zig
@@ -340,6 +340,9 @@ fn targetToAppleString(allocator: *Allocator, target: std.Target) ![]const u8 {
         .x86_64 => "x86_64",
         else => unreachable,
     };
+    if (target.os.tag == .ios) {
+        return std.fmt.allocPrint(allocator, "{s}-{s}-simulator", .{ arch, @tagName(target.os.tag) });
+    }
     return std.fmt.allocPrint(allocator, "{s}-{s}", .{ arch, @tagName(target.os.tag) });
 }
 
src/link/MachO.zig
@@ -82,8 +82,8 @@ data_in_code_cmd_index: ?u16 = null,
 function_starts_cmd_index: ?u16 = null,
 main_cmd_index: ?u16 = null,
 dylib_id_cmd_index: ?u16 = null,
-version_min_cmd_index: ?u16 = null,
 source_version_cmd_index: ?u16 = null,
+build_version_cmd_index: ?u16 = null,
 uuid_cmd_index: ?u16 = null,
 code_signature_cmd_index: ?u16 = null,
 /// Path to libSystem
@@ -2716,27 +2716,6 @@ fn populateMetadata(self: *MachO) !void {
         try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
     }
 
-    if (self.version_min_cmd_index == null) {
-        self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len);
-        const cmd: u32 = switch (self.base.options.target.os.tag) {
-            .macos => macho.LC_VERSION_MIN_MACOSX,
-            .ios => macho.LC_VERSION_MIN_IPHONEOS,
-            .tvos => macho.LC_VERSION_MIN_TVOS,
-            .watchos => macho.LC_VERSION_MIN_WATCHOS,
-            else => unreachable, // wrong OS
-        };
-        const ver = self.base.options.target.os.version_range.semver.min;
-        const version = ver.major << 16 | ver.minor << 8 | ver.patch;
-        try self.load_commands.append(self.base.allocator, .{
-            .VersionMin = .{
-                .cmd = cmd,
-                .cmdsize = @sizeOf(macho.version_min_command),
-                .version = version,
-                .sdk = version,
-            },
-        });
-    }
-
     if (self.source_version_cmd_index == null) {
         self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
         try self.load_commands.append(self.base.allocator, .{
@@ -2748,6 +2727,39 @@ fn populateMetadata(self: *MachO) !void {
         });
     }
 
+    if (self.build_version_cmd_index == null) {
+        self.build_version_cmd_index = @intCast(u16, self.load_commands.items.len);
+        const cmdsize = @intCast(u32, mem.alignForwardGeneric(
+            u64,
+            @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version),
+            @sizeOf(u64),
+        ));
+        const ver = self.base.options.target.os.version_range.semver.min;
+        const version = ver.major << 16 | ver.minor << 8 | ver.patch;
+        var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{
+            .cmd = macho.LC_BUILD_VERSION,
+            .cmdsize = cmdsize,
+            .platform = switch (self.base.options.target.os.tag) {
+                .macos => macho.PLATFORM_MACOS,
+                .ios => macho.PLATFORM_IOSSIMULATOR,
+                .watchos => macho.PLATFORM_WATCHOS,
+                .tvos => macho.PLATFORM_TVOS,
+                else => unreachable,
+            },
+            .minos = version,
+            .sdk = version,
+            .ntools = 1,
+        });
+        const ld_ver = macho.build_tool_version{
+            .tool = macho.TOOL_LD,
+            .version = 0x0,
+        };
+        cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command));
+        mem.set(u8, cmd.data, 0);
+        mem.copy(u8, cmd.data, mem.asBytes(&ld_ver));
+        try self.load_commands.append(self.base.allocator, .{ .BuildVersion = cmd });
+    }
+
     if (self.uuid_cmd_index == null) {
         self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);
         var uuid_cmd: macho.uuid_command = .{
@@ -4334,26 +4346,37 @@ pub fn populateMissingMetadata(self: *MachO) !void {
         });
         self.load_commands_dirty = true;
     }
-    if (self.version_min_cmd_index == null) {
-        self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len);
-        const cmd: u32 = switch (self.base.options.target.os.tag) {
-            .macos => macho.LC_VERSION_MIN_MACOSX,
-            .ios => macho.LC_VERSION_MIN_IPHONEOS,
-            .tvos => macho.LC_VERSION_MIN_TVOS,
-            .watchos => macho.LC_VERSION_MIN_WATCHOS,
-            else => unreachable, // wrong OS
-        };
+    if (self.build_version_cmd_index == null) {
+        self.build_version_cmd_index = @intCast(u16, self.load_commands.items.len);
+        const cmdsize = @intCast(u32, mem.alignForwardGeneric(
+            u64,
+            @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version),
+            @sizeOf(u64),
+        ));
         const ver = self.base.options.target.os.version_range.semver.min;
         const version = ver.major << 16 | ver.minor << 8 | ver.patch;
-        try self.load_commands.append(self.base.allocator, .{
-            .VersionMin = .{
-                .cmd = cmd,
-                .cmdsize = @sizeOf(macho.version_min_command),
-                .version = version,
-                .sdk = version,
+        var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{
+            .cmd = macho.LC_BUILD_VERSION,
+            .cmdsize = cmdsize,
+            .platform = switch (self.base.options.target.os.tag) {
+                .macos => macho.PLATFORM_MACOS,
+                .ios => macho.PLATFORM_IOSSIMULATOR,
+                .watchos => macho.PLATFORM_WATCHOS,
+                .tvos => macho.PLATFORM_TVOS,
+                else => unreachable,
             },
+            .minos = version,
+            .sdk = version,
+            .ntools = 1,
         });
-        self.load_commands_dirty = true;
+        const ld_ver = macho.build_tool_version{
+            .tool = macho.TOOL_LD,
+            .version = 0x0,
+        };
+        cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command));
+        mem.set(u8, cmd.data, 0);
+        mem.copy(u8, cmd.data, mem.asBytes(&ld_ver));
+        try self.load_commands.append(self.base.allocator, .{ .BuildVersion = cmd });
     }
     if (self.source_version_cmd_index == null) {
         self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);