Commit d2f92e1797

Alex Rønne Petersen <alex@alexrp.com>
2025-05-03 06:32:15
compiler: Link libunwind when linking glibc statically.
glibc's libc.a depends on the functions provided by libunwind.
1 parent f6476e9
Changed files (3)
src/Compilation/Config.zig
@@ -129,6 +129,7 @@ pub const ResolveError = error{
     LldCannotIncrementallyLink,
     LtoRequiresLld,
     SanitizeThreadRequiresLibCpp,
+    LibCRequiresLibUnwind,
     LibCppRequiresLibUnwind,
     OsRequiresLibC,
     LibCppRequiresLibC,
@@ -312,7 +313,7 @@ pub fn resolve(options: Options) ResolveError!Config {
         break :b false;
     };
 
-    const link_libunwind = b: {
+    var link_libunwind = b: {
         if (link_libcpp and target_util.libCxxNeedsLibUnwind(target)) {
             if (options.link_libunwind == false) return error.LibCppRequiresLibUnwind;
             break :b true;
@@ -379,6 +380,13 @@ pub fn resolve(options: Options) ResolveError!Config {
         break :b .static;
     };
 
+    // This is done here to avoid excessive duplicated logic due to the complex dependencies between these options.
+    if (options.output_mode == .Exe and link_libc and target_util.libCNeedsLibUnwind(target, link_mode)) {
+        if (options.link_libunwind == false) return error.LibCRequiresLibUnwind;
+
+        link_libunwind = true;
+    }
+
     const import_memory = options.import_memory orelse (options.output_mode == .Obj);
     const export_memory = b: {
         if (link_mode == .dynamic) {
src/main.zig
@@ -4206,6 +4206,7 @@ fn createModule(
             error.LldCannotIncrementallyLink => fatal("self-hosted backends do not support linking with LLD", .{}),
             error.LtoRequiresLld => fatal("LTO requires using LLD", .{}),
             error.SanitizeThreadRequiresLibCpp => fatal("thread sanitization is (for now) implemented in C++, so it requires linking libc++", .{}),
+            error.LibCRequiresLibUnwind => fatal("libc of the specified target requires linking libunwind", .{}),
             error.LibCppRequiresLibUnwind => fatal("libc++ requires linking libunwind", .{}),
             error.OsRequiresLibC => fatal("the target OS requires using libc as the stable syscall interface", .{}),
             error.LibCppRequiresLibC => fatal("libc++ requires linking libc", .{}),
src/target.zig
@@ -23,6 +23,10 @@ pub fn osRequiresLibC(target: std.Target) bool {
     return target.os.requiresLibC();
 }
 
+pub fn libCNeedsLibUnwind(target: std.Target, link_mode: std.builtin.LinkMode) bool {
+    return target.isGnuLibC() and link_mode == .static;
+}
+
 pub fn libCxxNeedsLibUnwind(target: std.Target) bool {
     return switch (target.os.tag) {
         .macos,