authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-26 12:00:30-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-11-26 12:00:30-08:00
log7c2cc45ad87b621831ac4b8cada809c2d88cdf0d
treed831a33e04f90fb27558bce226985095ef981546
parenta2c546fea30de2caf1efb454d327e70270c07338
parente2b6dfa6087f2e63bbc03e0430b73e900c95a193
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10226 from ziglang/fix-10217

macos: improved SDK detection and linker integration with _mh_execute_header

5 files changed, 184 insertions(+), 67 deletions(-)

lib/std/zig/system/darwin.zig+71-18
...@@ -2,14 +2,34 @@ const std = @import("std");...@@ -2,14 +2,34 @@ const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const Allocator = mem.Allocator;3const Allocator = mem.Allocator;
4const Target = std.Target;4const Target = std.Target;
5const Version = std.builtin.Version;
56
6pub const macos = @import("darwin/macos.zig");7pub const macos = @import("darwin/macos.zig");
78
8/// Detect SDK path on Darwin.9/// Check if SDK is installed on Darwin without triggering CLT installation popup window.
9/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which result can be used to specify10/// Note: simply invoking `xcrun` will inevitably trigger the CLT installation popup.
10/// `--sysroot` of the compiler.11/// Therefore, we resort to the same tool used by Homebrew, namely, invoking `xcode-select --print-path`
11/// The caller needs to free the resulting path slice.12/// and checking if the status is nonzero or the returned string in nonempty.
12pub fn getSDKPath(allocator: *Allocator, target: Target) !?[]u8 {13/// https://github.com/Homebrew/brew/blob/e119bdc571dcb000305411bc1e26678b132afb98/Library/Homebrew/brew.sh#L630
14pub fn isDarwinSDKInstalled(allocator: *Allocator) bool {
15 const argv = &[_][]const u8{ "/usr/bin/xcode-select", "--print-path" };
16 const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return false;
17 defer {
18 allocator.free(result.stderr);
19 allocator.free(result.stdout);
20 }
21 if (result.stderr.len != 0 or result.term.Exited != 0) {
22 // We don't actually care if there were errors as this is best-effort check anyhow.
23 return false;
24 }
25 return result.stdout.len > 0;
26}
27
28/// Detect SDK on Darwin.
29/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which fetches the path to the SDK sysroot (if any).
30/// Subsequently calls `xcrun --sdk <target_sdk> --show-sdk-version` which fetches version of the SDK.
31/// The caller needs to deinit the resulting struct.
32pub fn getDarwinSDK(allocator: *Allocator, target: Target) ?DarwinSDK {
13 const is_simulator_abi = target.abi == .simulator;33 const is_simulator_abi = target.abi == .simulator;
14 const sdk = switch (target.os.tag) {34 const sdk = switch (target.os.tag) {
15 .macos => "macosx",35 .macos => "macosx",
...@@ -18,21 +38,54 @@ pub fn getSDKPath(allocator: *Allocator, target: Target) !?[]u8 {...@@ -18,21 +38,54 @@ pub fn getSDKPath(allocator: *Allocator, target: Target) !?[]u8 {
18 .tvos => if (is_simulator_abi) "appletvsimulator" else "appletvos",38 .tvos => if (is_simulator_abi) "appletvsimulator" else "appletvos",
19 else => return null,39 else => return null,
20 };40 };
41 const path = path: {
42 const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-path" };
43 const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
44 defer {
45 allocator.free(result.stderr);
46 allocator.free(result.stdout);
47 }
48 if (result.stderr.len != 0 or result.term.Exited != 0) {
49 // We don't actually care if there were errors as this is best-effort check anyhow
50 // and in the worst case the user can specify the sysroot manually.
51 return null;
52 }
53 const path = allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n")) catch return null;
54 break :path path;
55 };
56 const version = version: {
57 const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-version" };
58 const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
59 defer {
60 allocator.free(result.stderr);
61 allocator.free(result.stdout);
62 }
63 if (result.stderr.len != 0 or result.term.Exited != 0) {
64 // We don't actually care if there were errors as this is best-effort check anyhow
65 // and in the worst case the user can specify the sysroot manually.
66 return null;
67 }
68 const raw_version = mem.trimRight(u8, result.stdout, "\r\n");
69 const version = Version.parse(raw_version) catch Version{
70 .major = 0,
71 .minor = 0,
72 };
73 break :version version;
74 };
75 return DarwinSDK{
76 .path = path,
77 .version = version,
78 };
79}
2180
22 const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-path" };81pub const DarwinSDK = struct {
23 const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv });82 path: []const u8,
24 defer {83 version: Version,
25 allocator.free(result.stderr);84
26 allocator.free(result.stdout);85 pub fn deinit(self: DarwinSDK, allocator: *Allocator) void {
27 }86 allocator.free(self.path);
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;
32 }87 }
33 const sysroot = try allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n"));88};
34 return sysroot;
35}
3689
37test "" {90test "" {
38 _ = @import("darwin/macos.zig");91 _ = @import("darwin/macos.zig");
src/Compilation.zig+53-43
...@@ -773,6 +773,8 @@ pub const InitOptions = struct {...@@ -773,6 +773,8 @@ pub const InitOptions = struct {
773 wasi_exec_model: ?std.builtin.WasiExecModel = null,773 wasi_exec_model: ?std.builtin.WasiExecModel = null,
774 /// (Zig compiler development) Enable dumping linker's state as JSON.774 /// (Zig compiler development) Enable dumping linker's state as JSON.
775 enable_link_snapshots: bool = false,775 enable_link_snapshots: bool = false,
776 /// (Darwin) Path and version of the native SDK if detected.
777 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
776};778};
777779
778fn addPackageTableToCacheHash(780fn addPackageTableToCacheHash(
...@@ -962,18 +964,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -962,18 +964,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
962 break :blk false;964 break :blk false;
963 };965 };
964966
965 const darwin_use_system_sdk = blk: {
966 if (comptime !builtin.target.isDarwin()) break :blk false;
967 if (!options.is_native_os) break :blk false;
968 if (builtin.os.tag != .macos or !options.target.isDarwin()) break :blk false;
969 break :blk options.frameworks.len > 0 or options.framework_dirs.len > 0;
970 };
971
972 const sysroot = blk: {967 const sysroot = blk: {
973 if (options.sysroot) |sysroot| {968 if (options.sysroot) |sysroot| {
974 break :blk sysroot;969 break :blk sysroot;
975 } else if (darwin_use_system_sdk) {970 } else if (options.native_darwin_sdk) |sdk| {
976 break :blk try std.zig.system.darwin.getSDKPath(arena, options.target);971 break :blk sdk.path;
977 } else {972 } else {
978 break :blk null;973 break :blk null;
979 }974 }
...@@ -1060,6 +1055,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1060,6 +1055,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1060 link_libc,1055 link_libc,
1061 options.system_lib_names.len != 0 or options.frameworks.len != 0,1056 options.system_lib_names.len != 0 or options.frameworks.len != 0,
1062 options.libc_installation,1057 options.libc_installation,
1058 options.native_darwin_sdk != null,
1063 );1059 );
10641060
1065 const must_pie = target_util.requiresPIE(options.target);1061 const must_pie = target_util.requiresPIE(options.target);
...@@ -1496,6 +1492,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1496,6 +1492,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1496 .wasi_exec_model = wasi_exec_model,1492 .wasi_exec_model = wasi_exec_model,
1497 .use_stage1 = use_stage1,1493 .use_stage1 = use_stage1,
1498 .enable_link_snapshots = options.enable_link_snapshots,1494 .enable_link_snapshots = options.enable_link_snapshots,
1495 .native_darwin_sdk = options.native_darwin_sdk,
1499 });1496 });
1500 errdefer bin_file.destroy();1497 errdefer bin_file.destroy();
1501 comp.* = .{1498 comp.* = .{
...@@ -3776,6 +3773,37 @@ const LibCDirs = struct {...@@ -3776,6 +3773,37 @@ const LibCDirs = struct {
3776 libc_installation: ?*const LibCInstallation,3773 libc_installation: ?*const LibCInstallation,
3777};3774};
37783775
3776fn getZigShippedLibCIncludeDirsDarwin(arena: *Allocator, zig_lib_dir: []const u8, target: Target) !LibCDirs {
3777 const arch_name = @tagName(target.cpu.arch);
3778 const os_name = try std.fmt.allocPrint(arena, "{s}.{d}", .{
3779 @tagName(target.os.tag),
3780 target.os.version_range.semver.min.major,
3781 });
3782 const s = std.fs.path.sep_str;
3783 const list = try arena.alloc([]const u8, 3);
3784
3785 list[0] = try std.fmt.allocPrint(
3786 arena,
3787 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-gnu",
3788 .{ zig_lib_dir, arch_name, os_name },
3789 );
3790 list[1] = try std.fmt.allocPrint(
3791 arena,
3792 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
3793 .{ zig_lib_dir, os_name },
3794 );
3795 list[2] = try std.fmt.allocPrint(
3796 arena,
3797 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-macos-any",
3798 .{zig_lib_dir},
3799 );
3800
3801 return LibCDirs{
3802 .libc_include_dir_list = list,
3803 .libc_installation = null,
3804 };
3805}
3806
3779fn detectLibCIncludeDirs(3807fn detectLibCIncludeDirs(
3780 arena: *Allocator,3808 arena: *Allocator,
3781 zig_lib_dir: []const u8,3809 zig_lib_dir: []const u8,
...@@ -3784,6 +3812,7 @@ fn detectLibCIncludeDirs(...@@ -3784,6 +3812,7 @@ fn detectLibCIncludeDirs(
3784 link_libc: bool,3812 link_libc: bool,
3785 link_system_libs: bool,3813 link_system_libs: bool,
3786 libc_installation: ?*const LibCInstallation,3814 libc_installation: ?*const LibCInstallation,
3815 has_macos_sdk: bool,
3787) !LibCDirs {3816) !LibCDirs {
3788 if (!link_libc) {3817 if (!link_libc) {
3789 return LibCDirs{3818 return LibCDirs{
...@@ -3800,11 +3829,14 @@ fn detectLibCIncludeDirs(...@@ -3800,11 +3829,14 @@ fn detectLibCIncludeDirs(
3800 // using the system libc installation.3829 // using the system libc installation.
3801 if (link_system_libs and is_native_abi and !target.isMinGW()) {3830 if (link_system_libs and is_native_abi and !target.isMinGW()) {
3802 if (target.isDarwin()) {3831 if (target.isDarwin()) {
3803 // For Darwin/macOS, we are all set with getSDKPath found earlier.3832 return if (has_macos_sdk)
3804 return LibCDirs{3833 // For Darwin/macOS, we are all set with getDarwinSDK found earlier.
3805 .libc_include_dir_list = &[0][]u8{},3834 LibCDirs{
3806 .libc_installation = null,3835 .libc_include_dir_list = &[0][]u8{},
3807 };3836 .libc_installation = null,
3837 }
3838 else
3839 getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target);
3808 }3840 }
3809 const libc = try arena.create(LibCInstallation);3841 const libc = try arena.create(LibCInstallation);
3810 libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true });3842 libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true });
...@@ -3815,36 +3847,14 @@ fn detectLibCIncludeDirs(...@@ -3815,36 +3847,14 @@ fn detectLibCIncludeDirs(
3815 // default if possible.3847 // default if possible.
3816 if (target_util.canBuildLibC(target)) {3848 if (target_util.canBuildLibC(target)) {
3817 switch (target.os.tag) {3849 switch (target.os.tag) {
3818 .macos => {3850 .macos => return if (has_macos_sdk)
3819 const arch_name = @tagName(target.cpu.arch);3851 // For Darwin/macOS, we are all set with getDarwinSDK found earlier.
3820 const os_name = try std.fmt.allocPrint(arena, "{s}.{d}", .{3852 LibCDirs{
3821 @tagName(target.os.tag),3853 .libc_include_dir_list = &[0][]u8{},
3822 target.os.version_range.semver.min.major,
3823 });
3824 const s = std.fs.path.sep_str;
3825 const list = try arena.alloc([]const u8, 3);
3826
3827 list[0] = try std.fmt.allocPrint(
3828 arena,
3829 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-gnu",
3830 .{ zig_lib_dir, arch_name, os_name },
3831 );
3832 list[1] = try std.fmt.allocPrint(
3833 arena,
3834 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
3835 .{ zig_lib_dir, os_name },
3836 );
3837 list[2] = try std.fmt.allocPrint(
3838 arena,
3839 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-macos-any",
3840 .{zig_lib_dir},
3841 );
3842
3843 return LibCDirs{
3844 .libc_include_dir_list = list,
3845 .libc_installation = null,3854 .libc_installation = null,
3846 };3855 }
3847 },3856 else
3857 getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target),
3848 else => {3858 else => {
3849 const generic_name = target_util.libCGenericName(target);3859 const generic_name = target_util.libCGenericName(target);
3850 // Some architectures are handled by the same set of headers.3860 // Some architectures are handled by the same set of headers.
src/link.zig+3
...@@ -153,6 +153,9 @@ pub const Options = struct {...@@ -153,6 +153,9 @@ pub const Options = struct {
153 /// (Zig compiler development) Enable dumping of linker's state as JSON.153 /// (Zig compiler development) Enable dumping of linker's state as JSON.
154 enable_link_snapshots: bool = false,154 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
156 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {159 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
157 return if (options.use_lld) .Obj else options.output_mode;160 return if (options.use_lld) .Obj else options.output_mode;
158 }161 }
src/link/MachO.zig+50-4
...@@ -154,6 +154,7 @@ tentatives: std.AutoArrayHashMapUnmanaged(u32, void) = .{},...@@ -154,6 +154,7 @@ tentatives: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
154locals_free_list: std.ArrayListUnmanaged(u32) = .{},154locals_free_list: std.ArrayListUnmanaged(u32) = .{},
155globals_free_list: std.ArrayListUnmanaged(u32) = .{},155globals_free_list: std.ArrayListUnmanaged(u32) = .{},
156156
157mh_execute_header_index: ?u32 = null,
157dyld_stub_binder_index: ?u32 = null,158dyld_stub_binder_index: ?u32 = null,
158dyld_private_atom: ?*Atom = null,159dyld_private_atom: ?*Atom = null,
159stub_helper_preamble_atom: ?*Atom = null,160stub_helper_preamble_atom: ?*Atom = null,
...@@ -863,6 +864,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -863,6 +864,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
863 sect.offset = self.tlv_bss_file_offset;864 sect.offset = self.tlv_bss_file_offset;
864 }865 }
865866
867 try self.createMhExecuteHeaderAtom();
866 for (self.objects.items) |*object, object_id| {868 for (self.objects.items) |*object, object_id| {
867 if (object.analyzed) continue;869 if (object.analyzed) continue;
868 try self.resolveSymbolsInObject(@intCast(u16, object_id));870 try self.resolveSymbolsInObject(@intCast(u16, object_id));
...@@ -2725,6 +2727,42 @@ fn resolveSymbolsInDylibs(self: *MachO) !void {...@@ -2725,6 +2727,42 @@ fn resolveSymbolsInDylibs(self: *MachO) !void {
2725 }2727 }
2726}2728}
27272729
2730fn createMhExecuteHeaderAtom(self: *MachO) !void {
2731 if (self.mh_execute_header_index != null) return;
2732
2733 const match: MatchingSection = .{
2734 .seg = self.text_segment_cmd_index.?,
2735 .sect = self.text_section_index.?,
2736 };
2737 const n_strx = try self.makeString("__mh_execute_header");
2738 const local_sym_index = @intCast(u32, self.locals.items.len);
2739 var nlist = macho.nlist_64{
2740 .n_strx = n_strx,
2741 .n_type = macho.N_SECT,
2742 .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1),
2743 .n_desc = 0,
2744 .n_value = 0,
2745 };
2746 try self.locals.append(self.base.allocator, nlist);
2747
2748 nlist.n_type |= macho.N_EXT;
2749 const global_sym_index = @intCast(u32, self.globals.items.len);
2750 try self.globals.append(self.base.allocator, nlist);
2751 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
2752 .where = .global,
2753 .where_index = global_sym_index,
2754 .local_sym_index = local_sym_index,
2755 .file = null,
2756 });
2757
2758 const atom = try self.createEmptyAtom(local_sym_index, 0, 0);
2759 const sym = &self.locals.items[local_sym_index];
2760 const vaddr = try self.allocateAtom(atom, 0, 1, match);
2761 sym.n_value = vaddr;
2762 atom.dirty = false;
2763 self.mh_execute_header_index = local_sym_index;
2764}
2765
2728fn resolveDyldStubBinder(self: *MachO) !void {2766fn resolveDyldStubBinder(self: *MachO) !void {
2729 if (self.dyld_stub_binder_index != null) return;2767 if (self.dyld_stub_binder_index != null) return;
27302768
...@@ -4077,8 +4115,16 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -4077,8 +4115,16 @@ pub fn populateMissingMetadata(self: *MachO) !void {
4077 @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version),4115 @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version),
4078 @sizeOf(u64),4116 @sizeOf(u64),
4079 ));4117 ));
4080 const ver = self.base.options.target.os.version_range.semver.min;4118 const platform_version = blk: {
4081 const version = ver.major << 16 | ver.minor << 8 | ver.patch;4119 const ver = self.base.options.target.os.version_range.semver.min;
4120 const platform_version = ver.major << 16 | ver.minor << 8;
4121 break :blk platform_version;
4122 };
4123 const sdk_version = if (self.base.options.native_darwin_sdk) |sdk| blk: {
4124 const ver = sdk.version;
4125 const sdk_version = ver.major << 16 | ver.minor << 8;
4126 break :blk sdk_version;
4127 } else platform_version;
4082 const is_simulator_abi = self.base.options.target.abi == .simulator;4128 const is_simulator_abi = self.base.options.target.abi == .simulator;
4083 var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{4129 var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{
4084 .cmd = macho.LC_BUILD_VERSION,4130 .cmd = macho.LC_BUILD_VERSION,
...@@ -4090,8 +4136,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -4090,8 +4136,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
4090 .tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS,4136 .tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS,
4091 else => unreachable,4137 else => unreachable,
4092 },4138 },
4093 .minos = version,4139 .minos = platform_version,
4094 .sdk = version,4140 .sdk = sdk_version,
4095 .ntools = 1,4141 .ntools = 1,
4096 });4142 });
4097 const ld_ver = macho.build_tool_version{4143 const ld_ver = macho.build_tool_version{
src/main.zig+7-2
...@@ -663,6 +663,7 @@ fn buildOutputType(...@@ -663,6 +663,7 @@ fn buildOutputType(
663 var minor_subsystem_version: ?u32 = null;663 var minor_subsystem_version: ?u32 = null;
664 var wasi_exec_model: ?std.builtin.WasiExecModel = null;664 var wasi_exec_model: ?std.builtin.WasiExecModel = null;
665 var enable_link_snapshots: bool = false;665 var enable_link_snapshots: bool = false;
666 var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null;
666667
667 var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa);668 var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa);
668 defer system_libs.deinit();669 defer system_libs.deinit();
...@@ -1857,10 +1858,13 @@ fn buildOutputType(...@@ -1857,10 +1858,13 @@ fn buildOutputType(
1857 }1858 }
18581859
1859 const has_sysroot = if (comptime builtin.target.isDarwin()) outer: {1860 const has_sysroot = if (comptime builtin.target.isDarwin()) outer: {
1860 if (try std.zig.system.darwin.getSDKPath(arena, target_info.target)) |sdk_path| {1861 if (std.zig.system.darwin.isDarwinSDKInstalled(arena)) {
1862 const sdk = std.zig.system.darwin.getDarwinSDK(arena, target_info.target) orelse
1863 break :outer false;
1864 native_darwin_sdk = sdk;
1861 try clang_argv.ensureUnusedCapacity(2);1865 try clang_argv.ensureUnusedCapacity(2);
1862 clang_argv.appendAssumeCapacity("-isysroot");1866 clang_argv.appendAssumeCapacity("-isysroot");
1863 clang_argv.appendAssumeCapacity(sdk_path);1867 clang_argv.appendAssumeCapacity(sdk.path);
1864 break :outer true;1868 break :outer true;
1865 } else break :outer false;1869 } else break :outer false;
1866 } else false;1870 } else false;
...@@ -2340,6 +2344,7 @@ fn buildOutputType(...@@ -2340,6 +2344,7 @@ fn buildOutputType(
2340 .wasi_exec_model = wasi_exec_model,2344 .wasi_exec_model = wasi_exec_model,
2341 .debug_compile_errors = debug_compile_errors,2345 .debug_compile_errors = debug_compile_errors,
2342 .enable_link_snapshots = enable_link_snapshots,2346 .enable_link_snapshots = enable_link_snapshots,
2347 .native_darwin_sdk = native_darwin_sdk,
2343 }) catch |err| {2348 }) catch |err| {
2344 fatal("unable to create compilation: {s}", .{@errorName(err)});2349 fatal("unable to create compilation: {s}", .{@errorName(err)});
2345 };2350 };