| author | |
| committer | |
| log | 4e5a88b28882eda156a46ecc7f70887a7bc0b49b |
| tree | 1ccdc54fdb432ff72692e9f10f4f0640ef6869cd |
| parent | a699d678b2c81dcf333a4f4bb84676836849a618 |
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 #101647 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 | } |
| 92 | 92 | ||
| 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 | }; |
| 629 | 629 | ||
| 630 | pub const SystemLib = link.SystemLib; | ||
| 631 | |||
| 630 | pub const InitOptions = struct { | 632 | pub 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 clocks | 680 | /// * process clocks |
| 678 | /// * getpid | 681 | /// * 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 or | 938 | if (options.link_objects.len != 0 or |
| 936 | options.c_source_files.len != 0 or | 939 | options.c_source_files.len != 0 or |
| 937 | options.frameworks.len != 0 or | 940 | options.frameworks.len != 0 or |
| 938 | options.system_libs.len != 0 or | 941 | options.system_lib_names.len != 0 or |
| 939 | options.link_libc or options.link_libcpp or | 942 | options.link_libc or options.link_libcpp or |
| 940 | link_eh_frame_hdr or | 943 | link_eh_frame_hdr or |
| 941 | options.link_emit_relocs or | 944 | 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 | ); |
| 1056 | 1059 | ||
| ... | @@ -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 | }; |
| 1374 | 1377 | ||
| 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 | } |
| 1381 | 1384 | ||
| 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"); |
| 18 | const Air = @import("Air.zig"); | 18 | const Air = @import("Air.zig"); |
| 19 | const Liveness = @import("Liveness.zig"); | 19 | const Liveness = @import("Liveness.zig"); |
| 20 | 20 | ||
| 21 | pub const SystemLib = struct { | ||
| 22 | needed: bool = false, | ||
| 23 | }; | ||
| 24 | |||
| 25 | pub 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 | |||
| 21 | pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version; | 37 | pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version; |
| 22 | 38 | ||
| 23 | pub const Emit = struct { | 39 | pub 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 libraries | 1634 | // 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 which | 1635 | // 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 | } |
| 1639 | 1662 | ||
| 1663 | if (!as_needed) { | ||
| 1664 | argv.appendAssumeCapacity("--as-needed"); | ||
| 1665 | as_needed = true; | ||
| 1666 | } | ||
| 1667 | |||
| 1640 | // libc++ dep | 1668 | // 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); |
| 476 | 476 | ||
| 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 section | 387 | \\ -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 library | 390 | \\ -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 path | 393 | \\ -L[d], --library-directory [d] Add a directory to the library search path |
| 392 | \\ -T[script], --script [script] Use a custom linker script | 394 | \\ -T[script], --script [script] Use a custom linker script |
| 393 | \\ --version-script [path] Provide a version .map file | 395 | \\ --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; |
| 657 | 659 | ||
| 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(); |
| 660 | 662 | ||
| 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") or | 873 | } else if (mem.eql(u8, arg, "-D") or |
| 868 | mem.eql(u8, arg, "-isystem") or | 874 | mem.eql(u8, arg, "-isystem") or |
| 869 | mem.eql(u8, arg, "-I") or | 875 | 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") or | 1178 | } 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 | // -l | 1273 | // -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 | } |
| 1305 | 1314 | 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(); |
| 1778 | 1793 | ||
| 1779 | if (sysroot == null and (cross_target.isNativeOs() or is_darwin_on_darwin) and | 1794 | 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, |