diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-11-20 17:23:44 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-11-20 17:23:44 -0700 |
| commit | 4e5a88b28882eda156a46ecc7f70887a7bc0b49b (patch) | |
| tree | 1ccdc54fdb432ff72692e9f10f4f0640ef6869cd /src/main.zig | |
| parent | a699d678b2c81dcf333a4f4bb84676836849a618 (diff) | |
| download | zig-4e5a88b28882eda156a46ecc7f70887a7bc0b49b.tar.gz zig-4e5a88b28882eda156a46ecc7f70887a7bc0b49b.zip | |
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
Diffstat (limited to 'src/main.zig')
| -rw-r--r-- | src/main.zig | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/src/main.zig b/src/main.zig index f5ab7f7368..57193022e5 100644 --- a/src/main.zig +++ b/src/main.zig @@ -387,7 +387,9 @@ const usage_build_generic = \\ -ffunction-sections Places each function in a separate section \\ \\Link Options: - \\ -l[lib], --library [lib] Link against system library + \\ -l[lib], --library [lib] Link against system library (only if actually used) + \\ -needed-l[lib], Link against system library (even if unused) + \\ --needed-library [lib] \\ -L[d], --library-directory [d] Add a directory to the library search path \\ -T[script], --script [script] Use a custom linker script \\ --version-script [path] Provide a version .map file @@ -655,7 +657,7 @@ fn buildOutputType( var wasi_exec_model: ?std.builtin.WasiExecModel = null; var enable_link_snapshots: bool = false; - var system_libs = std.ArrayList([]const u8).init(gpa); + var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa); defer system_libs.deinit(); var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(gpa); @@ -860,10 +862,14 @@ fn buildOutputType( version_script = args[i]; } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - // We don't know whether this library is part of libc or libc++ until we resolve the target. - // So we simply append to the list for now. + // We don't know whether this library is part of libc or libc++ until + // we resolve the target, so we simply append to the list for now. i += 1; - try system_libs.append(args[i]); + try system_libs.put(args[i], .{ .needed = false }); + } else if (mem.eql(u8, arg, "--needed-library") or mem.eql(u8, arg, "-needed-l")) { + if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); + i += 1; + try system_libs.put(args[i], .{ .needed = true }); } else if (mem.eql(u8, arg, "-D") or mem.eql(u8, arg, "-isystem") or mem.eql(u8, arg, "-I") or @@ -1164,9 +1170,11 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "-F")) { try framework_dirs.append(arg[2..]); } else if (mem.startsWith(u8, arg, "-l")) { - // We don't know whether this library is part of libc or libc++ until we resolve the target. - // So we simply append to the list for now. - try system_libs.append(arg[2..]); + // We don't know whether this library is part of libc or libc++ until + // we resolve the target, so we simply append to the list for now. + try system_libs.put(arg["-l".len..], .{ .needed = false }); + } else if (mem.startsWith(u8, arg, "-needed-l")) { + try system_libs.put(arg["-needed-l".len..], .{ .needed = true }); } else if (mem.startsWith(u8, arg, "-D") or mem.startsWith(u8, arg, "-I")) { @@ -1230,6 +1238,7 @@ fn buildOutputType( var linker_args = std.ArrayList([]const u8).init(arena); var it = ClangArgIterator.init(arena, all_args); var emit_llvm = false; + var needed = false; while (it.has_next) { it.next() catch |err| { fatal("unable to parse command line parameters: {s}", .{@errorName(err)}); @@ -1262,9 +1271,9 @@ fn buildOutputType( }, .l => { // -l - // We don't know whether this library is part of libc or libc++ until we resolve the target. - // So we simply append to the list for now. - try system_libs.append(it.only_arg); + // We don't know whether this library is part of libc or libc++ until + // we resolve the target, so we simply append to the list for now. + try system_libs.put(it.only_arg, .{ .needed = needed }); }, .ignore => {}, .driver_punt => { @@ -1302,8 +1311,13 @@ fn buildOutputType( continue; } } - - try linker_args.append(linker_arg); + if (mem.eql(u8, linker_arg, "--as-needed")) { + needed = false; + } else if (mem.eql(u8, linker_arg, "--no-as-needed")) { + needed = true; + } else { + try linker_args.append(linker_arg); + } } }, .optimize => { @@ -1725,21 +1739,22 @@ fn buildOutputType( // existence via flags instead. { var i: usize = 0; - while (i < system_libs.items.len) { - const lib_name = system_libs.items[i]; + while (i < system_libs.count()) { + const lib_name = system_libs.keys()[i]; + if (target_util.is_libc_lib_name(target_info.target, lib_name)) { link_libc = true; - _ = system_libs.orderedRemove(i); + _ = system_libs.orderedRemove(lib_name); continue; } if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) { link_libcpp = true; - _ = system_libs.orderedRemove(i); + _ = system_libs.orderedRemove(lib_name); continue; } if (mem.eql(u8, lib_name, "unwind")) { link_libunwind = true; - _ = system_libs.orderedRemove(i); + _ = system_libs.orderedRemove(lib_name); continue; } if (std.fs.path.isAbsolute(lib_name)) { @@ -1748,7 +1763,7 @@ fn buildOutputType( if (target_info.target.os.tag == .wasi) { if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { try wasi_emulated_libs.append(crt_file); - _ = system_libs.orderedRemove(i); + _ = system_libs.orderedRemove(lib_name); continue; } } @@ -1777,7 +1792,7 @@ fn buildOutputType( const is_darwin_on_darwin = (comptime builtin.target.isDarwin()) and cross_target.isDarwin(); if (sysroot == null and (cross_target.isNativeOs() or is_darwin_on_darwin) and - (system_libs.items.len != 0 or want_native_include_dirs)) + (system_libs.count() != 0 or want_native_include_dirs)) { const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { fatal("unable to detect native system paths: {s}", .{@errorName(err)}); @@ -2144,7 +2159,8 @@ fn buildOutputType( .link_objects = link_objects.items, .framework_dirs = framework_dirs.items, .frameworks = frameworks.items, - .system_libs = system_libs.items, + .system_lib_names = system_libs.keys(), + .system_lib_infos = system_libs.values(), .wasi_emulated_libs = wasi_emulated_libs.items, .link_libc = link_libc, .link_libcpp = link_libcpp, |
