authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-11-26 16:08:44+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-11-26 16:26:44+01:00
log8317dbd1cb32eaeafa509e7142766f3d9a82de5f
tree780a0c6d17d3b10b22a3cce70543240a4900d13e
parent02d8ca71f98800df08754ce3d2d2e39541178f64

macos: detect SDK path and version, then pass to the linker

Since we are already detecting the path to the native SDK, if available, also fetch SDK's version and route that to the linker. The linker can then use it to correctly populate LC_BUILD_VERSION load command.

5 files changed, 87 insertions(+), 34 deletions(-)

lib/std/zig/system/darwin.zig+52-18
......@@ -2,14 +2,15 @@ const std = @import("std");
22const mem = std.mem;
33const Allocator = mem.Allocator;
44const Target = std.Target;
5const Version = std.builtin.Version;
56
67pub const macos = @import("darwin/macos.zig");
78
8/// Detect SDK path on Darwin.
9/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which result can be used to specify
10/// `--sysroot` of the compiler.
11/// The caller needs to free the resulting path slice.
12pub fn getSDKPath(allocator: *Allocator, target: Target) !?[]u8 {
9/// Detect SDK on Darwin.
10/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which fetches the path to the SDK sysroot (if any).
11/// Subsequently calls `xcrun --sdk <target_sdk> --show-sdk-version` which fetches version of the SDK.
12/// The caller needs to deinit the resulting struct.
13pub fn getDarwinSDK(allocator: *Allocator, target: Target) !?DarwinSDK {
1314 const is_simulator_abi = target.abi == .simulator;
1415 const sdk = switch (target.os.tag) {
1516 .macos => "macosx",
......@@ -18,21 +19,54 @@ pub fn getSDKPath(allocator: *Allocator, target: Target) !?[]u8 {
1819 .tvos => if (is_simulator_abi) "appletvsimulator" else "appletvos",
1920 else => return null,
2021 };
22 const path = path: {
23 const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-path" };
24 const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv });
25 defer {
26 allocator.free(result.stderr);
27 allocator.free(result.stdout);
28 }
29 if (result.stderr.len != 0 or result.term.Exited != 0) {
30 // We don't actually care if there were errors as this is best-effort check anyhow
31 // and in the worst case the user can specify the sysroot manually.
32 return null;
33 }
34 const path = try allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n"));
35 break :path path;
36 };
37 const version = version: {
38 const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-version" };
39 const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv });
40 defer {
41 allocator.free(result.stderr);
42 allocator.free(result.stdout);
43 }
44 if (result.stderr.len != 0 or result.term.Exited != 0) {
45 // We don't actually care if there were errors as this is best-effort check anyhow
46 // and in the worst case the user can specify the sysroot manually.
47 return null;
48 }
49 const raw_version = mem.trimRight(u8, result.stdout, "\r\n");
50 const version = Version.parse(raw_version) catch Version{
51 .major = 0,
52 .minor = 0,
53 };
54 break :version version;
55 };
56 return DarwinSDK{
57 .path = path,
58 .version = version,
59 };
60}
2161
22 const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-path" };
23 const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv });
24 defer {
25 allocator.free(result.stderr);
26 allocator.free(result.stdout);
27 }
28 if (result.stderr.len != 0 or result.term.Exited != 0) {
29 // We don't actually care if there were errors as this is best-effort check anyhow
30 // and in the worst case the user can specify the sysroot manually.
31 return null;
62pub const DarwinSDK = struct {
63 path: []const u8,
64 version: Version,
65
66 pub fn deinit(self: DarwinSDK, allocator: *Allocator) void {
67 allocator.free(self.path);
3268 }
33 const sysroot = try allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n"));
34 return sysroot;
35}
69};
3670
3771test "" {
3872 _ = @import("darwin/macos.zig");
src/Compilation.zig+15-7
......@@ -773,8 +773,8 @@ pub const InitOptions = struct {
773773 wasi_exec_model: ?std.builtin.WasiExecModel = null,
774774 /// (Zig compiler development) Enable dumping linker's state as JSON.
775775 enable_link_snapshots: bool = false,
776 /// (Darwin). Path to native macOS SDK if detected.
777 native_macos_sdk_path: ?[]const u8 = null,
776 /// (Darwin) Path and version of the native SDK if detected.
777 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
778778};
779779
780780fn addPackageTableToCacheHash(
......@@ -967,8 +967,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
967967 const sysroot = blk: {
968968 if (options.sysroot) |sysroot| {
969969 break :blk sysroot;
970 } else if (options.native_macos_sdk_path) |sdk_path| {
971 break :blk sdk_path;
970 } else if (options.native_darwin_sdk) |sdk| {
971 break :blk sdk.path;
972972 } else {
973973 break :blk null;
974974 }
......@@ -1055,7 +1055,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
10551055 link_libc,
10561056 options.system_lib_names.len != 0 or options.frameworks.len != 0,
10571057 options.libc_installation,
1058 options.native_macos_sdk_path != null,
1058 options.native_darwin_sdk != null,
10591059 );
10601060
10611061 const must_pie = target_util.requiresPIE(options.target);
......@@ -1492,6 +1492,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
14921492 .wasi_exec_model = wasi_exec_model,
14931493 .use_stage1 = use_stage1,
14941494 .enable_link_snapshots = options.enable_link_snapshots,
1495 .native_darwin_sdk = options.native_darwin_sdk,
14951496 });
14961497 errdefer bin_file.destroy();
14971498 comp.* = .{
......@@ -3829,7 +3830,7 @@ fn detectLibCIncludeDirs(
38293830 if (link_system_libs and is_native_abi and !target.isMinGW()) {
38303831 if (target.isDarwin()) {
38313832 return if (has_macos_sdk)
3832 // For Darwin/macOS, we are all set with getSDKPath found earlier.
3833 // For Darwin/macOS, we are all set with getDarwinSDK found earlier.
38333834 LibCDirs{
38343835 .libc_include_dir_list = &[0][]u8{},
38353836 .libc_installation = null,
......@@ -3846,7 +3847,14 @@ fn detectLibCIncludeDirs(
38463847 // default if possible.
38473848 if (target_util.canBuildLibC(target)) {
38483849 switch (target.os.tag) {
3849 .macos => return getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target),
3850 .macos => return if (has_macos_sdk)
3851 // For Darwin/macOS, we are all set with getDarwinSDK found earlier.
3852 LibCDirs{
3853 .libc_include_dir_list = &[0][]u8{},
3854 .libc_installation = null,
3855 }
3856 else
3857 getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target),
38503858 else => {
38513859 const generic_name = target_util.libCGenericName(target);
38523860 // Some architectures are handled by the same set of headers.
src/link.zig+3
......@@ -153,6 +153,9 @@ pub const Options = struct {
153153 /// (Zig compiler development) Enable dumping of linker's state as JSON.
154154 enable_link_snapshots: bool = false,
155155
156 /// (Darwin) Path and version of the native SDK if detected.
157 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
158
156159 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
157160 return if (options.use_lld) .Obj else options.output_mode;
158161 }
src/link/MachO.zig+12-4
......@@ -4077,8 +4077,16 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40774077 @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version),
40784078 @sizeOf(u64),
40794079 ));
4080 const ver = self.base.options.target.os.version_range.semver.min;
4081 const version = ver.major << 16 | ver.minor << 8 | ver.patch;
4080 const platform_version = blk: {
4081 const ver = self.base.options.target.os.version_range.semver.min;
4082 const platform_version = ver.major << 16 | ver.minor << 8;
4083 break :blk platform_version;
4084 };
4085 const sdk_version = if (self.base.options.native_darwin_sdk) |sdk| blk: {
4086 const ver = sdk.version;
4087 const sdk_version = ver.major << 16 | ver.minor << 8;
4088 break :blk sdk_version;
4089 } else platform_version;
40824090 const is_simulator_abi = self.base.options.target.abi == .simulator;
40834091 var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{
40844092 .cmd = macho.LC_BUILD_VERSION,
......@@ -4090,8 +4098,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40904098 .tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS,
40914099 else => unreachable,
40924100 },
4093 .minos = version,
4094 .sdk = version,
4101 .minos = platform_version,
4102 .sdk = sdk_version,
40954103 .ntools = 1,
40964104 });
40974105 const ld_ver = macho.build_tool_version{
src/main.zig+5-5
......@@ -663,7 +663,7 @@ fn buildOutputType(
663663 var minor_subsystem_version: ?u32 = null;
664664 var wasi_exec_model: ?std.builtin.WasiExecModel = null;
665665 var enable_link_snapshots: bool = false;
666 var native_macos_sdk_path: ?[]const u8 = null;
666 var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null;
667667
668668 var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa);
669669 defer system_libs.deinit();
......@@ -1858,11 +1858,11 @@ fn buildOutputType(
18581858 }
18591859
18601860 const has_sysroot = if (comptime builtin.target.isDarwin()) outer: {
1861 if (try std.zig.system.darwin.getSDKPath(arena, target_info.target)) |sdk_path| {
1862 native_macos_sdk_path = sdk_path;
1861 if (try std.zig.system.darwin.getDarwinSDK(arena, target_info.target)) |sdk| {
1862 native_darwin_sdk = sdk;
18631863 try clang_argv.ensureUnusedCapacity(2);
18641864 clang_argv.appendAssumeCapacity("-isysroot");
1865 clang_argv.appendAssumeCapacity(sdk_path);
1865 clang_argv.appendAssumeCapacity(sdk.path);
18661866 break :outer true;
18671867 } else break :outer false;
18681868 } else false;
......@@ -2342,7 +2342,7 @@ fn buildOutputType(
23422342 .wasi_exec_model = wasi_exec_model,
23432343 .debug_compile_errors = debug_compile_errors,
23442344 .enable_link_snapshots = enable_link_snapshots,
2345 .native_macos_sdk_path = native_macos_sdk_path,
2345 .native_darwin_sdk = native_darwin_sdk,
23462346 }) catch |err| {
23472347 fatal("unable to create compilation: {s}", .{@errorName(err)});
23482348 };