macho: swap out VERSION_MIN for BUILD_VERSION

this makes the app successfully run on the iOS simluator!
This commit is contained in:
Jakub Konka 2021-08-05 16:57:59 +02:00
parent ace9b3de64
commit 7007684984
4 changed files with 87 additions and 38 deletions

View File

@ -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

View File

@ -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);

View File

@ -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) });
}

View File

@ -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),