authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-20 17:23:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-20 17:23:44-07:00
log4e5a88b28882eda156a46ecc7f70887a7bc0b49b
tree1ccdc54fdb432ff72692e9f10f4f0640ef6869cd
parenta699d678b2c81dcf333a4f4bb84676836849a618

stage2: default dynamic libraries to be linked as needed

After this change, the default for dynamic libraries (`-l` or `--library`) is to only link them if they end up being actually used. With the Zig CLI, the new options `-needed-l` or `--needed-library` can be used to force link against a dynamic library. With `zig cc`, this behavior can be overridden with `-Wl,--no-as-needed` (and restored with `-Wl,--as-needed`). Closes #10164

7 files changed, 102 insertions(+), 47 deletions(-)

src/Cache.zig-8
...@@ -90,14 +90,6 @@ pub const HashHelper = struct {...@@ -90,14 +90,6 @@ pub const HashHelper = struct {
90 for (list_of_bytes) |bytes| hh.addBytes(bytes);90 for (list_of_bytes) |bytes| hh.addBytes(bytes);
91 }91 }
9292
93 pub fn addStringSet(hh: *HashHelper, hm: std.StringArrayHashMapUnmanaged(void)) void {
94 const keys = hm.keys();
95 hh.add(keys.len);
96 for (keys) |key| {
97 hh.addBytes(key);
98 }
99 }
100
101 /// Convert the input value into bytes and record it as a dependency of the process being cached.93 /// Convert the input value into bytes and record it as a dependency of the process being cached.
102 pub fn add(hh: *HashHelper, x: anytype) void {94 pub fn add(hh: *HashHelper, x: anytype) void {
103 switch (@TypeOf(x)) {95 switch (@TypeOf(x)) {
src/Compilation.zig+11-8
...@@ -627,6 +627,8 @@ pub const ClangPreprocessorMode = enum {...@@ -627,6 +627,8 @@ pub const ClangPreprocessorMode = enum {
627 stdout,627 stdout,
628};628};
629629
630pub const SystemLib = link.SystemLib;
631
630pub const InitOptions = struct {632pub const InitOptions = struct {
631 zig_lib_directory: Directory,633 zig_lib_directory: Directory,
632 local_cache_directory: Directory,634 local_cache_directory: Directory,
...@@ -672,7 +674,8 @@ pub const InitOptions = struct {...@@ -672,7 +674,8 @@ pub const InitOptions = struct {
672 link_objects: []const []const u8 = &[0][]const u8{},674 link_objects: []const []const u8 = &[0][]const u8{},
673 framework_dirs: []const []const u8 = &[0][]const u8{},675 framework_dirs: []const []const u8 = &[0][]const u8{},
674 frameworks: []const []const u8 = &[0][]const u8{},676 frameworks: []const []const u8 = &[0][]const u8{},
675 system_libs: []const []const u8 = &[0][]const u8{},677 system_lib_names: []const []const u8 = &.{},
678 system_lib_infos: []const SystemLib = &.{},
676 /// These correspond to the WASI libc emulated subcomponents including:679 /// These correspond to the WASI libc emulated subcomponents including:
677 /// * process clocks680 /// * process clocks
678 /// * getpid681 /// * getpid
...@@ -935,7 +938,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -935,7 +938,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
935 if (options.link_objects.len != 0 or938 if (options.link_objects.len != 0 or
936 options.c_source_files.len != 0 or939 options.c_source_files.len != 0 or
937 options.frameworks.len != 0 or940 options.frameworks.len != 0 or
938 options.system_libs.len != 0 or941 options.system_lib_names.len != 0 or
939 options.link_libc or options.link_libcpp or942 options.link_libc or options.link_libcpp or
940 link_eh_frame_hdr or943 link_eh_frame_hdr or
941 options.link_emit_relocs or944 options.link_emit_relocs or
...@@ -1003,7 +1006,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1003,7 +1006,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1003 break :dl true;1006 break :dl true;
1004 }1007 }
1005 const any_dyn_libs: bool = x: {1008 const any_dyn_libs: bool = x: {
1006 if (options.system_libs.len != 0)1009 if (options.system_lib_names.len != 0)
1007 break :x true;1010 break :x true;
1008 for (options.link_objects) |obj| {1011 for (options.link_objects) |obj| {
1009 switch (classifyFileExt(obj)) {1012 switch (classifyFileExt(obj)) {
...@@ -1050,7 +1053,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1050,7 +1053,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1050 options.target,1053 options.target,
1051 options.is_native_abi,1054 options.is_native_abi,
1052 link_libc,1055 link_libc,
1053 options.system_libs.len != 0 or options.frameworks.len != 0,1056 options.system_lib_names.len != 0 or options.frameworks.len != 0,
1054 options.libc_installation,1057 options.libc_installation,
1055 );1058 );
10561059
...@@ -1372,11 +1375,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1372,11 +1375,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1372 };1375 };
1373 };1376 };
13741377
1375 var system_libs: std.StringArrayHashMapUnmanaged(void) = .{};1378 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};
1376 errdefer system_libs.deinit(gpa);1379 errdefer system_libs.deinit(gpa);
1377 try system_libs.ensureTotalCapacity(gpa, options.system_libs.len);1380 try system_libs.ensureTotalCapacity(gpa, options.system_lib_names.len);
1378 for (options.system_libs) |lib_name| {1381 for (options.system_lib_names) |lib_name, i| {
1379 system_libs.putAssumeCapacity(lib_name, {});1382 system_libs.putAssumeCapacity(lib_name, options.system_lib_infos[i]);
1380 }1383 }
13811384
1382 const bin_file = try link.File.openPath(gpa, .{1385 const bin_file = try link.File.openPath(gpa, .{
src/link.zig+17-1
...@@ -18,6 +18,22 @@ const wasi_libc = @import("wasi_libc.zig");...@@ -18,6 +18,22 @@ const wasi_libc = @import("wasi_libc.zig");
18const Air = @import("Air.zig");18const Air = @import("Air.zig");
19const Liveness = @import("Liveness.zig");19const Liveness = @import("Liveness.zig");
2020
21pub const SystemLib = struct {
22 needed: bool = false,
23};
24
25pub fn hashAddSystemLibs(
26 hh: *Cache.HashHelper,
27 hm: std.StringArrayHashMapUnmanaged(SystemLib),
28) void {
29 const keys = hm.keys();
30 hh.add(keys.len);
31 hh.addListOfBytes(keys);
32 for (hm.values()) |value| {
33 hh.add(value.needed);
34 }
35}
36
21pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version;37pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version;
2238
23pub const Emit = struct {39pub const Emit = struct {
...@@ -121,7 +137,7 @@ pub const Options = struct {...@@ -121,7 +137,7 @@ pub const Options = struct {
121 objects: []const []const u8,137 objects: []const []const u8,
122 framework_dirs: []const []const u8,138 framework_dirs: []const []const u8,
123 frameworks: []const []const u8,139 frameworks: []const []const u8,
124 system_libs: std.StringArrayHashMapUnmanaged(void),140 system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
125 wasi_emulated_libs: []const wasi_libc.CRTFile,141 wasi_emulated_libs: []const wasi_libc.CRTFile,
126 lib_dirs: []const []const u8,142 lib_dirs: []const []const u8,
127 rpath_list: []const []const u8,143 rpath_list: []const []const u8,
src/link/Coff.zig+1-1
...@@ -940,7 +940,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -940,7 +940,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
940 }940 }
941 }941 }
942 }942 }
943 man.hash.addStringSet(self.base.options.system_libs);943 link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
944 man.hash.addOptional(self.base.options.subsystem);944 man.hash.addOptional(self.base.options.subsystem);
945 man.hash.add(self.base.options.is_test);945 man.hash.add(self.base.options.is_test);
946 man.hash.add(self.base.options.tsaware);946 man.hash.add(self.base.options.tsaware);
src/link/Elf.zig+35-7
...@@ -1345,7 +1345,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1345,7 +1345,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1345 }1345 }
1346 man.hash.addOptionalBytes(self.base.options.soname);1346 man.hash.addOptionalBytes(self.base.options.soname);
1347 man.hash.addOptional(self.base.options.version);1347 man.hash.addOptional(self.base.options.version);
1348 man.hash.addStringSet(self.base.options.system_libs);1348 link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
1349 man.hash.add(allow_shlib_undefined);1349 man.hash.add(allow_shlib_undefined);
1350 man.hash.add(self.base.options.bind_global_refs_locally);1350 man.hash.add(self.base.options.bind_global_refs_locally);
1351 man.hash.add(self.base.options.tsan);1351 man.hash.add(self.base.options.tsan);
...@@ -1550,7 +1550,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1550,7 +1550,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1550 for (self.base.options.system_libs.keys()) |link_lib| {1550 for (self.base.options.system_libs.keys()) |link_lib| {
1551 test_path.shrinkRetainingCapacity(0);1551 test_path.shrinkRetainingCapacity(0);
1552 const sep = fs.path.sep_str;1552 const sep = fs.path.sep_str;
1553 try test_path.writer().print("{s}" ++ sep ++ "lib{s}.so", .{ lib_dir_path, link_lib });1553 try test_path.writer().print("{s}" ++ sep ++ "lib{s}.so", .{
1554 lib_dir_path, link_lib,
1555 });
1554 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {1556 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
1555 error.FileNotFound => continue,1557 error.FileNotFound => continue,
1556 else => |e| return e,1558 else => |e| return e,
...@@ -1627,16 +1629,42 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1627,16 +1629,42 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1627 // Shared libraries.1629 // Shared libraries.
1628 if (is_exe_or_dyn_lib) {1630 if (is_exe_or_dyn_lib) {
1629 const system_libs = self.base.options.system_libs.keys();1631 const system_libs = self.base.options.system_libs.keys();
1630 try argv.ensureUnusedCapacity(system_libs.len);1632 const system_libs_values = self.base.options.system_libs.values();
1631 for (system_libs) |link_lib| {1633
1632 // By this time, we depend on these libs being dynamically linked libraries and not static libraries1634 // Worst-case, we need an --as-needed argument for every lib, as well
1633 // (the check for that needs to be earlier), but they could be full paths to .so files, in which1635 // as one before and one after.
1634 // case we want to avoid prepending "-l".1636 try argv.ensureUnusedCapacity(system_libs.len * 2 + 2);
1637 argv.appendAssumeCapacity("--as-needed");
1638 var as_needed = true;
1639
1640 for (system_libs) |link_lib, i| {
1641 const lib_as_needed = !system_libs_values[i].needed;
1642 switch ((@as(u2, @boolToInt(lib_as_needed)) << 1) | @boolToInt(as_needed)) {
1643 0b00, 0b11 => {},
1644 0b01 => {
1645 argv.appendAssumeCapacity("--no-as-needed");
1646 as_needed = false;
1647 },
1648 0b10 => {
1649 argv.appendAssumeCapacity("--as-needed");
1650 as_needed = true;
1651 },
1652 }
1653
1654 // By this time, we depend on these libs being dynamically linked
1655 // libraries and not static libraries (the check for that needs to be earlier),
1656 // but they could be full paths to .so files, in which case we
1657 // want to avoid prepending "-l".
1635 const ext = Compilation.classifyFileExt(link_lib);1658 const ext = Compilation.classifyFileExt(link_lib);
1636 const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{s}", .{link_lib});1659 const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{s}", .{link_lib});
1637 argv.appendAssumeCapacity(arg);1660 argv.appendAssumeCapacity(arg);
1638 }1661 }
16391662
1663 if (!as_needed) {
1664 argv.appendAssumeCapacity("--as-needed");
1665 as_needed = true;
1666 }
1667
1640 // libc++ dep1668 // libc++ dep
1641 if (self.base.options.link_libcpp) {1669 if (self.base.options.link_libcpp) {
1642 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);1670 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
src/link/MachO.zig+1-1
...@@ -471,7 +471,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -471,7 +471,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
471 if (is_dyn_lib) {471 if (is_dyn_lib) {
472 man.hash.addOptional(self.base.options.version);472 man.hash.addOptional(self.base.options.version);
473 }473 }
474 man.hash.addStringSet(self.base.options.system_libs);474 link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
475 man.hash.addOptionalBytes(self.base.options.sysroot);475 man.hash.addOptionalBytes(self.base.options.sysroot);
476476
477 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.477 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
src/main.zig+37-21
...@@ -387,7 +387,9 @@ const usage_build_generic =...@@ -387,7 +387,9 @@ const usage_build_generic =
387 \\ -ffunction-sections Places each function in a separate section387 \\ -ffunction-sections Places each function in a separate section
388 \\388 \\
389 \\Link Options:389 \\Link Options:
390 \\ -l[lib], --library [lib] Link against system library390 \\ -l[lib], --library [lib] Link against system library (only if actually used)
391 \\ -needed-l[lib], Link against system library (even if unused)
392 \\ --needed-library [lib]
391 \\ -L[d], --library-directory [d] Add a directory to the library search path393 \\ -L[d], --library-directory [d] Add a directory to the library search path
392 \\ -T[script], --script [script] Use a custom linker script394 \\ -T[script], --script [script] Use a custom linker script
393 \\ --version-script [path] Provide a version .map file395 \\ --version-script [path] Provide a version .map file
...@@ -655,7 +657,7 @@ fn buildOutputType(...@@ -655,7 +657,7 @@ fn buildOutputType(
655 var wasi_exec_model: ?std.builtin.WasiExecModel = null;657 var wasi_exec_model: ?std.builtin.WasiExecModel = null;
656 var enable_link_snapshots: bool = false;658 var enable_link_snapshots: bool = false;
657659
658 var system_libs = std.ArrayList([]const u8).init(gpa);660 var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa);
659 defer system_libs.deinit();661 defer system_libs.deinit();
660662
661 var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(gpa);663 var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(gpa);
...@@ -860,10 +862,14 @@ fn buildOutputType(...@@ -860,10 +862,14 @@ fn buildOutputType(
860 version_script = args[i];862 version_script = args[i];
861 } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {863 } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {
862 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});864 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
863 // We don't know whether this library is part of libc or libc++ until we resolve the target.865 // We don't know whether this library is part of libc or libc++ until
864 // So we simply append to the list for now.866 // we resolve the target, so we simply append to the list for now.
865 i += 1;867 i += 1;
866 try system_libs.append(args[i]);868 try system_libs.put(args[i], .{ .needed = false });
869 } else if (mem.eql(u8, arg, "--needed-library") or mem.eql(u8, arg, "-needed-l")) {
870 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
871 i += 1;
872 try system_libs.put(args[i], .{ .needed = true });
867 } else if (mem.eql(u8, arg, "-D") or873 } else if (mem.eql(u8, arg, "-D") or
868 mem.eql(u8, arg, "-isystem") or874 mem.eql(u8, arg, "-isystem") or
869 mem.eql(u8, arg, "-I") or875 mem.eql(u8, arg, "-I") or
...@@ -1164,9 +1170,11 @@ fn buildOutputType(...@@ -1164,9 +1170,11 @@ fn buildOutputType(
1164 } else if (mem.startsWith(u8, arg, "-F")) {1170 } else if (mem.startsWith(u8, arg, "-F")) {
1165 try framework_dirs.append(arg[2..]);1171 try framework_dirs.append(arg[2..]);
1166 } else if (mem.startsWith(u8, arg, "-l")) {1172 } else if (mem.startsWith(u8, arg, "-l")) {
1167 // We don't know whether this library is part of libc or libc++ until we resolve the target.1173 // We don't know whether this library is part of libc or libc++ until
1168 // So we simply append to the list for now.1174 // we resolve the target, so we simply append to the list for now.
1169 try system_libs.append(arg[2..]);1175 try system_libs.put(arg["-l".len..], .{ .needed = false });
1176 } else if (mem.startsWith(u8, arg, "-needed-l")) {
1177 try system_libs.put(arg["-needed-l".len..], .{ .needed = true });
1170 } else if (mem.startsWith(u8, arg, "-D") or1178 } else if (mem.startsWith(u8, arg, "-D") or
1171 mem.startsWith(u8, arg, "-I"))1179 mem.startsWith(u8, arg, "-I"))
1172 {1180 {
...@@ -1230,6 +1238,7 @@ fn buildOutputType(...@@ -1230,6 +1238,7 @@ fn buildOutputType(
1230 var linker_args = std.ArrayList([]const u8).init(arena);1238 var linker_args = std.ArrayList([]const u8).init(arena);
1231 var it = ClangArgIterator.init(arena, all_args);1239 var it = ClangArgIterator.init(arena, all_args);
1232 var emit_llvm = false;1240 var emit_llvm = false;
1241 var needed = false;
1233 while (it.has_next) {1242 while (it.has_next) {
1234 it.next() catch |err| {1243 it.next() catch |err| {
1235 fatal("unable to parse command line parameters: {s}", .{@errorName(err)});1244 fatal("unable to parse command line parameters: {s}", .{@errorName(err)});
...@@ -1262,9 +1271,9 @@ fn buildOutputType(...@@ -1262,9 +1271,9 @@ fn buildOutputType(
1262 },1271 },
1263 .l => {1272 .l => {
1264 // -l1273 // -l
1265 // We don't know whether this library is part of libc or libc++ until we resolve the target.1274 // We don't know whether this library is part of libc or libc++ until
1266 // So we simply append to the list for now.1275 // we resolve the target, so we simply append to the list for now.
1267 try system_libs.append(it.only_arg);1276 try system_libs.put(it.only_arg, .{ .needed = needed });
1268 },1277 },
1269 .ignore => {},1278 .ignore => {},
1270 .driver_punt => {1279 .driver_punt => {
...@@ -1302,8 +1311,13 @@ fn buildOutputType(...@@ -1302,8 +1311,13 @@ fn buildOutputType(
1302 continue;1311 continue;
1303 }1312 }
1304 }1313 }
13051314 if (mem.eql(u8, linker_arg, "--as-needed")) {
1306 try linker_args.append(linker_arg);1315 needed = false;
1316 } else if (mem.eql(u8, linker_arg, "--no-as-needed")) {
1317 needed = true;
1318 } else {
1319 try linker_args.append(linker_arg);
1320 }
1307 }1321 }
1308 },1322 },
1309 .optimize => {1323 .optimize => {
...@@ -1725,21 +1739,22 @@ fn buildOutputType(...@@ -1725,21 +1739,22 @@ fn buildOutputType(
1725 // existence via flags instead.1739 // existence via flags instead.
1726 {1740 {
1727 var i: usize = 0;1741 var i: usize = 0;
1728 while (i < system_libs.items.len) {1742 while (i < system_libs.count()) {
1729 const lib_name = system_libs.items[i];1743 const lib_name = system_libs.keys()[i];
1744
1730 if (target_util.is_libc_lib_name(target_info.target, lib_name)) {1745 if (target_util.is_libc_lib_name(target_info.target, lib_name)) {
1731 link_libc = true;1746 link_libc = true;
1732 _ = system_libs.orderedRemove(i);1747 _ = system_libs.orderedRemove(lib_name);
1733 continue;1748 continue;
1734 }1749 }
1735 if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) {1750 if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) {
1736 link_libcpp = true;1751 link_libcpp = true;
1737 _ = system_libs.orderedRemove(i);1752 _ = system_libs.orderedRemove(lib_name);
1738 continue;1753 continue;
1739 }1754 }
1740 if (mem.eql(u8, lib_name, "unwind")) {1755 if (mem.eql(u8, lib_name, "unwind")) {
1741 link_libunwind = true;1756 link_libunwind = true;
1742 _ = system_libs.orderedRemove(i);1757 _ = system_libs.orderedRemove(lib_name);
1743 continue;1758 continue;
1744 }1759 }
1745 if (std.fs.path.isAbsolute(lib_name)) {1760 if (std.fs.path.isAbsolute(lib_name)) {
...@@ -1748,7 +1763,7 @@ fn buildOutputType(...@@ -1748,7 +1763,7 @@ fn buildOutputType(
1748 if (target_info.target.os.tag == .wasi) {1763 if (target_info.target.os.tag == .wasi) {
1749 if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| {1764 if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| {
1750 try wasi_emulated_libs.append(crt_file);1765 try wasi_emulated_libs.append(crt_file);
1751 _ = system_libs.orderedRemove(i);1766 _ = system_libs.orderedRemove(lib_name);
1752 continue;1767 continue;
1753 }1768 }
1754 }1769 }
...@@ -1777,7 +1792,7 @@ fn buildOutputType(...@@ -1777,7 +1792,7 @@ fn buildOutputType(
1777 const is_darwin_on_darwin = (comptime builtin.target.isDarwin()) and cross_target.isDarwin();1792 const is_darwin_on_darwin = (comptime builtin.target.isDarwin()) and cross_target.isDarwin();
17781793
1779 if (sysroot == null and (cross_target.isNativeOs() or is_darwin_on_darwin) and1794 if (sysroot == null and (cross_target.isNativeOs() or is_darwin_on_darwin) and
1780 (system_libs.items.len != 0 or want_native_include_dirs))1795 (system_libs.count() != 0 or want_native_include_dirs))
1781 {1796 {
1782 const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| {1797 const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| {
1783 fatal("unable to detect native system paths: {s}", .{@errorName(err)});1798 fatal("unable to detect native system paths: {s}", .{@errorName(err)});
...@@ -2144,7 +2159,8 @@ fn buildOutputType(...@@ -2144,7 +2159,8 @@ fn buildOutputType(
2144 .link_objects = link_objects.items,2159 .link_objects = link_objects.items,
2145 .framework_dirs = framework_dirs.items,2160 .framework_dirs = framework_dirs.items,
2146 .frameworks = frameworks.items,2161 .frameworks = frameworks.items,
2147 .system_libs = system_libs.items,2162 .system_lib_names = system_libs.keys(),
2163 .system_lib_infos = system_libs.values(),
2148 .wasi_emulated_libs = wasi_emulated_libs.items,2164 .wasi_emulated_libs = wasi_emulated_libs.items,
2149 .link_libc = link_libc,2165 .link_libc = link_libc,
2150 .link_libcpp = link_libcpp,2166 .link_libcpp = link_libcpp,