aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-09-26 13:16:07 -0700
committerGitHub <noreply@github.com>2023-09-26 13:16:07 -0700
commit5d907171e2941be9ad62e289ceeb17e7b4c0be2b (patch)
tree45fffa3f7d66a02820c3b3aab2273258ea60a802 /src
parent15ce9652525de2cc245203042d8c62ef30d5de1f (diff)
parent0c8bf405ebeab9b1c72ca31b4f066189d74048d0 (diff)
downloadzig-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.zig31
-rw-r--r--src/link.zig9
-rw-r--r--src/link/MachO.zig46
-rw-r--r--src/link/MachO/load_commands.zig35
-rw-r--r--src/link/MachO/zld.zig20
-rw-r--r--src/target.zig44
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;
}