@@ -387,7 +387,9 @@ const usage_build_generic =
387
387
\\ -ffunction-sections Places each function in a separate section
388
388
\\
389
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
393
\\ -L[d], --library-directory [d] Add a directory to the library search path
392
394
\\ -T[script], --script [script] Use a custom linker script
393
395
\\ --version-script [path] Provide a version .map file
@@ -655,7 +657,7 @@ fn buildOutputType(
655
657
var wasi_exec_model : ? std.builtin.WasiExecModel = null ;
656
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
661
defer system_libs .deinit ();
660
662
661
663
var wasi_emulated_libs = std .ArrayList (wasi_libc .CRTFile ).init (gpa );
@@ -860,10 +862,14 @@ fn buildOutputType(
860
862
version_script = args [i ];
861
863
} else if (mem .eql (u8 , arg , "--library" ) or mem .eql (u8 , arg , "-l" )) {
862
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.
864
- // So we simply append to the list for now.
865
+ // We don't know whether this library is part of libc or libc++ until
866
+ // we resolve the target, so we simply append to the list for now.
865
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
873
} else if (mem .eql (u8 , arg , "-D" ) or
868
874
mem .eql (u8 , arg , "-isystem" ) or
869
875
mem .eql (u8 , arg , "-I" ) or
@@ -1164,9 +1170,11 @@ fn buildOutputType(
1164
1170
} else if (mem .startsWith (u8 , arg , "-F" )) {
1165
1171
try framework_dirs .append (arg [2.. ]);
1166
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.
1168
- // So we simply append to the list for now.
1169
- try system_libs .append (arg [2.. ]);
1173
+ // We don't know whether this library is part of libc or libc++ until
1174
+ // we resolve the target, so we simply append to the list for now.
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
1178
} else if (mem .startsWith (u8 , arg , "-D" ) or
1171
1179
mem .startsWith (u8 , arg , "-I" ))
1172
1180
{
@@ -1230,6 +1238,7 @@ fn buildOutputType(
1230
1238
var linker_args = std .ArrayList ([]const u8 ).init (arena );
1231
1239
var it = ClangArgIterator .init (arena , all_args );
1232
1240
var emit_llvm = false ;
1241
+ var needed = false ;
1233
1242
while (it .has_next ) {
1234
1243
it .next () catch | err | {
1235
1244
fatal ("unable to parse command line parameters: {s}" , .{@errorName (err )});
@@ -1262,9 +1271,9 @@ fn buildOutputType(
1262
1271
},
1263
1272
.l = > {
1264
1273
// -l
1265
- // We don't know whether this library is part of libc or libc++ until we resolve the target.
1266
- // So we simply append to the list for now.
1267
- try system_libs .append (it .only_arg );
1274
+ // We don't know whether this library is part of libc or libc++ until
1275
+ // we resolve the target, so we simply append to the list for now.
1276
+ try system_libs .put (it .only_arg , .{ . needed = needed } );
1268
1277
},
1269
1278
.ignore = > {},
1270
1279
.driver_punt = > {
@@ -1302,8 +1311,13 @@ fn buildOutputType(
1302
1311
continue ;
1303
1312
}
1304
1313
}
1305
-
1306
- try linker_args .append (linker_arg );
1314
+ if (mem .eql (u8 , linker_arg , "--as-needed" )) {
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
1323
.optimize = > {
@@ -1725,21 +1739,22 @@ fn buildOutputType(
1725
1739
// existence via flags instead.
1726
1740
{
1727
1741
var i : usize = 0 ;
1728
- while (i < system_libs .items .len ) {
1729
- const lib_name = system_libs .items [i ];
1742
+ while (i < system_libs .count ()) {
1743
+ const lib_name = system_libs .keys ()[i ];
1744
+
1730
1745
if (target_util .is_libc_lib_name (target_info .target , lib_name )) {
1731
1746
link_libc = true ;
1732
- _ = system_libs .orderedRemove (i );
1747
+ _ = system_libs .orderedRemove (lib_name );
1733
1748
continue ;
1734
1749
}
1735
1750
if (target_util .is_libcpp_lib_name (target_info .target , lib_name )) {
1736
1751
link_libcpp = true ;
1737
- _ = system_libs .orderedRemove (i );
1752
+ _ = system_libs .orderedRemove (lib_name );
1738
1753
continue ;
1739
1754
}
1740
1755
if (mem .eql (u8 , lib_name , "unwind" )) {
1741
1756
link_libunwind = true ;
1742
- _ = system_libs .orderedRemove (i );
1757
+ _ = system_libs .orderedRemove (lib_name );
1743
1758
continue ;
1744
1759
}
1745
1760
if (std .fs .path .isAbsolute (lib_name )) {
@@ -1748,7 +1763,7 @@ fn buildOutputType(
1748
1763
if (target_info .target .os .tag == .wasi ) {
1749
1764
if (wasi_libc .getEmulatedLibCRTFile (lib_name )) | crt_file | {
1750
1765
try wasi_emulated_libs .append (crt_file );
1751
- _ = system_libs .orderedRemove (i );
1766
+ _ = system_libs .orderedRemove (lib_name );
1752
1767
continue ;
1753
1768
}
1754
1769
}
@@ -1777,7 +1792,7 @@ fn buildOutputType(
1777
1792
const is_darwin_on_darwin = (comptime builtin .target .isDarwin ()) and cross_target .isDarwin ();
1778
1793
1779
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
1797
const paths = std .zig .system .NativePaths .detect (arena , target_info ) catch | err | {
1783
1798
fatal ("unable to detect native system paths: {s}" , .{@errorName (err )});
@@ -2144,7 +2159,8 @@ fn buildOutputType(
2144
2159
.link_objects = link_objects .items ,
2145
2160
.framework_dirs = framework_dirs .items ,
2146
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
2164
.wasi_emulated_libs = wasi_emulated_libs .items ,
2149
2165
.link_libc = link_libc ,
2150
2166
.link_libcpp = link_libcpp ,
0 commit comments