diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-09-26 13:16:07 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-26 13:16:07 -0700 |
| commit | 5d907171e2941be9ad62e289ceeb17e7b4c0be2b (patch) | |
| tree | 45fffa3f7d66a02820c3b3aab2273258ea60a802 /src | |
| parent | 15ce9652525de2cc245203042d8c62ef30d5de1f (diff) | |
| parent | 0c8bf405ebeab9b1c72ca31b4f066189d74048d0 (diff) | |
| download | zig-5d907171e2941be9ad62e289ceeb17e7b4c0be2b.tar.gz zig-5d907171e2941be9ad62e289ceeb17e7b4c0be2b.zip | |
Merge pull request #17152 from mikdusan/macos-sdk
macos SDK updates and enhancements
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compilation.zig | 31 | ||||
| -rw-r--r-- | src/link.zig | 9 | ||||
| -rw-r--r-- | src/link/MachO.zig | 46 | ||||
| -rw-r--r-- | src/link/MachO/load_commands.zig | 35 | ||||
| -rw-r--r-- | src/link/MachO/zld.zig | 20 | ||||
| -rw-r--r-- | src/target.zig | 44 |
6 files changed, 111 insertions, 74 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index c1cfe4613c..4bd3218a35 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1557,6 +1557,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .link_libc = link_libc, .link_libcpp = link_libcpp, .link_libunwind = link_libunwind, + .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, .objects = options.link_objects, .frameworks = options.frameworks, .framework_dirs = options.framework_dirs, @@ -5294,6 +5295,7 @@ fn detectWin32ResourceIncludeDirs(arena: Allocator, options: InitOptions) !LibCD .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, + .darwin_sdk_layout = null, }, } } @@ -5662,38 +5664,23 @@ const LibCDirs = struct { libc_installation: ?*const LibCInstallation, libc_framework_dir_list: []const []const u8, sysroot: ?[]const u8, + darwin_sdk_layout: ?link.DarwinSdkLayout, }; -fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8, target: Target) !LibCDirs { - const arch_name = @tagName(target.cpu.arch); - const os_name = try std.fmt.allocPrint(arena, "{s}.{d}", .{ - @tagName(target.os.tag), - target.os.version_range.semver.min.major, - }); +fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8) !LibCDirs { const s = std.fs.path.sep_str; - const list = try arena.alloc([]const u8, 3); - + const list = try arena.alloc([]const u8, 1); list[0] = try std.fmt.allocPrint( arena, - "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-none", - .{ zig_lib_dir, arch_name, os_name }, - ); - list[1] = try std.fmt.allocPrint( - arena, - "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any", - .{ zig_lib_dir, os_name }, - ); - list[2] = try std.fmt.allocPrint( - arena, "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-macos-any", .{zig_lib_dir}, ); - return LibCDirs{ .libc_include_dir_list = list, .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, + .darwin_sdk_layout = .vendored, }; } @@ -5711,6 +5698,7 @@ pub fn detectLibCIncludeDirs( .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, + .darwin_sdk_layout = null, }; } @@ -5768,6 +5756,7 @@ pub fn detectLibCIncludeDirs( .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, + .darwin_sdk_layout = null, }; } @@ -5822,6 +5811,7 @@ fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const .libc_installation = lci, .libc_framework_dir_list = framework_list.items, .sysroot = sysroot, + .darwin_sdk_layout = if (sysroot == null) null else .sdk, }; } @@ -5831,7 +5821,7 @@ fn detectLibCFromBuilding( target: std.Target, ) !LibCDirs { if (target.isDarwin()) - return getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target); + return getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir); const generic_name = target_util.libCGenericName(target); // Some architectures are handled by the same set of headers. @@ -5883,6 +5873,7 @@ fn detectLibCFromBuilding( .libc_installation = null, .libc_framework_dir_list = &.{}, .sysroot = null, + .darwin_sdk_layout = .vendored, }; } diff --git a/src/link.zig b/src/link.zig index fb71262f66..844ddb7b40 100644 --- a/src/link.zig +++ b/src/link.zig @@ -137,6 +137,7 @@ pub const Options = struct { link_libc: bool, link_libcpp: bool, link_libunwind: bool, + darwin_sdk_layout: ?DarwinSdkLayout, function_sections: bool, no_builtin: bool, eh_frame_hdr: bool, @@ -282,6 +283,14 @@ pub const HashStyle = enum { sysv, gnu, both }; pub const CompressDebugSections = enum { none, zlib }; +/// 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, <NONE> }. + vendored, +}; + pub const File = struct { tag: Tag, options: Options, diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 735a36a9df..b779aff41f 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -558,10 +558,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No }); { const platform = Platform.fromTarget(self.base.options.target); - const sdk_version: ?std.SemanticVersion = if (self.base.options.sysroot) |path| - load_commands.inferSdkVersionFromSdkPath(path) - else - null; + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); } else if (platform.isVersionMinCompatible()) { @@ -647,11 +644,6 @@ pub fn resolveLibSystem( var checked_paths = std.ArrayList([]const u8).init(tmp_arena); success: { - if (self.base.options.sysroot) |root| { - const dir = try fs.path.join(tmp_arena, &[_][]const u8{ root, "usr", "lib" }); - if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success; - } - for (search_dirs) |dir| if (try accessLibPath( tmp_arena, &test_path, @@ -660,11 +652,16 @@ pub fn resolveLibSystem( "libSystem", )) break :success; - const dir = try comp.zig_lib_directory.join(tmp_arena, &[_][]const u8{ "libc", "darwin" }); - const lib_name = try std.fmt.allocPrint(tmp_arena, "libSystem.{d}", .{ - self.base.options.target.os.version_range.semver.min.major, - }); - if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, lib_name)) break :success; + if (self.base.options.darwin_sdk_layout) |sdk_layout| switch (sdk_layout) { + .sdk => { + const dir = try fs.path.join(tmp_arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" }); + if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success; + }, + .vendored => { + const dir = try comp.zig_lib_directory.join(tmp_arena, &[_][]const u8{ "libc", "darwin" }); + if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success; + }, + }; try self.reportMissingLibraryError(checked_paths.items, "unable to find libSystem system library", .{}); return; @@ -676,27 +673,6 @@ pub fn resolveLibSystem( .weak = false, .path = libsystem_path, }); - - const ext = fs.path.extension(libsystem_path); - if (mem.eql(u8, ext, ".dylib")) { - // We found 'libSystem.dylib', so now we also need to look for 'libc.dylib'. - success: { - if (self.base.options.sysroot) |root| { - const dir = try fs.path.join(tmp_arena, &[_][]const u8{ root, "usr", "lib" }); - if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libc")) break :success; - } - - for (search_dirs) |dir| if (try accessLibPath( - tmp_arena, - &test_path, - &checked_paths, - dir, - "libc", - )) break :success; - - try self.reportMissingLibraryError(checked_paths.items, "unable to find libc system library", .{}); - } - } } fn accessLibPath( diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index cd1e015757..669e806728 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -467,8 +467,27 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion { }; } -pub fn inferSdkVersionFromSdkPath(path: []const u8) ?std.SemanticVersion { - const stem = std.fs.path.stem(path); +pub fn inferSdkVersion(gpa: Allocator, comp: *const Compilation) ?std.SemanticVersion { + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + const options = comp.bin_file.options; + + const sdk_layout = options.darwin_sdk_layout orelse return null; + const sdk_dir = switch (sdk_layout) { + .sdk => options.sysroot.?, + .vendored => std.fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null, + }; + if (readSdkVersionFromSettings(arena, sdk_dir)) |ver| { + return parseSdkVersion(ver); + } else |_| { + // Read from settings should always succeed when vendored. + if (sdk_layout == .vendored) @panic("zig installation bug: unable to parse SDK version"); + } + + // infer from pathname + const stem = std.fs.path.stem(sdk_dir); const start = for (stem, 0..) |c, i| { if (std.ascii.isDigit(c)) break i; } else stem.len; @@ -479,6 +498,17 @@ pub fn inferSdkVersionFromSdkPath(path: []const u8) ?std.SemanticVersion { 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, dir: []const u8) ![]const u8 { + const sdk_path = try std.fs.path.join(arena, &.{ dir, "SDKSettings.json" }); + const contents = try std.fs.cwd().readFileAlloc(arena, sdk_path, 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 { @@ -532,3 +562,4 @@ const mem = std.mem; const Allocator = mem.Allocator; const Dylib = @import("Dylib.zig"); const MachO = @import("../MachO.zig"); +const Compilation = @import("../../Compilation.zig"); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 1c1301e2b5..19339eb19a 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -235,6 +235,20 @@ pub fn linkWithZld( } } + { + const platform = Platform.fromTarget(options.target); + try argv.append("-platform_version"); + try argv.append(@tagName(platform.os_tag)); + try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version})); + + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + if (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, "{}", .{platform.version})); + } + } + if (options.sysroot) |syslibroot| { try argv.append("-syslibroot"); try argv.append(syslibroot); @@ -300,7 +314,6 @@ pub fn linkWithZld( try argv.append(full_out_path); try argv.append("-lSystem"); - try argv.append("-lc"); for (options.system_libs.keys()) |l_name| { const info = options.system_libs.get(l_name).?; @@ -561,10 +574,7 @@ pub fn linkWithZld( }); { const platform = Platform.fromTarget(macho_file.base.options.target); - const sdk_version: ?std.SemanticVersion = if (macho_file.base.options.sysroot) |path| - load_commands.inferSdkVersionFromSdkPath(path) - else - null; + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); } else { diff --git a/src/target.zig b/src/target.zig index 5e5cf95614..59a7a48cf9 100644 --- a/src/target.zig +++ b/src/target.zig @@ -18,8 +18,6 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .aarch64, .os = .linux, .abi = .musl }, .{ .arch = .aarch64, .os = .windows, .abi = .gnu }, .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 11, .minor = 0, .patch = 0 } }, - .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 12, .minor = 0, .patch = 0 } }, - .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 13, .minor = 0, .patch = 0 } }, .{ .arch = .armeb, .os = .linux, .abi = .gnueabi }, .{ .arch = .armeb, .os = .linux, .abi = .gnueabihf }, .{ .arch = .armeb, .os = .linux, .abi = .musleabi }, @@ -72,9 +70,7 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .x86_64, .os = .linux, .abi = .gnux32 }, .{ .arch = .x86_64, .os = .linux, .abi = .musl }, .{ .arch = .x86_64, .os = .windows, .abi = .gnu }, - .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 11, .minor = 0, .patch = 0 } }, - .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 12, .minor = 0, .patch = 0 } }, - .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 13, .minor = 0, .patch = 0 } }, + .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } }, }; pub fn libCGenericName(target: std.Target) [:0]const u8 { @@ -153,7 +149,7 @@ pub fn canBuildLibC(target: std.Target) bool { if (target.cpu.arch == libc.arch and target.os.tag == libc.os and target.abi == libc.abi) { if (target.os.tag == .macos) { const ver = target.os.version_range.semver; - if (ver.min.major != libc.os_ver.?.major) continue; // no match, keep going + return ver.min.order(libc.os_ver.?) != .lt; } return true; } @@ -358,7 +354,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool { } pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool { - const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows; + const ignore_case = target.os.tag == .macos or target.os.tag == .windows; if (eqlIgnoreCase(ignore_case, name, "c")) return true; @@ -366,7 +362,6 @@ pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool { if (target.isMinGW()) { if (eqlIgnoreCase(ignore_case, name, "m")) return true; - if (eqlIgnoreCase(ignore_case, name, "uuid")) return true; if (eqlIgnoreCase(ignore_case, name, "mingw32")) @@ -379,7 +374,7 @@ pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool { return false; } - if (target.abi.isGnu() or target.abi.isMusl() or target.os.tag.isDarwin()) { + if (target.abi.isGnu() or target.abi.isMusl()) { if (eqlIgnoreCase(ignore_case, name, "m")) return true; if (eqlIgnoreCase(ignore_case, name, "rt")) @@ -396,13 +391,38 @@ pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool { return true; } - if (target.abi.isMusl() or target.os.tag.isDarwin()) { + if (target.abi.isMusl()) { if (eqlIgnoreCase(ignore_case, name, "crypt")) return true; } - if (target.os.tag.isDarwin() and eqlIgnoreCase(ignore_case, name, "System")) - return true; + if (target.os.tag.isDarwin()) { + if (eqlIgnoreCase(ignore_case, name, "System")) + return true; + if (eqlIgnoreCase(ignore_case, name, "c")) + return true; + if (eqlIgnoreCase(ignore_case, name, "dbm")) + return true; + if (eqlIgnoreCase(ignore_case, name, "dl")) + return true; + if (eqlIgnoreCase(ignore_case, name, "info")) + return true; + if (eqlIgnoreCase(ignore_case, name, "m")) + return true; + if (eqlIgnoreCase(ignore_case, name, "poll")) + return true; + if (eqlIgnoreCase(ignore_case, name, "proc")) + return true; + if (eqlIgnoreCase(ignore_case, name, "pthread")) + return true; + if (eqlIgnoreCase(ignore_case, name, "rpcsvc")) + return true; + } + + if (target.os.isAtLeast(.macos, .{ .major = 10, .minor = 8, .patch = 0 }) orelse false) { + if (eqlIgnoreCase(ignore_case, name, "mx")) + return true; + } return false; } |
