diff --git a/lib/std/zig/LibCDirs.zig b/lib/std/zig/LibCDirs.zig index 84002241bf9ea4fb1dbf5f8702a4723c05a01694..0c8873479420e6aca1db1e27e02f79600ee10950 100644 --- a/lib/std/zig/LibCDirs.zig +++ b/lib/std/zig/LibCDirs.zig @@ -11,15 +11,6 @@ libc_include_dir_list: []const []const u8, libc_installation: ?*const LibCInstallation, libc_framework_dir_list: []const []const u8, sysroot: ?[]const u8, -darwin_sdk_layout: ?DarwinSdkLayout, - -/// The filesystem layout of darwin SDK elements. -pub const DarwinSdkLayout = enum { - /// macOS SDK layout: TOP { /usr/include, /usr/lib, /System/Library/Frameworks }. - sdk, - /// Shipped libc layout: TOP { /lib/libc/include, /lib/libc/darwin, }. - vendored, -}; pub fn detect( arena: Allocator, @@ -37,7 +28,6 @@ pub fn detect( .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, - .darwin_sdk_layout = null, }; } @@ -102,13 +92,11 @@ pub fn detect( .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, - .darwin_sdk_layout = null, }; } fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *const LibCInstallation) !LibCDirs { var list = try std.array_list.Managed([]const u8).initCapacity(arena, 5); - var framework_list = std.array_list.Managed([]const u8).init(arena); list.appendAssumeCapacity(lci.include_dir.?); @@ -149,21 +137,15 @@ fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *con } } - var sysroot: ?[]const u8 = null; - - if (target.os.tag.isDarwin()) d: { - const down1 = std.fs.path.dirname(lci.sys_include_dir.?) orelse break :d; - const down2 = std.fs.path.dirname(down1) orelse break :d; - try framework_list.append(try std.fs.path.join(arena, &.{ down2, "System", "Library", "Frameworks" })); - sysroot = down2; - } + const frameworks: []const []const u8 = if (target.os.tag.isDarwin()) try arena.dupe([]const u8, &.{ + try std.fs.path.join(arena, &.{ lci.darwin_sdk_dir.?, "System", "Library", "Frameworks" }), + }) else &.{}; return .{ .libc_include_dir_list = list.items, .libc_installation = lci, - .libc_framework_dir_list = framework_list.items, - .sysroot = sysroot, - .darwin_sdk_layout = if (sysroot == null) null else .sdk, + .libc_framework_dir_list = frameworks, + .sysroot = if (target.os.tag.isDarwin()) lci.darwin_sdk_dir.? else null, }; } @@ -178,7 +160,6 @@ pub fn detectFromBuilding(arena: Allocator, zig_lib_dir: Path, target: *const st .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, - .darwin_sdk_layout = .vendored, }; } @@ -230,7 +211,6 @@ pub fn detectFromBuilding(arena: Allocator, zig_lib_dir: Path, target: *const st .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, - .darwin_sdk_layout = .vendored, }; } diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig index a96bbaea26e8cdabad6aba221584916ee4c7d9cf..5191bb323b5873465c17749502c6930cd336f630 100644 --- a/lib/std/zig/LibCInstallation.zig +++ b/lib/std/zig/LibCInstallation.zig @@ -23,6 +23,7 @@ crt_dir: ?[]const u8 = null, msvc_lib_dir: ?[]const u8 = null, kernel32_lib_dir: ?[]const u8 = null, cc_dir: ?[]const u8 = null, +darwin_sdk_dir: ?[]const u8 = null, pub const FindError = error{ OutOfMemory, @@ -121,19 +122,16 @@ pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const }); return error.ParseError; } + if (self.darwin_sdk_dir == null and os_tag.isDarwin()) { + log.err("darwin_sdk_dir may not be empty for {t}", .{os_tag}); + return error.ParseError; + } return self; } pub fn render(self: LibCInstallation, out: *std.Io.Writer) !void { @setEvalBranchQuota(4000); - const include_dir = self.include_dir orelse ""; - const sys_include_dir = self.sys_include_dir orelse ""; - const crt_dir = self.crt_dir orelse ""; - const msvc_lib_dir = self.msvc_lib_dir orelse ""; - const kernel32_lib_dir = self.kernel32_lib_dir orelse ""; - const cc_dir = self.cc_dir orelse ""; - try out.print( \\# The directory that contains `stdlib.h`. \\# On POSIX, can be found with: `cc -E -Wp,-v -xc /dev/null` @@ -161,13 +159,18 @@ pub fn render(self: LibCInstallation, out: *std.Io.Writer) !void { \\# Only needed when targeting MSVC on Windows. \\kernel32_lib_dir={s} \\ + \\# The directory that contains `SDKSettings.json` + \\# Only needed when targeting Darwin. + \\darwin_sdk_dir={s} + \\ , .{ - include_dir, - sys_include_dir, - crt_dir, - msvc_lib_dir, - kernel32_lib_dir, - cc_dir, + self.include_dir orelse "", + self.sys_include_dir orelse "", + self.cc_dir orelse "", + self.crt_dir orelse "", + self.msvc_lib_dir orelse "", + self.kernel32_lib_dir orelse "", + self.darwin_sdk_dir orelse "", }); } @@ -186,10 +189,10 @@ pub fn findNative(gpa: Allocator, io: Io, args: FindNativeOptions) FindError!Lib if (is_darwin and args.target.os.tag.isDarwin()) { if (!std.zig.system.darwin.isSdkInstalled(gpa, io)) return error.DarwinSdkNotFound; - const sdk = std.zig.system.darwin.getSdk(gpa, io, args.target) orelse + self.darwin_sdk_dir = std.zig.system.darwin.getSdk(gpa, io, args.target) orelse return error.DarwinSdkNotFound; - defer gpa.free(sdk); + const sdk = self.darwin_sdk_dir.?; self.include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include" }); self.sys_include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include" }); self.crt_dir = try fs.path.join(gpa, &.{ sdk, "usr/lib" }); diff --git a/src/Compilation.zig b/src/Compilation.zig index 8e2f545811a1a77237ca13560b0553cd48541b4f..1259141064c2b9c2e7513d427d9029010c63bdb9 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2208,7 +2208,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .z_relro = options.linker_z_relro, .z_common_page_size = options.linker_z_common_page_size, .z_max_page_size = options.linker_z_max_page_size, - .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, .frameworks = options.frameworks, .lib_directories = options.lib_directories, .framework_dirs = options.framework_dirs, @@ -2453,10 +2452,16 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`. comp.oneshot_prelink_tasks.appendAssumeCapacity(.load_host_libc); } else if (target.isDarwinLibC()) { - try comp.oneshot_prelink_tasks.append(gpa, .{ .load_tbd = .{ - .root_dir = comp.dirs.zig_lib, - .sub_path = "libc" ++ fs.path.sep_str ++ "darwin" ++ fs.path.sep_str ++ "libSystem.tbd", - } }); + try comp.oneshot_prelink_tasks.appendSlice(gpa, &.{ + .{ .load_tbd = .{ + .root_dir = comp.dirs.zig_lib, + .sub_path = "libc" ++ fs.path.sep_str ++ "darwin" ++ fs.path.sep_str ++ "libSystem.tbd", + } }, + .{ .load_darwin_sdk_settings = .{ + .root_dir = comp.dirs.zig_lib, + .sub_path = "libc" ++ fs.path.sep_str ++ "darwin" ++ fs.path.sep_str ++ "SDKSettings.json", + } }, + }); // TODO delete logic from MachO flush() and queue up tasks here instead. } else if (target.isMuslLibC()) { if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable); @@ -3487,7 +3492,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(opts.discard_local_symbols); man.hash.addOptional(opts.compatibility_version); man.hash.addOptionalBytes(opts.install_name); - man.hash.addOptional(opts.darwin_sdk_layout); // COFF specific stuff man.hash.addOptional(opts.subsystem); diff --git a/src/link.zig b/src/link.zig index 247ca5d4b9250e2dd94408d34d2e12786483376a..34b020b677cce80c7f541c158276a507d031331e 100644 --- a/src/link.zig +++ b/src/link.zig @@ -502,7 +502,6 @@ pub const File = struct { /// Remove dylibs that are unreachable by the entry point or exported symbols dead_strip_dylibs: bool, frameworks: []const MachO.Framework, - darwin_sdk_layout: ?MachO.SdkLayout, /// Force load all members of static archives that implement an /// Objective-C class or category force_load_objc: bool, @@ -1248,6 +1247,59 @@ pub const File = struct { } } + fn loadDarwinSdkSettings(base: *File, sdk_settings_path: Path) Error!void { + const comp = base.comp; + const io = comp.io; + const arena = comp.arena; + const diags = &comp.link_diags; + + const contents = sdk_settings_path.root_dir.handle.readFileAlloc( + io, + sdk_settings_path.sub_path, + arena, + .limited(1024 * 1024 * 256), + ) catch |err| switch (err) { + error.OutOfMemory, error.Canceled => |e| return e, + else => |e| return diags.failParse(sdk_settings_path, "failed to parse Darwin SDK settings: {t}", .{e}), + }; + + const parsed = std.json.parseFromSlice(std.json.Value, arena, contents, .{}) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => |e| return diags.failParse(sdk_settings_path, "failed to parse Darwin SDK settings: {t}", .{e}), + }; + const parsed_object = switch (parsed.value) { + .object => |obj| obj, + else => return diags.failParse(sdk_settings_path, "failed to parse Darwin SDK settings: file is not a JSON object", .{}), + }; + + const version_json = parsed_object.get("MinimalDisplayName") orelse return diags.failParse( + sdk_settings_path, + "failed to parse Darwin SDK settings: 'MinimalDisplayName' missing", + .{}, + ); + const version_str: []const u8 = switch (version_json) { + .string => |str| str, + else => return diags.failParse( + sdk_settings_path, + "failed to parse Darwin SDK settings: 'MinimalDisplayName' not a string", + .{}, + ), + }; + const version: DarwinSdkVersion = try .parse(diags, sdk_settings_path, version_str); + try base.setDarwinSdkVersion(version); + } + + fn setDarwinSdkVersion(base: *File, version: DarwinSdkVersion) Error!void { + assert(!base.post_prelink); + switch (base.tag) { + inline .macho, .macho2 => |tag| { + dev.check(tag.devFeature()); + return @as(*tag.Type(), @fieldParentPtr("base", base)).setDarwinSdkVersion(version); + }, + else => unreachable, + } + } + /// Called when all linker inputs have been sent via `loadInput`. After /// this, `loadInput` will not be called anymore. pub fn prelink(base: *File) Error!void { @@ -1451,6 +1503,7 @@ pub const PrelinkTask = union(enum) { /// GNU ld script. load_dso: Path, load_tbd: Path, + load_darwin_sdk_settings: Path, }; pub const ZcuTask = union(enum) { /// Sent once per update, as the very first `ZcuTask` in the update. Indicates that all per-file @@ -1589,7 +1642,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { error.FileNotFound => {}, error.AlreadyReported => return, error.Canceled => io.recancel(), - else => |e| diags.addParseError(archive_path, "failed to parse archive {f}: {s}", .{ archive_path, @errorName(e) }), + else => |e| diags.addParseError(archive_path, "failed to parse archive: {s}", .{@errorName(e)}), } diags.addError("failed to find library '{s}'", .{lib_name}); @@ -1612,6 +1665,19 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { } } + if (target.os.tag.isDarwin()) { + const sdk_settings_path: Path = .initCwd(std.fmt.allocPrint( + comp.arena, + "{s}" ++ sep ++ "SDKSettings.json", + .{libc_installation.darwin_sdk_dir.?}, + ) catch return diags.setAllocFailure()); + base.loadDarwinSdkSettings(sdk_settings_path) catch |err| switch (err) { + error.OutOfMemory => return diags.setAllocFailure(), + error.Canceled => return io.recancel(), + error.AlreadyReported => return, + }; + } + if (target.os.tag == .windows and target.abi == .msvc) { const inputs: []const struct { dir: enum { crt, msvc_lib, kernel32_lib }, @@ -1709,6 +1775,15 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { else => |e| diags.addParseError(path, "failed to parse tbd: {t}", .{e}), } }, + .load_darwin_sdk_settings => |path| { + const prog_node = comp.link_prog_node.start("Parse SDK Settings", 0); + defer prog_node.end(); + base.loadDarwinSdkSettings(path) catch |err| switch (err) { + error.OutOfMemory => return diags.setAllocFailure(), + error.Canceled => return io.recancel(), + error.AlreadyReported => return, + }; + }, } } pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void { @@ -2793,3 +2868,76 @@ pub fn firstObjectInput(inputs: []const Input) ?Input.Object { }; return null; } + +pub const DarwinSdkVersion = packed struct(u32) { + patch: u8, + minor: u8, + major: u16, + + fn parse( + diags: *Diags, + /// Passed to `Diags.failParse` on error. + sdk_settings_path: Path, + version_str: []const u8, + ) error{AlreadyReported}!DarwinSdkVersion { + var it = std.mem.splitScalar(u8, version_str, '.'); + + const major = try parseComponent( + .major, + diags, + sdk_settings_path, + version_str, + it.first(), + ); + const minor = if (it.next()) |component_str| try parseComponent( + .minor, + diags, + sdk_settings_path, + version_str, + component_str, + ) else return diags.failParse( + sdk_settings_path, + "failed to parse Darwin SDK version {q}: missing minor version", + .{version_str}, + ); + const patch = if (it.next()) |component_str| try parseComponent( + .patch, + diags, + sdk_settings_path, + version_str, + component_str, + ) else 0; // Apple sometimes omit the patch version + + if (it.next() != null) return diags.failParse( + sdk_settings_path, + "failed to parse Darwin SDK version {q}: too many version components", + .{version_str}, + ); + + return .{ .major = major, .minor = minor, .patch = patch }; + } + + fn parseComponent( + comptime component: enum { major, minor, patch }, + diags: *Diags, + /// Passed to `Diags.failParse` on error. + sdk_settings_path: Path, + /// Only used for error messages. + version_str: []const u8, + component_str: []const u8, + ) error{AlreadyReported}!@FieldType(DarwinSdkVersion, @tagName(component)) { + const Int = @FieldType(DarwinSdkVersion, @tagName(component)); + return std.fmt.parseInt(Int, component_str, 10) catch |err| switch (err) { + error.Overflow => return diags.failParse( + sdk_settings_path, + "failed to parse Darwin SDK version {q}: {t} version {q} too large", + .{ version_str, component, component_str }, + ), + error.InvalidCharacter => return diags.failParse( + sdk_settings_path, + "failed to parse Darwin SDK version {q}: invalid {t} version {q}", + .{ version_str, component, component_str }, + ), + }; + } +}; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index db7d1733859235990e5cc60fcd840b5fa8cd30dc..03c350c210f3410994028f77a0cf97ae0ef30ae1 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -106,9 +106,7 @@ has_tlv: AtomicBool = AtomicBool.init(false), binds_to_weak: AtomicBool = AtomicBool.init(false), weak_defines: AtomicBool = AtomicBool.init(false), -/// Options -/// SDK layout -sdk_layout: ?SdkLayout, +// Options /// Size of the __PAGEZERO segment. pagezero_size: ?u64, /// Minimum space for future expansion of the load commands. @@ -134,7 +132,7 @@ compatibility_version: ?std.SemanticVersion, /// Entry name entry_name: ?[]const u8, platform: Platform, -sdk_version: ?std.SemanticVersion, +sdk_version: ?link.DarwinSdkVersion, /// When set to true, the linker will hoist all dylibs including system dependent dylibs. no_implicit_dylibs: bool = false, /// Whether the linker should parse and always force load objects containing ObjC in archives. @@ -198,7 +196,6 @@ pub fn createEmpty( .headerpad_size = options.headerpad_size, .headerpad_max_install_names = options.headerpad_max_install_names, .dead_strip_dylibs = options.dead_strip_dylibs, - .sdk_layout = options.darwin_sdk_layout, .frameworks = options.frameworks, .install_name = options.install_name, .entitlements = options.entitlements, @@ -210,7 +207,7 @@ pub fn createEmpty( .named => |name| name, }, .platform = Platform.fromTarget(target), - .sdk_version = if (options.darwin_sdk_layout) |layout| inferSdkVersion(comp, layout) else null, + .sdk_version = null, .undefined_treatment = if (allow_shlib_undefined) .dynamic_lookup else .@"error", // TODO delete this, directories must instead be resolved by the frontend .lib_directories = options.lib_directories, @@ -604,12 +601,20 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { try argv.append("-platform_version"); try argv.append(@tagName(self.platform.os_tag)); - try argv.append(try std.fmt.allocPrint(arena, "{f}", .{self.platform.version})); + try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}.{d}", .{ + self.platform.version.major, + self.platform.version.minor, + self.platform.version.patch, + })); if (self.sdk_version) |ver| { try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor })); } else { - try argv.append(try std.fmt.allocPrint(arena, "{f}", .{self.platform.version})); + try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}.{d}", .{ + self.platform.version.major, + self.platform.version.minor, + self.platform.version.patch, + })); } if (comp.sysroot) |syslibroot| { @@ -4101,7 +4106,7 @@ pub const null_sym = macho.nlist_64{ pub const Platform = struct { os_tag: std.Target.Os.Tag, abi: std.Target.Abi, - version: std.SemanticVersion, + version: link.DarwinSdkVersion, /// Using Apple's ld64 as our blueprint, `min_version` as well as `sdk_version` are set to /// the extracted minimum platform version. @@ -4128,7 +4133,7 @@ pub const Platform = struct { => .simulator, else => .none, }, - .version = appleVersionToSemanticVersion(cmd.minos), + .version = @fromBackingInt(cmd.minos), }; }, .VERSION_MIN_IPHONEOS, @@ -4147,7 +4152,7 @@ pub const Platform = struct { else => unreachable, }, .abi = .none, - .version = appleVersionToSemanticVersion(cmd.version), + .version = @fromBackingInt(cmd.version), }; }, else => unreachable, @@ -4155,17 +4160,18 @@ pub const Platform = struct { } pub fn fromTarget(target: *const std.Target) Platform { + const semver = target.os.version_range.semver.min; return .{ .os_tag = target.os.tag, .abi = target.abi, - .version = target.os.version_range.semver.min, + .version = .{ + .major = @intCast(semver.major), + .minor = @intCast(semver.minor), + .patch = @intCast(semver.patch), + }, }; } - pub fn toAppleVersion(plat: Platform) u32 { - return semanticVersionToAppleVersion(plat.version); - } - pub fn toApplePlatform(plat: Platform) macho.PLATFORM { return switch (plat.os_tag) { .driverkit => .DRIVERKIT, @@ -4182,7 +4188,7 @@ pub const Platform = struct { pub fn isBuildVersionCompatible(plat: Platform) bool { inline for (supported_platforms) |sup_plat| { if (sup_plat[0] == plat.os_tag and sup_plat[1] == plat.abi) { - return sup_plat[2] <= plat.toAppleVersion(); + return sup_plat[2] <= @backingInt(plat.version); } } return false; @@ -4191,7 +4197,7 @@ pub const Platform = struct { pub fn isVersionMinCompatible(plat: Platform) bool { inline for (supported_platforms) |sup_plat| { if (sup_plat[0] == plat.os_tag and sup_plat[1] == plat.abi) { - return sup_plat[3] <= plat.toAppleVersion(); + return sup_plat[3] <= @backingInt(plat.version); } } return false; @@ -4250,86 +4256,8 @@ const supported_platforms = [_]SupportedPlatforms{ }; // zig fmt: on -pub inline fn semanticVersionToAppleVersion(version: std.SemanticVersion) u32 { - const major = version.major; - const minor = version.minor; - const patch = version.patch; - return (@as(u32, @intCast(major)) << 16) | (@as(u32, @intCast(minor)) << 8) | @as(u32, @intCast(patch)); -} - -pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion { - return .{ - .major = @as(u16, @truncate(version >> 16)), - .minor = @as(u8, @truncate(version >> 8)), - .patch = @as(u8, @truncate(version)), - }; -} - -fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersion { - const gpa = comp.gpa; - - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - const io = comp.io; - - const sdk_dir = switch (sdk_layout) { - .sdk => comp.sysroot.?, - .vendored => fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "libc", "darwin" }) catch return null, - }; - if (readSdkVersionFromSettings(arena, io, sdk_dir)) |ver| { - return parseSdkVersion(ver); - } else |_| { - // Read from settings should always succeed when vendored. - // TODO: convert to fatal linker error - if (sdk_layout == .vendored) @panic("zig installation bug: unable to parse SDK version"); - } - - // infer from pathname - const stem = fs.path.stem(sdk_dir); - const start = for (stem, 0..) |c, i| { - if (std.ascii.isDigit(c)) break i; - } else stem.len; - const end = for (stem[start..], start..) |c, i| { - if (std.ascii.isDigit(c) or c == '.') continue; - break i; - } else stem.len; - return parseSdkVersion(stem[start..end]); -} - -// Official Apple SDKs ship with a `SDKSettings.json` located at the top of SDK fs layout. -// Use property `MinimalDisplayName` to determine version. -// The file/property is also available with vendored libc. -fn readSdkVersionFromSettings(arena: Allocator, io: Io, dir: []const u8) ![]const u8 { - const sdk_path = try fs.path.join(arena, &.{ dir, "SDKSettings.json" }); - const contents = try Io.Dir.cwd().readFileAlloc(io, sdk_path, arena, .limited(std.math.maxInt(u16))); - const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{}); - if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string; - return error.SdkVersionFailure; -} - -// Versions reported by Apple aren't exactly semantically valid as they usually omit -// the patch component, so we parse SDK value by hand. -fn parseSdkVersion(raw: []const u8) ?std.SemanticVersion { - var parsed: std.SemanticVersion = .{ - .major = 0, - .minor = 0, - .patch = 0, - }; - - const parseNext = struct { - fn parseNext(it: anytype) ?u16 { - const nn = it.next() orelse return null; - return std.fmt.parseInt(u16, nn, 10) catch null; - } - }.parseNext; - - var it = std.mem.splitAny(u8, raw, "."); - parsed.major = parseNext(&it) orelse return null; - parsed.minor = parseNext(&it) orelse return null; - parsed.patch = parseNext(&it) orelse 0; - return parsed; +pub fn setDarwinSdkVersion(self: *MachO, version: link.DarwinSdkVersion) link.Error!void { + self.sdk_version = version; } /// When allocating, the ideal_capacity is calculated by @@ -4377,8 +4305,6 @@ const SystemLib = struct { } }; -pub const SdkLayout = std.zig.LibCDirs.DarwinSdkLayout; - const UndefinedTreatment = enum { @"error", warn, diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 62bbc751cb58e82aee019f07065eabf1b8cf8917..f6b97406849f031a235a51f31c64cb8e3b65b545 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -9,6 +9,7 @@ const Allocator = std.mem.Allocator; const DebugSymbols = @import("DebugSymbols.zig"); const Dylib = @import("Dylib.zig"); const MachO = @import("../MachO.zig"); +const link = @import("../../link.zig"); pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld"; @@ -296,7 +297,7 @@ pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { } } -pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { +pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?link.DarwinSdkVersion, writer: *Writer) !void { const cmd: macho.LC = switch (platform.os_tag) { .macos => .VERSION_MIN_MACOSX, .ios, .maccatalyst => .VERSION_MIN_IPHONEOS, @@ -306,24 +307,18 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer }; try writer.writeAll(mem.asBytes(&macho.version_min_command{ .cmd = cmd, - .version = platform.toAppleVersion(), - .sdk = if (sdk_version) |ver| - MachO.semanticVersionToAppleVersion(ver) - else - platform.toAppleVersion(), + .version = @backingInt(platform.version), + .sdk = @backingInt(sdk_version orelse platform.version), })); } -pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { +pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?link.DarwinSdkVersion, writer: *Writer) !void { const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version); try writer.writeStruct(@as(macho.build_version_command, .{ .cmdsize = cmdsize, .platform = platform.toApplePlatform(), - .minos = platform.toAppleVersion(), - .sdk = if (sdk_version) |ver| - MachO.semanticVersionToAppleVersion(ver) - else - platform.toAppleVersion(), + .minos = @backingInt(platform.version), + .sdk = @backingInt(sdk_version orelse platform.version), .ntools = 1, }), .little); try writer.writeAll(mem.asBytes(&macho.build_tool_version{ diff --git a/src/link/MachO2.zig b/src/link/MachO2.zig index c01ed3cf0b62d1a22555792236c32ffea0fb098d..47e97ba57d1ef1313bcfa48bb244b7d8730e8536 100644 --- a/src/link/MachO2.zig +++ b/src/link/MachO2.zig @@ -138,6 +138,10 @@ pub fn loadInput(macho: *MachO, input: link.Input) link.Error!void { _ = input; @panic("TODO"); } +pub fn setDarwinSdkVersion(macho: *MachO, version: link.DarwinSdkVersion) link.Error!void { + _ = macho; + std.log.err("MLUGG TODO: sdk version is '{d}.{d}.{d}'", .{ version.major, version.minor, version.patch }); +} pub fn prelink(macho: *MachO, prog_node: std.Progress.Node) link.Error!void { _ = macho; _ = prog_node;