| author | |
| committer | |
| log | 2a5e70202b11982bde5cadb287cdb1abdcd1a49b |
| tree | 05d118f122fa8640bdff073f1a95a0a68b4a6e4e |
| parent | c1ce1a2da70b1f3667df16212ace4c227aeaced1 |
| signature | Commit is signed but in an unrecognized format. |
The SDK version is determined by parsing the `SDKSettings.json` file in
the Darwin SDK (or in `lib/libc/darwin/` when using our vendored libs).
(The old Mach-O linker also had a fallback strategy of determining the
version from the SDK path, but that seems unnecessary nowadays.)
Moving that parsing to `src/link.zig`, and calling into it at the same
time as handling libc (libSystem), turns out to simplify this logic
quite a bit!7 files changed, 220 insertions(+), 160 deletions(-)
lib/std/zig/LibCDirs.zig+5-25| ... | @@ -11,15 +11,6 @@ libc_include_dir_list: []const []const u8, | ... | @@ -11,15 +11,6 @@ libc_include_dir_list: []const []const u8, |
| 11 | libc_installation: ?*const LibCInstallation, | 11 | libc_installation: ?*const LibCInstallation, |
| 12 | libc_framework_dir_list: []const []const u8, | 12 | libc_framework_dir_list: []const []const u8, |
| 13 | sysroot: ?[]const u8, | 13 | sysroot: ?[]const u8, |
| 14 | darwin_sdk_layout: ?DarwinSdkLayout, | ||
| 15 | |||
| 16 | /// The filesystem layout of darwin SDK elements. | ||
| 17 | pub const DarwinSdkLayout = enum { | ||
| 18 | /// macOS SDK layout: TOP { /usr/include, /usr/lib, /System/Library/Frameworks }. | ||
| 19 | sdk, | ||
| 20 | /// Shipped libc layout: TOP { /lib/libc/include, /lib/libc/darwin, <NONE> }. | ||
| 21 | vendored, | ||
| 22 | }; | ||
| 23 | 14 | ||
| 24 | pub fn detect( | 15 | pub fn detect( |
| 25 | arena: Allocator, | 16 | arena: Allocator, |
| ... | @@ -37,7 +28,6 @@ pub fn detect( | ... | @@ -37,7 +28,6 @@ pub fn detect( |
| 37 | .libc_installation = null, | 28 | .libc_installation = null, |
| 38 | .libc_framework_dir_list = &.{}, | 29 | .libc_framework_dir_list = &.{}, |
| 39 | .sysroot = null, | 30 | .sysroot = null, |
| 40 | .darwin_sdk_layout = null, | ||
| 41 | }; | 31 | }; |
| 42 | } | 32 | } |
| 43 | 33 | ||
| ... | @@ -102,13 +92,11 @@ pub fn detect( | ... | @@ -102,13 +92,11 @@ pub fn detect( |
| 102 | .libc_installation = null, | 92 | .libc_installation = null, |
| 103 | .libc_framework_dir_list = &.{}, | 93 | .libc_framework_dir_list = &.{}, |
| 104 | .sysroot = null, | 94 | .sysroot = null, |
| 105 | .darwin_sdk_layout = null, | ||
| 106 | }; | 95 | }; |
| 107 | } | 96 | } |
| 108 | 97 | ||
| 109 | fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *const LibCInstallation) !LibCDirs { | 98 | fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *const LibCInstallation) !LibCDirs { |
| 110 | var list = try std.array_list.Managed([]const u8).initCapacity(arena, 5); | 99 | var list = try std.array_list.Managed([]const u8).initCapacity(arena, 5); |
| 111 | var framework_list = std.array_list.Managed([]const u8).init(arena); | ||
| 112 | 100 | ||
| 113 | list.appendAssumeCapacity(lci.include_dir.?); | 101 | list.appendAssumeCapacity(lci.include_dir.?); |
| 114 | 102 | ||
| ... | @@ -149,21 +137,15 @@ fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *con | ... | @@ -149,21 +137,15 @@ fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *con |
| 149 | } | 137 | } |
| 150 | } | 138 | } |
| 151 | 139 | ||
| 152 | var sysroot: ?[]const u8 = null; | 140 | const frameworks: []const []const u8 = if (target.os.tag.isDarwin()) try arena.dupe([]const u8, &.{ |
| 153 | 141 | try std.fs.path.join(arena, &.{ lci.darwin_sdk_dir.?, "System", "Library", "Frameworks" }), | |
| 154 | if (target.os.tag.isDarwin()) d: { | 142 | }) else &.{}; |
| 155 | const down1 = std.fs.path.dirname(lci.sys_include_dir.?) orelse break :d; | ||
| 156 | const down2 = std.fs.path.dirname(down1) orelse break :d; | ||
| 157 | try framework_list.append(try std.fs.path.join(arena, &.{ down2, "System", "Library", "Frameworks" })); | ||
| 158 | sysroot = down2; | ||
| 159 | } | ||
| 160 | 143 | ||
| 161 | return .{ | 144 | return .{ |
| 162 | .libc_include_dir_list = list.items, | 145 | .libc_include_dir_list = list.items, |
| 163 | .libc_installation = lci, | 146 | .libc_installation = lci, |
| 164 | .libc_framework_dir_list = framework_list.items, | 147 | .libc_framework_dir_list = frameworks, |
| 165 | .sysroot = sysroot, | 148 | .sysroot = if (target.os.tag.isDarwin()) lci.darwin_sdk_dir.? else null, |
| 166 | .darwin_sdk_layout = if (sysroot == null) null else .sdk, | ||
| 167 | }; | 149 | }; |
| 168 | } | 150 | } |
| 169 | 151 | ||
| ... | @@ -178,7 +160,6 @@ pub fn detectFromBuilding(arena: Allocator, zig_lib_dir: Path, target: *const st | ... | @@ -178,7 +160,6 @@ pub fn detectFromBuilding(arena: Allocator, zig_lib_dir: Path, target: *const st |
| 178 | .libc_installation = null, | 160 | .libc_installation = null, |
| 179 | .libc_framework_dir_list = &.{}, | 161 | .libc_framework_dir_list = &.{}, |
| 180 | .sysroot = null, | 162 | .sysroot = null, |
| 181 | .darwin_sdk_layout = .vendored, | ||
| 182 | }; | 163 | }; |
| 183 | } | 164 | } |
| 184 | 165 | ||
| ... | @@ -230,7 +211,6 @@ pub fn detectFromBuilding(arena: Allocator, zig_lib_dir: Path, target: *const st | ... | @@ -230,7 +211,6 @@ pub fn detectFromBuilding(arena: Allocator, zig_lib_dir: Path, target: *const st |
| 230 | .libc_installation = null, | 211 | .libc_installation = null, |
| 231 | .libc_framework_dir_list = &.{}, | 212 | .libc_framework_dir_list = &.{}, |
| 232 | .sysroot = null, | 213 | .sysroot = null, |
| 233 | .darwin_sdk_layout = .vendored, | ||
| 234 | }; | 214 | }; |
| 235 | } | 215 | } |
| 236 | 216 |
lib/std/zig/LibCInstallation.zig+18-15| ... | @@ -23,6 +23,7 @@ crt_dir: ?[]const u8 = null, | ... | @@ -23,6 +23,7 @@ crt_dir: ?[]const u8 = null, |
| 23 | msvc_lib_dir: ?[]const u8 = null, | 23 | msvc_lib_dir: ?[]const u8 = null, |
| 24 | kernel32_lib_dir: ?[]const u8 = null, | 24 | kernel32_lib_dir: ?[]const u8 = null, |
| 25 | cc_dir: ?[]const u8 = null, | 25 | cc_dir: ?[]const u8 = null, |
| 26 | darwin_sdk_dir: ?[]const u8 = null, | ||
| 26 | 27 | ||
| 27 | pub const FindError = error{ | 28 | pub const FindError = error{ |
| 28 | OutOfMemory, | 29 | OutOfMemory, |
| ... | @@ -121,19 +122,16 @@ pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const | ... | @@ -121,19 +122,16 @@ pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const |
| 121 | }); | 122 | }); |
| 122 | return error.ParseError; | 123 | return error.ParseError; |
| 123 | } | 124 | } |
| 125 | if (self.darwin_sdk_dir == null and os_tag.isDarwin()) { | ||
| 126 | log.err("darwin_sdk_dir may not be empty for {t}", .{os_tag}); | ||
| 127 | return error.ParseError; | ||
| 128 | } | ||
| 124 | 129 | ||
| 125 | return self; | 130 | return self; |
| 126 | } | 131 | } |
| 127 | 132 | ||
| 128 | pub fn render(self: LibCInstallation, out: *std.Io.Writer) !void { | 133 | pub fn render(self: LibCInstallation, out: *std.Io.Writer) !void { |
| 129 | @setEvalBranchQuota(4000); | 134 | @setEvalBranchQuota(4000); |
| 130 | const include_dir = self.include_dir orelse ""; | ||
| 131 | const sys_include_dir = self.sys_include_dir orelse ""; | ||
| 132 | const crt_dir = self.crt_dir orelse ""; | ||
| 133 | const msvc_lib_dir = self.msvc_lib_dir orelse ""; | ||
| 134 | const kernel32_lib_dir = self.kernel32_lib_dir orelse ""; | ||
| 135 | const cc_dir = self.cc_dir orelse ""; | ||
| 136 | |||
| 137 | try out.print( | 135 | try out.print( |
| 138 | \\# The directory that contains `stdlib.h`. | 136 | \\# The directory that contains `stdlib.h`. |
| 139 | \\# On POSIX, can be found with: `cc -E -Wp,-v -xc /dev/null` | 137 | \\# 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 { | ... | @@ -161,13 +159,18 @@ pub fn render(self: LibCInstallation, out: *std.Io.Writer) !void { |
| 161 | \\# Only needed when targeting MSVC on Windows. | 159 | \\# Only needed when targeting MSVC on Windows. |
| 162 | \\kernel32_lib_dir={s} | 160 | \\kernel32_lib_dir={s} |
| 163 | \\ | 161 | \\ |
| 162 | \\# The directory that contains `SDKSettings.json` | ||
| 163 | \\# Only needed when targeting Darwin. | ||
| 164 | \\darwin_sdk_dir={s} | ||
| 165 | \\ | ||
| 164 | , .{ | 166 | , .{ |
| 165 | include_dir, | 167 | self.include_dir orelse "", |
| 166 | sys_include_dir, | 168 | self.sys_include_dir orelse "", |
| 167 | crt_dir, | 169 | self.cc_dir orelse "", |
| 168 | msvc_lib_dir, | 170 | self.crt_dir orelse "", |
| 169 | kernel32_lib_dir, | 171 | self.msvc_lib_dir orelse "", |
| 170 | cc_dir, | 172 | self.kernel32_lib_dir orelse "", |
| 173 | self.darwin_sdk_dir orelse "", | ||
| 171 | }); | 174 | }); |
| 172 | } | 175 | } |
| 173 | 176 | ||
| ... | @@ -186,10 +189,10 @@ pub fn findNative(gpa: Allocator, io: Io, args: FindNativeOptions) FindError!Lib | ... | @@ -186,10 +189,10 @@ pub fn findNative(gpa: Allocator, io: Io, args: FindNativeOptions) FindError!Lib |
| 186 | if (is_darwin and args.target.os.tag.isDarwin()) { | 189 | if (is_darwin and args.target.os.tag.isDarwin()) { |
| 187 | if (!std.zig.system.darwin.isSdkInstalled(gpa, io)) | 190 | if (!std.zig.system.darwin.isSdkInstalled(gpa, io)) |
| 188 | return error.DarwinSdkNotFound; | 191 | return error.DarwinSdkNotFound; |
| 189 | const sdk = std.zig.system.darwin.getSdk(gpa, io, args.target) orelse | 192 | self.darwin_sdk_dir = std.zig.system.darwin.getSdk(gpa, io, args.target) orelse |
| 190 | return error.DarwinSdkNotFound; | 193 | return error.DarwinSdkNotFound; |
| 191 | defer gpa.free(sdk); | ||
| 192 | 194 | ||
| 195 | const sdk = self.darwin_sdk_dir.?; | ||
| 193 | self.include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include" }); | 196 | self.include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include" }); |
| 194 | self.sys_include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include" }); | 197 | self.sys_include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include" }); |
| 195 | self.crt_dir = try fs.path.join(gpa, &.{ sdk, "usr/lib" }); | 198 | self.crt_dir = try fs.path.join(gpa, &.{ sdk, "usr/lib" }); |
src/Compilation.zig+10-6| ... | @@ -2208,7 +2208,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, | ... | @@ -2208,7 +2208,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2208 | .z_relro = options.linker_z_relro, | 2208 | .z_relro = options.linker_z_relro, |
| 2209 | .z_common_page_size = options.linker_z_common_page_size, | 2209 | .z_common_page_size = options.linker_z_common_page_size, |
| 2210 | .z_max_page_size = options.linker_z_max_page_size, | 2210 | .z_max_page_size = options.linker_z_max_page_size, |
| 2211 | .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, | ||
| 2212 | .frameworks = options.frameworks, | 2211 | .frameworks = options.frameworks, |
| 2213 | .lib_directories = options.lib_directories, | 2212 | .lib_directories = options.lib_directories, |
| 2214 | .framework_dirs = options.framework_dirs, | 2213 | .framework_dirs = options.framework_dirs, |
| ... | @@ -2453,10 +2452,16 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, | ... | @@ -2453,10 +2452,16 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2453 | // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`. | 2452 | // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`. |
| 2454 | comp.oneshot_prelink_tasks.appendAssumeCapacity(.load_host_libc); | 2453 | comp.oneshot_prelink_tasks.appendAssumeCapacity(.load_host_libc); |
| 2455 | } else if (target.isDarwinLibC()) { | 2454 | } else if (target.isDarwinLibC()) { |
| 2456 | try comp.oneshot_prelink_tasks.append(gpa, .{ .load_tbd = .{ | 2455 | try comp.oneshot_prelink_tasks.appendSlice(gpa, &.{ |
| 2457 | .root_dir = comp.dirs.zig_lib, | 2456 | .{ .load_tbd = .{ |
| 2458 | .sub_path = "libc" ++ fs.path.sep_str ++ "darwin" ++ fs.path.sep_str ++ "libSystem.tbd", | 2457 | .root_dir = comp.dirs.zig_lib, |
| 2459 | } }); | 2458 | .sub_path = "libc" ++ fs.path.sep_str ++ "darwin" ++ fs.path.sep_str ++ "libSystem.tbd", |
| 2459 | } }, | ||
| 2460 | .{ .load_darwin_sdk_settings = .{ | ||
| 2461 | .root_dir = comp.dirs.zig_lib, | ||
| 2462 | .sub_path = "libc" ++ fs.path.sep_str ++ "darwin" ++ fs.path.sep_str ++ "SDKSettings.json", | ||
| 2463 | } }, | ||
| 2464 | }); | ||
| 2460 | // TODO delete logic from MachO flush() and queue up tasks here instead. | 2465 | // TODO delete logic from MachO flush() and queue up tasks here instead. |
| 2461 | } else if (target.isMuslLibC()) { | 2466 | } else if (target.isMuslLibC()) { |
| 2462 | if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable); | 2467 | if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable); |
| ... | @@ -3487,7 +3492,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes | ... | @@ -3487,7 +3492,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes |
| 3487 | man.hash.add(opts.discard_local_symbols); | 3492 | man.hash.add(opts.discard_local_symbols); |
| 3488 | man.hash.addOptional(opts.compatibility_version); | 3493 | man.hash.addOptional(opts.compatibility_version); |
| 3489 | man.hash.addOptionalBytes(opts.install_name); | 3494 | man.hash.addOptionalBytes(opts.install_name); |
| 3490 | man.hash.addOptional(opts.darwin_sdk_layout); | ||
| 3491 | 3495 | ||
| 3492 | // COFF specific stuff | 3496 | // COFF specific stuff |
| 3493 | man.hash.addOptional(opts.subsystem); | 3497 | man.hash.addOptional(opts.subsystem); |
src/link.zig+150-2| ... | @@ -502,7 +502,6 @@ pub const File = struct { | ... | @@ -502,7 +502,6 @@ pub const File = struct { |
| 502 | /// Remove dylibs that are unreachable by the entry point or exported symbols | 502 | /// Remove dylibs that are unreachable by the entry point or exported symbols |
| 503 | dead_strip_dylibs: bool, | 503 | dead_strip_dylibs: bool, |
| 504 | frameworks: []const MachO.Framework, | 504 | frameworks: []const MachO.Framework, |
| 505 | darwin_sdk_layout: ?MachO.SdkLayout, | ||
| 506 | /// Force load all members of static archives that implement an | 505 | /// Force load all members of static archives that implement an |
| 507 | /// Objective-C class or category | 506 | /// Objective-C class or category |
| 508 | force_load_objc: bool, | 507 | force_load_objc: bool, |
| ... | @@ -1248,6 +1247,59 @@ pub const File = struct { | ... | @@ -1248,6 +1247,59 @@ pub const File = struct { |
| 1248 | } | 1247 | } |
| 1249 | } | 1248 | } |
| 1250 | 1249 | ||
| 1250 | fn loadDarwinSdkSettings(base: *File, sdk_settings_path: Path) Error!void { | ||
| 1251 | const comp = base.comp; | ||
| 1252 | const io = comp.io; | ||
| 1253 | const arena = comp.arena; | ||
| 1254 | const diags = &comp.link_diags; | ||
| 1255 | |||
| 1256 | const contents = sdk_settings_path.root_dir.handle.readFileAlloc( | ||
| 1257 | io, | ||
| 1258 | sdk_settings_path.sub_path, | ||
| 1259 | arena, | ||
| 1260 | .limited(1024 * 1024 * 256), | ||
| 1261 | ) catch |err| switch (err) { | ||
| 1262 | error.OutOfMemory, error.Canceled => |e| return e, | ||
| 1263 | else => |e| return diags.failParse(sdk_settings_path, "failed to parse Darwin SDK settings: {t}", .{e}), | ||
| 1264 | }; | ||
| 1265 | |||
| 1266 | const parsed = std.json.parseFromSlice(std.json.Value, arena, contents, .{}) catch |err| switch (err) { | ||
| 1267 | error.OutOfMemory => |e| return e, | ||
| 1268 | else => |e| return diags.failParse(sdk_settings_path, "failed to parse Darwin SDK settings: {t}", .{e}), | ||
| 1269 | }; | ||
| 1270 | const parsed_object = switch (parsed.value) { | ||
| 1271 | .object => |obj| obj, | ||
| 1272 | else => return diags.failParse(sdk_settings_path, "failed to parse Darwin SDK settings: file is not a JSON object", .{}), | ||
| 1273 | }; | ||
| 1274 | |||
| 1275 | const version_json = parsed_object.get("MinimalDisplayName") orelse return diags.failParse( | ||
| 1276 | sdk_settings_path, | ||
| 1277 | "failed to parse Darwin SDK settings: 'MinimalDisplayName' missing", | ||
| 1278 | .{}, | ||
| 1279 | ); | ||
| 1280 | const version_str: []const u8 = switch (version_json) { | ||
| 1281 | .string => |str| str, | ||
| 1282 | else => return diags.failParse( | ||
| 1283 | sdk_settings_path, | ||
| 1284 | "failed to parse Darwin SDK settings: 'MinimalDisplayName' not a string", | ||
| 1285 | .{}, | ||
| 1286 | ), | ||
| 1287 | }; | ||
| 1288 | const version: DarwinSdkVersion = try .parse(diags, sdk_settings_path, version_str); | ||
| 1289 | try base.setDarwinSdkVersion(version); | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | fn setDarwinSdkVersion(base: *File, version: DarwinSdkVersion) Error!void { | ||
| 1293 | assert(!base.post_prelink); | ||
| 1294 | switch (base.tag) { | ||
| 1295 | inline .macho, .macho2 => |tag| { | ||
| 1296 | dev.check(tag.devFeature()); | ||
| 1297 | return @as(*tag.Type(), @fieldParentPtr("base", base)).setDarwinSdkVersion(version); | ||
| 1298 | }, | ||
| 1299 | else => unreachable, | ||
| 1300 | } | ||
| 1301 | } | ||
| 1302 | |||
| 1251 | /// Called when all linker inputs have been sent via `loadInput`. After | 1303 | /// Called when all linker inputs have been sent via `loadInput`. After |
| 1252 | /// this, `loadInput` will not be called anymore. | 1304 | /// this, `loadInput` will not be called anymore. |
| 1253 | pub fn prelink(base: *File) Error!void { | 1305 | pub fn prelink(base: *File) Error!void { |
| ... | @@ -1451,6 +1503,7 @@ pub const PrelinkTask = union(enum) { | ... | @@ -1451,6 +1503,7 @@ pub const PrelinkTask = union(enum) { |
| 1451 | /// GNU ld script. | 1503 | /// GNU ld script. |
| 1452 | load_dso: Path, | 1504 | load_dso: Path, |
| 1453 | load_tbd: Path, | 1505 | load_tbd: Path, |
| 1506 | load_darwin_sdk_settings: Path, | ||
| 1454 | }; | 1507 | }; |
| 1455 | pub const ZcuTask = union(enum) { | 1508 | pub const ZcuTask = union(enum) { |
| 1456 | /// Sent once per update, as the very first `ZcuTask` in the update. Indicates that all per-file | 1509 | /// 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 { | ... | @@ -1589,7 +1642,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1589 | error.FileNotFound => {}, | 1642 | error.FileNotFound => {}, |
| 1590 | error.AlreadyReported => return, | 1643 | error.AlreadyReported => return, |
| 1591 | error.Canceled => io.recancel(), | 1644 | error.Canceled => io.recancel(), |
| 1592 | else => |e| diags.addParseError(archive_path, "failed to parse archive {f}: {s}", .{ archive_path, @errorName(e) }), | 1645 | else => |e| diags.addParseError(archive_path, "failed to parse archive: {s}", .{@errorName(e)}), |
| 1593 | } | 1646 | } |
| 1594 | 1647 | ||
| 1595 | diags.addError("failed to find library '{s}'", .{lib_name}); | 1648 | diags.addError("failed to find library '{s}'", .{lib_name}); |
| ... | @@ -1612,6 +1665,19 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1612,6 +1665,19 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1612 | } | 1665 | } |
| 1613 | } | 1666 | } |
| 1614 | 1667 | ||
| 1668 | if (target.os.tag.isDarwin()) { | ||
| 1669 | const sdk_settings_path: Path = .initCwd(std.fmt.allocPrint( | ||
| 1670 | comp.arena, | ||
| 1671 | "{s}" ++ sep ++ "SDKSettings.json", | ||
| 1672 | .{libc_installation.darwin_sdk_dir.?}, | ||
| 1673 | ) catch return diags.setAllocFailure()); | ||
| 1674 | base.loadDarwinSdkSettings(sdk_settings_path) catch |err| switch (err) { | ||
| 1675 | error.OutOfMemory => return diags.setAllocFailure(), | ||
| 1676 | error.Canceled => return io.recancel(), | ||
| 1677 | error.AlreadyReported => return, | ||
| 1678 | }; | ||
| 1679 | } | ||
| 1680 | |||
| 1615 | if (target.os.tag == .windows and target.abi == .msvc) { | 1681 | if (target.os.tag == .windows and target.abi == .msvc) { |
| 1616 | const inputs: []const struct { | 1682 | const inputs: []const struct { |
| 1617 | dir: enum { crt, msvc_lib, kernel32_lib }, | 1683 | dir: enum { crt, msvc_lib, kernel32_lib }, |
| ... | @@ -1709,6 +1775,15 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1709,6 +1775,15 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1709 | else => |e| diags.addParseError(path, "failed to parse tbd: {t}", .{e}), | 1775 | else => |e| diags.addParseError(path, "failed to parse tbd: {t}", .{e}), |
| 1710 | } | 1776 | } |
| 1711 | }, | 1777 | }, |
| 1778 | .load_darwin_sdk_settings => |path| { | ||
| 1779 | const prog_node = comp.link_prog_node.start("Parse SDK Settings", 0); | ||
| 1780 | defer prog_node.end(); | ||
| 1781 | base.loadDarwinSdkSettings(path) catch |err| switch (err) { | ||
| 1782 | error.OutOfMemory => return diags.setAllocFailure(), | ||
| 1783 | error.Canceled => return io.recancel(), | ||
| 1784 | error.AlreadyReported => return, | ||
| 1785 | }; | ||
| 1786 | }, | ||
| 1712 | } | 1787 | } |
| 1713 | } | 1788 | } |
| 1714 | pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void { | 1789 | pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void { |
| ... | @@ -2793,3 +2868,76 @@ pub fn firstObjectInput(inputs: []const Input) ?Input.Object { | ... | @@ -2793,3 +2868,76 @@ pub fn firstObjectInput(inputs: []const Input) ?Input.Object { |
| 2793 | }; | 2868 | }; |
| 2794 | return null; | 2869 | return null; |
| 2795 | } | 2870 | } |
| 2871 | |||
| 2872 | pub const DarwinSdkVersion = packed struct(u32) { | ||
| 2873 | patch: u8, | ||
| 2874 | minor: u8, | ||
| 2875 | major: u16, | ||
| 2876 | |||
| 2877 | fn parse( | ||
| 2878 | diags: *Diags, | ||
| 2879 | /// Passed to `Diags.failParse` on error. | ||
| 2880 | sdk_settings_path: Path, | ||
| 2881 | version_str: []const u8, | ||
| 2882 | ) error{AlreadyReported}!DarwinSdkVersion { | ||
| 2883 | var it = std.mem.splitScalar(u8, version_str, '.'); | ||
| 2884 | |||
| 2885 | const major = try parseComponent( | ||
| 2886 | .major, | ||
| 2887 | diags, | ||
| 2888 | sdk_settings_path, | ||
| 2889 | version_str, | ||
| 2890 | it.first(), | ||
| 2891 | ); | ||
| 2892 | const minor = if (it.next()) |component_str| try parseComponent( | ||
| 2893 | .minor, | ||
| 2894 | diags, | ||
| 2895 | sdk_settings_path, | ||
| 2896 | version_str, | ||
| 2897 | component_str, | ||
| 2898 | ) else return diags.failParse( | ||
| 2899 | sdk_settings_path, | ||
| 2900 | "failed to parse Darwin SDK version {q}: missing minor version", | ||
| 2901 | .{version_str}, | ||
| 2902 | ); | ||
| 2903 | const patch = if (it.next()) |component_str| try parseComponent( | ||
| 2904 | .patch, | ||
| 2905 | diags, | ||
| 2906 | sdk_settings_path, | ||
| 2907 | version_str, | ||
| 2908 | component_str, | ||
| 2909 | ) else 0; // Apple sometimes omit the patch version | ||
| 2910 | |||
| 2911 | if (it.next() != null) return diags.failParse( | ||
| 2912 | sdk_settings_path, | ||
| 2913 | "failed to parse Darwin SDK version {q}: too many version components", | ||
| 2914 | .{version_str}, | ||
| 2915 | ); | ||
| 2916 | |||
| 2917 | return .{ .major = major, .minor = minor, .patch = patch }; | ||
| 2918 | } | ||
| 2919 | |||
| 2920 | fn parseComponent( | ||
| 2921 | comptime component: enum { major, minor, patch }, | ||
| 2922 | diags: *Diags, | ||
| 2923 | /// Passed to `Diags.failParse` on error. | ||
| 2924 | sdk_settings_path: Path, | ||
| 2925 | /// Only used for error messages. | ||
| 2926 | version_str: []const u8, | ||
| 2927 | component_str: []const u8, | ||
| 2928 | ) error{AlreadyReported}!@FieldType(DarwinSdkVersion, @tagName(component)) { | ||
| 2929 | const Int = @FieldType(DarwinSdkVersion, @tagName(component)); | ||
| 2930 | return std.fmt.parseInt(Int, component_str, 10) catch |err| switch (err) { | ||
| 2931 | error.Overflow => return diags.failParse( | ||
| 2932 | sdk_settings_path, | ||
| 2933 | "failed to parse Darwin SDK version {q}: {t} version {q} too large", | ||
| 2934 | .{ version_str, component, component_str }, | ||
| 2935 | ), | ||
| 2936 | error.InvalidCharacter => return diags.failParse( | ||
| 2937 | sdk_settings_path, | ||
| 2938 | "failed to parse Darwin SDK version {q}: invalid {t} version {q}", | ||
| 2939 | .{ version_str, component, component_str }, | ||
| 2940 | ), | ||
| 2941 | }; | ||
| 2942 | } | ||
| 2943 | }; |
src/link/MachO.zig+26-100| ... | @@ -106,9 +106,7 @@ has_tlv: AtomicBool = AtomicBool.init(false), | ... | @@ -106,9 +106,7 @@ has_tlv: AtomicBool = AtomicBool.init(false), |
| 106 | binds_to_weak: AtomicBool = AtomicBool.init(false), | 106 | binds_to_weak: AtomicBool = AtomicBool.init(false), |
| 107 | weak_defines: AtomicBool = AtomicBool.init(false), | 107 | weak_defines: AtomicBool = AtomicBool.init(false), |
| 108 | 108 | ||
| 109 | /// Options | 109 | // Options |
| 110 | /// SDK layout | ||
| 111 | sdk_layout: ?SdkLayout, | ||
| 112 | /// Size of the __PAGEZERO segment. | 110 | /// Size of the __PAGEZERO segment. |
| 113 | pagezero_size: ?u64, | 111 | pagezero_size: ?u64, |
| 114 | /// Minimum space for future expansion of the load commands. | 112 | /// Minimum space for future expansion of the load commands. |
| ... | @@ -134,7 +132,7 @@ compatibility_version: ?std.SemanticVersion, | ... | @@ -134,7 +132,7 @@ compatibility_version: ?std.SemanticVersion, |
| 134 | /// Entry name | 132 | /// Entry name |
| 135 | entry_name: ?[]const u8, | 133 | entry_name: ?[]const u8, |
| 136 | platform: Platform, | 134 | platform: Platform, |
| 137 | sdk_version: ?std.SemanticVersion, | 135 | sdk_version: ?link.DarwinSdkVersion, |
| 138 | /// When set to true, the linker will hoist all dylibs including system dependent dylibs. | 136 | /// When set to true, the linker will hoist all dylibs including system dependent dylibs. |
| 139 | no_implicit_dylibs: bool = false, | 137 | no_implicit_dylibs: bool = false, |
| 140 | /// Whether the linker should parse and always force load objects containing ObjC in archives. | 138 | /// Whether the linker should parse and always force load objects containing ObjC in archives. |
| ... | @@ -198,7 +196,6 @@ pub fn createEmpty( | ... | @@ -198,7 +196,6 @@ pub fn createEmpty( |
| 198 | .headerpad_size = options.headerpad_size, | 196 | .headerpad_size = options.headerpad_size, |
| 199 | .headerpad_max_install_names = options.headerpad_max_install_names, | 197 | .headerpad_max_install_names = options.headerpad_max_install_names, |
| 200 | .dead_strip_dylibs = options.dead_strip_dylibs, | 198 | .dead_strip_dylibs = options.dead_strip_dylibs, |
| 201 | .sdk_layout = options.darwin_sdk_layout, | ||
| 202 | .frameworks = options.frameworks, | 199 | .frameworks = options.frameworks, |
| 203 | .install_name = options.install_name, | 200 | .install_name = options.install_name, |
| 204 | .entitlements = options.entitlements, | 201 | .entitlements = options.entitlements, |
| ... | @@ -210,7 +207,7 @@ pub fn createEmpty( | ... | @@ -210,7 +207,7 @@ pub fn createEmpty( |
| 210 | .named => |name| name, | 207 | .named => |name| name, |
| 211 | }, | 208 | }, |
| 212 | .platform = Platform.fromTarget(target), | 209 | .platform = Platform.fromTarget(target), |
| 213 | .sdk_version = if (options.darwin_sdk_layout) |layout| inferSdkVersion(comp, layout) else null, | 210 | .sdk_version = null, |
| 214 | .undefined_treatment = if (allow_shlib_undefined) .dynamic_lookup else .@"error", | 211 | .undefined_treatment = if (allow_shlib_undefined) .dynamic_lookup else .@"error", |
| 215 | // TODO delete this, directories must instead be resolved by the frontend | 212 | // TODO delete this, directories must instead be resolved by the frontend |
| 216 | .lib_directories = options.lib_directories, | 213 | .lib_directories = options.lib_directories, |
| ... | @@ -604,12 +601,20 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -604,12 +601,20 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 604 | 601 | ||
| 605 | try argv.append("-platform_version"); | 602 | try argv.append("-platform_version"); |
| 606 | try argv.append(@tagName(self.platform.os_tag)); | 603 | try argv.append(@tagName(self.platform.os_tag)); |
| 607 | try argv.append(try std.fmt.allocPrint(arena, "{f}", .{self.platform.version})); | 604 | try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}.{d}", .{ |
| 605 | self.platform.version.major, | ||
| 606 | self.platform.version.minor, | ||
| 607 | self.platform.version.patch, | ||
| 608 | })); | ||
| 608 | 609 | ||
| 609 | if (self.sdk_version) |ver| { | 610 | if (self.sdk_version) |ver| { |
| 610 | try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor })); | 611 | try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor })); |
| 611 | } else { | 612 | } else { |
| 612 | try argv.append(try std.fmt.allocPrint(arena, "{f}", .{self.platform.version})); | 613 | try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}.{d}", .{ |
| 614 | self.platform.version.major, | ||
| 615 | self.platform.version.minor, | ||
| 616 | self.platform.version.patch, | ||
| 617 | })); | ||
| 613 | } | 618 | } |
| 614 | 619 | ||
| 615 | if (comp.sysroot) |syslibroot| { | 620 | if (comp.sysroot) |syslibroot| { |
| ... | @@ -4101,7 +4106,7 @@ pub const null_sym = macho.nlist_64{ | ... | @@ -4101,7 +4106,7 @@ pub const null_sym = macho.nlist_64{ |
| 4101 | pub const Platform = struct { | 4106 | pub const Platform = struct { |
| 4102 | os_tag: std.Target.Os.Tag, | 4107 | os_tag: std.Target.Os.Tag, |
| 4103 | abi: std.Target.Abi, | 4108 | abi: std.Target.Abi, |
| 4104 | version: std.SemanticVersion, | 4109 | version: link.DarwinSdkVersion, |
| 4105 | 4110 | ||
| 4106 | /// Using Apple's ld64 as our blueprint, `min_version` as well as `sdk_version` are set to | 4111 | /// Using Apple's ld64 as our blueprint, `min_version` as well as `sdk_version` are set to |
| 4107 | /// the extracted minimum platform version. | 4112 | /// the extracted minimum platform version. |
| ... | @@ -4128,7 +4133,7 @@ pub const Platform = struct { | ... | @@ -4128,7 +4133,7 @@ pub const Platform = struct { |
| 4128 | => .simulator, | 4133 | => .simulator, |
| 4129 | else => .none, | 4134 | else => .none, |
| 4130 | }, | 4135 | }, |
| 4131 | .version = appleVersionToSemanticVersion(cmd.minos), | 4136 | .version = @fromBackingInt(cmd.minos), |
| 4132 | }; | 4137 | }; |
| 4133 | }, | 4138 | }, |
| 4134 | .VERSION_MIN_IPHONEOS, | 4139 | .VERSION_MIN_IPHONEOS, |
| ... | @@ -4147,7 +4152,7 @@ pub const Platform = struct { | ... | @@ -4147,7 +4152,7 @@ pub const Platform = struct { |
| 4147 | else => unreachable, | 4152 | else => unreachable, |
| 4148 | }, | 4153 | }, |
| 4149 | .abi = .none, | 4154 | .abi = .none, |
| 4150 | .version = appleVersionToSemanticVersion(cmd.version), | 4155 | .version = @fromBackingInt(cmd.version), |
| 4151 | }; | 4156 | }; |
| 4152 | }, | 4157 | }, |
| 4153 | else => unreachable, | 4158 | else => unreachable, |
| ... | @@ -4155,17 +4160,18 @@ pub const Platform = struct { | ... | @@ -4155,17 +4160,18 @@ pub const Platform = struct { |
| 4155 | } | 4160 | } |
| 4156 | 4161 | ||
| 4157 | pub fn fromTarget(target: *const std.Target) Platform { | 4162 | pub fn fromTarget(target: *const std.Target) Platform { |
| 4163 | const semver = target.os.version_range.semver.min; | ||
| 4158 | return .{ | 4164 | return .{ |
| 4159 | .os_tag = target.os.tag, | 4165 | .os_tag = target.os.tag, |
| 4160 | .abi = target.abi, | 4166 | .abi = target.abi, |
| 4161 | .version = target.os.version_range.semver.min, | 4167 | .version = .{ |
| 4168 | .major = @intCast(semver.major), | ||
| 4169 | .minor = @intCast(semver.minor), | ||
| 4170 | .patch = @intCast(semver.patch), | ||
| 4171 | }, | ||
| 4162 | }; | 4172 | }; |
| 4163 | } | 4173 | } |
| 4164 | 4174 | ||
| 4165 | pub fn toAppleVersion(plat: Platform) u32 { | ||
| 4166 | return semanticVersionToAppleVersion(plat.version); | ||
| 4167 | } | ||
| 4168 | |||
| 4169 | pub fn toApplePlatform(plat: Platform) macho.PLATFORM { | 4175 | pub fn toApplePlatform(plat: Platform) macho.PLATFORM { |
| 4170 | return switch (plat.os_tag) { | 4176 | return switch (plat.os_tag) { |
| 4171 | .driverkit => .DRIVERKIT, | 4177 | .driverkit => .DRIVERKIT, |
| ... | @@ -4182,7 +4188,7 @@ pub const Platform = struct { | ... | @@ -4182,7 +4188,7 @@ pub const Platform = struct { |
| 4182 | pub fn isBuildVersionCompatible(plat: Platform) bool { | 4188 | pub fn isBuildVersionCompatible(plat: Platform) bool { |
| 4183 | inline for (supported_platforms) |sup_plat| { | 4189 | inline for (supported_platforms) |sup_plat| { |
| 4184 | if (sup_plat[0] == plat.os_tag and sup_plat[1] == plat.abi) { | 4190 | if (sup_plat[0] == plat.os_tag and sup_plat[1] == plat.abi) { |
| 4185 | return sup_plat[2] <= plat.toAppleVersion(); | 4191 | return sup_plat[2] <= @backingInt(plat.version); |
| 4186 | } | 4192 | } |
| 4187 | } | 4193 | } |
| 4188 | return false; | 4194 | return false; |
| ... | @@ -4191,7 +4197,7 @@ pub const Platform = struct { | ... | @@ -4191,7 +4197,7 @@ pub const Platform = struct { |
| 4191 | pub fn isVersionMinCompatible(plat: Platform) bool { | 4197 | pub fn isVersionMinCompatible(plat: Platform) bool { |
| 4192 | inline for (supported_platforms) |sup_plat| { | 4198 | inline for (supported_platforms) |sup_plat| { |
| 4193 | if (sup_plat[0] == plat.os_tag and sup_plat[1] == plat.abi) { | 4199 | if (sup_plat[0] == plat.os_tag and sup_plat[1] == plat.abi) { |
| 4194 | return sup_plat[3] <= plat.toAppleVersion(); | 4200 | return sup_plat[3] <= @backingInt(plat.version); |
| 4195 | } | 4201 | } |
| 4196 | } | 4202 | } |
| 4197 | return false; | 4203 | return false; |
| ... | @@ -4250,86 +4256,8 @@ const supported_platforms = [_]SupportedPlatforms{ | ... | @@ -4250,86 +4256,8 @@ const supported_platforms = [_]SupportedPlatforms{ |
| 4250 | }; | 4256 | }; |
| 4251 | // zig fmt: on | 4257 | // zig fmt: on |
| 4252 | 4258 | ||
| 4253 | pub inline fn semanticVersionToAppleVersion(version: std.SemanticVersion) u32 { | 4259 | pub fn setDarwinSdkVersion(self: *MachO, version: link.DarwinSdkVersion) link.Error!void { |
| 4254 | const major = version.major; | 4260 | self.sdk_version = version; |
| 4255 | const minor = version.minor; | ||
| 4256 | const patch = version.patch; | ||
| 4257 | return (@as(u32, @intCast(major)) << 16) | (@as(u32, @intCast(minor)) << 8) | @as(u32, @intCast(patch)); | ||
| 4258 | } | ||
| 4259 | |||
| 4260 | pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion { | ||
| 4261 | return .{ | ||
| 4262 | .major = @as(u16, @truncate(version >> 16)), | ||
| 4263 | .minor = @as(u8, @truncate(version >> 8)), | ||
| 4264 | .patch = @as(u8, @truncate(version)), | ||
| 4265 | }; | ||
| 4266 | } | ||
| 4267 | |||
| 4268 | fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersion { | ||
| 4269 | const gpa = comp.gpa; | ||
| 4270 | |||
| 4271 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); | ||
| 4272 | defer arena_allocator.deinit(); | ||
| 4273 | const arena = arena_allocator.allocator(); | ||
| 4274 | |||
| 4275 | const io = comp.io; | ||
| 4276 | |||
| 4277 | const sdk_dir = switch (sdk_layout) { | ||
| 4278 | .sdk => comp.sysroot.?, | ||
| 4279 | .vendored => fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "libc", "darwin" }) catch return null, | ||
| 4280 | }; | ||
| 4281 | if (readSdkVersionFromSettings(arena, io, sdk_dir)) |ver| { | ||
| 4282 | return parseSdkVersion(ver); | ||
| 4283 | } else |_| { | ||
| 4284 | // Read from settings should always succeed when vendored. | ||
| 4285 | // TODO: convert to fatal linker error | ||
| 4286 | if (sdk_layout == .vendored) @panic("zig installation bug: unable to parse SDK version"); | ||
| 4287 | } | ||
| 4288 | |||
| 4289 | // infer from pathname | ||
| 4290 | const stem = fs.path.stem(sdk_dir); | ||
| 4291 | const start = for (stem, 0..) |c, i| { | ||
| 4292 | if (std.ascii.isDigit(c)) break i; | ||
| 4293 | } else stem.len; | ||
| 4294 | const end = for (stem[start..], start..) |c, i| { | ||
| 4295 | if (std.ascii.isDigit(c) or c == '.') continue; | ||
| 4296 | break i; | ||
| 4297 | } else stem.len; | ||
| 4298 | return parseSdkVersion(stem[start..end]); | ||
| 4299 | } | ||
| 4300 | |||
| 4301 | // Official Apple SDKs ship with a `SDKSettings.json` located at the top of SDK fs layout. | ||
| 4302 | // Use property `MinimalDisplayName` to determine version. | ||
| 4303 | // The file/property is also available with vendored libc. | ||
| 4304 | fn readSdkVersionFromSettings(arena: Allocator, io: Io, dir: []const u8) ![]const u8 { | ||
| 4305 | const sdk_path = try fs.path.join(arena, &.{ dir, "SDKSettings.json" }); | ||
| 4306 | const contents = try Io.Dir.cwd().readFileAlloc(io, sdk_path, arena, .limited(std.math.maxInt(u16))); | ||
| 4307 | const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{}); | ||
| 4308 | if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string; | ||
| 4309 | return error.SdkVersionFailure; | ||
| 4310 | } | ||
| 4311 | |||
| 4312 | // Versions reported by Apple aren't exactly semantically valid as they usually omit | ||
| 4313 | // the patch component, so we parse SDK value by hand. | ||
| 4314 | fn parseSdkVersion(raw: []const u8) ?std.SemanticVersion { | ||
| 4315 | var parsed: std.SemanticVersion = .{ | ||
| 4316 | .major = 0, | ||
| 4317 | .minor = 0, | ||
| 4318 | .patch = 0, | ||
| 4319 | }; | ||
| 4320 | |||
| 4321 | const parseNext = struct { | ||
| 4322 | fn parseNext(it: anytype) ?u16 { | ||
| 4323 | const nn = it.next() orelse return null; | ||
| 4324 | return std.fmt.parseInt(u16, nn, 10) catch null; | ||
| 4325 | } | ||
| 4326 | }.parseNext; | ||
| 4327 | |||
| 4328 | var it = std.mem.splitAny(u8, raw, "."); | ||
| 4329 | parsed.major = parseNext(&it) orelse return null; | ||
| 4330 | parsed.minor = parseNext(&it) orelse return null; | ||
| 4331 | parsed.patch = parseNext(&it) orelse 0; | ||
| 4332 | return parsed; | ||
| 4333 | } | 4261 | } |
| 4334 | 4262 | ||
| 4335 | /// When allocating, the ideal_capacity is calculated by | 4263 | /// When allocating, the ideal_capacity is calculated by |
| ... | @@ -4377,8 +4305,6 @@ const SystemLib = struct { | ... | @@ -4377,8 +4305,6 @@ const SystemLib = struct { |
| 4377 | } | 4305 | } |
| 4378 | }; | 4306 | }; |
| 4379 | 4307 | ||
| 4380 | pub const SdkLayout = std.zig.LibCDirs.DarwinSdkLayout; | ||
| 4381 | |||
| 4382 | const UndefinedTreatment = enum { | 4308 | const UndefinedTreatment = enum { |
| 4383 | @"error", | 4309 | @"error", |
| 4384 | warn, | 4310 | warn, |
src/link/MachO/load_commands.zig+7-12| ... | @@ -9,6 +9,7 @@ const Allocator = std.mem.Allocator; | ... | @@ -9,6 +9,7 @@ const Allocator = std.mem.Allocator; |
| 9 | const DebugSymbols = @import("DebugSymbols.zig"); | 9 | const DebugSymbols = @import("DebugSymbols.zig"); |
| 10 | const Dylib = @import("Dylib.zig"); | 10 | const Dylib = @import("Dylib.zig"); |
| 11 | const MachO = @import("../MachO.zig"); | 11 | const MachO = @import("../MachO.zig"); |
| 12 | const link = @import("../../link.zig"); | ||
| 12 | 13 | ||
| 13 | pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld"; | 14 | pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld"; |
| 14 | 15 | ||
| ... | @@ -296,7 +297,7 @@ pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { | ... | @@ -296,7 +297,7 @@ pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { |
| 296 | } | 297 | } |
| 297 | } | 298 | } |
| 298 | 299 | ||
| 299 | pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { | 300 | pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?link.DarwinSdkVersion, writer: *Writer) !void { |
| 300 | const cmd: macho.LC = switch (platform.os_tag) { | 301 | const cmd: macho.LC = switch (platform.os_tag) { |
| 301 | .macos => .VERSION_MIN_MACOSX, | 302 | .macos => .VERSION_MIN_MACOSX, |
| 302 | .ios, .maccatalyst => .VERSION_MIN_IPHONEOS, | 303 | .ios, .maccatalyst => .VERSION_MIN_IPHONEOS, |
| ... | @@ -306,24 +307,18 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer | ... | @@ -306,24 +307,18 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer |
| 306 | }; | 307 | }; |
| 307 | try writer.writeAll(mem.asBytes(&macho.version_min_command{ | 308 | try writer.writeAll(mem.asBytes(&macho.version_min_command{ |
| 308 | .cmd = cmd, | 309 | .cmd = cmd, |
| 309 | .version = platform.toAppleVersion(), | 310 | .version = @backingInt(platform.version), |
| 310 | .sdk = if (sdk_version) |ver| | 311 | .sdk = @backingInt(sdk_version orelse platform.version), |
| 311 | MachO.semanticVersionToAppleVersion(ver) | ||
| 312 | else | ||
| 313 | platform.toAppleVersion(), | ||
| 314 | })); | 312 | })); |
| 315 | } | 313 | } |
| 316 | 314 | ||
| 317 | pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { | 315 | pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?link.DarwinSdkVersion, writer: *Writer) !void { |
| 318 | const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version); | 316 | const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version); |
| 319 | try writer.writeStruct(@as(macho.build_version_command, .{ | 317 | try writer.writeStruct(@as(macho.build_version_command, .{ |
| 320 | .cmdsize = cmdsize, | 318 | .cmdsize = cmdsize, |
| 321 | .platform = platform.toApplePlatform(), | 319 | .platform = platform.toApplePlatform(), |
| 322 | .minos = platform.toAppleVersion(), | 320 | .minos = @backingInt(platform.version), |
| 323 | .sdk = if (sdk_version) |ver| | 321 | .sdk = @backingInt(sdk_version orelse platform.version), |
| 324 | MachO.semanticVersionToAppleVersion(ver) | ||
| 325 | else | ||
| 326 | platform.toAppleVersion(), | ||
| 327 | .ntools = 1, | 322 | .ntools = 1, |
| 328 | }), .little); | 323 | }), .little); |
| 329 | try writer.writeAll(mem.asBytes(&macho.build_tool_version{ | 324 | try writer.writeAll(mem.asBytes(&macho.build_tool_version{ |
src/link/MachO2.zig+4| ... | @@ -138,6 +138,10 @@ pub fn loadInput(macho: *MachO, input: link.Input) link.Error!void { | ... | @@ -138,6 +138,10 @@ pub fn loadInput(macho: *MachO, input: link.Input) link.Error!void { |
| 138 | _ = input; | 138 | _ = input; |
| 139 | @panic("TODO"); | 139 | @panic("TODO"); |
| 140 | } | 140 | } |
| 141 | pub fn setDarwinSdkVersion(macho: *MachO, version: link.DarwinSdkVersion) link.Error!void { | ||
| 142 | _ = macho; | ||
| 143 | std.log.err("MLUGG TODO: sdk version is '{d}.{d}.{d}'", .{ version.major, version.minor, version.patch }); | ||
| 144 | } | ||
| 141 | pub fn prelink(macho: *MachO, prog_node: std.Progress.Node) link.Error!void { | 145 | pub fn prelink(macho: *MachO, prog_node: std.Progress.Node) link.Error!void { |
| 142 | _ = macho; | 146 | _ = macho; |
| 143 | _ = prog_node; | 147 | _ = prog_node; |