Commit 826179bff4

Andrew Kelley <andrew@ziglang.org>
2021-05-14 00:59:24
stage2: -lunwind is handled specially
* `-lc++` now implies `-lc`. * `-lunwind` is now pulled out into a separate `link_libunwind` flag in the frontend driver code. This allows a project to request zig to provide libunwind even if the default situation that causes it to be implicitly added, is not active. * build.zig: ask for -lunwind when building the self-hosted compiler on Linux. Otherwise we get linker errors with unresolved symbols to libunwind.
1 parent 76a2597
src/link/Elf.zig
@@ -1643,9 +1643,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
             if (self.base.options.link_libcpp) {
                 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
                 try argv.append(comp.libcxx_static_lib.?.full_object_path);
-                if (target_util.libcNeedsLibUnwind(target)) {
-                    try argv.append(comp.libunwind_static_lib.?.full_object_path);
-                }
+            }
+
+            // libunwind dep
+            if (self.base.options.link_libunwind) {
+                try argv.append(comp.libunwind_static_lib.?.full_object_path);
             }
 
             // libc dep
src/Compilation.zig
@@ -544,6 +544,7 @@ pub const InitOptions = struct {
     system_libs: []const []const u8 = &[0][]const u8{},
     link_libc: bool = false,
     link_libcpp: bool = false,
+    link_libunwind: bool = false,
     want_pic: ?bool = null,
     /// This means that if the output mode is an executable it will be a
     /// Position Independent Executable. If the output mode is not an
@@ -791,8 +792,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
         };
 
         const tsan = options.want_tsan orelse false;
+        // TSAN is implemented in C++ so it requires linking libc++.
+        const link_libcpp = options.link_libcpp or tsan;
+        const link_libc = link_libcpp or options.link_libc or
+            target_util.osRequiresLibC(options.target);
 
-        const link_libc = options.link_libc or target_util.osRequiresLibC(options.target) or tsan;
+        const link_libunwind = options.link_libunwind or
+            (link_libcpp and target_util.libcNeedsLibUnwind(options.target));
 
         const must_dynamic_link = dl: {
             if (target_util.cannotDynamicLink(options.target))
@@ -878,9 +884,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             break :pic explicit;
         } else pie or must_pic;
 
-        // TSAN is implemented in C++ so it requires linking libc++.
-        const link_libcpp = options.link_libcpp or tsan;
-
         // Make a decision on whether to use Clang for translate-c and compiling C files.
         const use_clang = if (options.use_clang) |explicit| explicit else blk: {
             if (build_options.have_llvm) {
@@ -973,6 +976,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
         cache.hash.add(strip);
         cache.hash.add(link_libc);
         cache.hash.add(link_libcpp);
+        cache.hash.add(link_libunwind);
         cache.hash.add(options.output_mode);
         cache.hash.add(options.machine_code_model);
         cache.hash.addOptionalEmitLoc(options.emit_bin);
@@ -1157,6 +1161,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             .system_linker_hack = darwin_options.system_linker_hack,
             .link_libc = link_libc,
             .link_libcpp = link_libcpp,
+            .link_libunwind = link_libunwind,
             .objects = options.link_objects,
             .frameworks = options.frameworks,
             .framework_dirs = options.framework_dirs,
@@ -3022,9 +3027,7 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
         .Lib => comp.bin_file.options.link_mode == .Dynamic,
         .Exe => true,
     };
-    return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and
-        comp.bin_file.options.link_libcpp and
-        target_util.libcNeedsLibUnwind(comp.getTarget());
+    return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind;
 }
 
 fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void {
src/link.zig
@@ -63,6 +63,7 @@ pub const Options = struct {
     system_linker_hack: bool,
     link_libc: bool,
     link_libcpp: bool,
+    link_libunwind: bool,
     function_sections: bool,
     eh_frame_hdr: bool,
     emit_relocs: bool,
src/main.zig
@@ -520,6 +520,7 @@ fn buildOutputType(
     var ensure_libcpp_on_non_freestanding = false;
     var link_libc = false;
     var link_libcpp = false;
+    var link_libunwind = false;
     var want_native_include_dirs = false;
     var enable_cache: ?bool = null;
     var want_pic: ?bool = null;
@@ -1532,6 +1533,11 @@ fn buildOutputType(
                 _ = system_libs.orderedRemove(i);
                 continue;
             }
+            if (mem.eql(u8, lib_name, "unwind")) {
+                link_libunwind = true;
+                _ = system_libs.orderedRemove(i);
+                continue;
+            }
             if (std.fs.path.isAbsolute(lib_name)) {
                 fatal("cannot use absolute path as a system library: {s}", .{lib_name});
             }
@@ -1847,6 +1853,7 @@ fn buildOutputType(
         .system_libs = system_libs.items,
         .link_libc = link_libc,
         .link_libcpp = link_libcpp,
+        .link_libunwind = link_libunwind,
         .want_pic = want_pic,
         .want_pie = want_pie,
         .want_lto = want_lto,
build.zig
@@ -397,8 +397,7 @@ fn addCmakeCfgOptionsToExe(
             },
             else => |e| return e,
         };
-
-        exe.linkSystemLibrary("pthread");
+        exe.linkSystemLibrary("unwind");
     } else if (exe.target.isFreeBSD()) {
         try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes);
         exe.linkSystemLibrary("pthread");