From 826179bff40fdbd8c3b11138897fcfbb3367def8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 May 2021 15:59:24 -0700 Subject: [PATCH] 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. --- build.zig | 3 +-- src/Compilation.zig | 17 ++++++++++------- src/link.zig | 1 + src/link/Elf.zig | 8 +++++--- src/main.zig | 7 +++++++ 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/build.zig b/build.zig index d3e02bba5e..39c5257fae 100644 --- a/build.zig +++ b/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"); diff --git a/src/Compilation.zig b/src/Compilation.zig index 0f04f02b7d..140e160b69 100644 --- a/src/Compilation.zig +++ b/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 { diff --git a/src/link.zig b/src/link.zig index c0f9a50b2b..b30db06148 100644 --- a/src/link.zig +++ b/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, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index b94e562eb7..0b2d800bd7 100644 --- a/src/link/Elf.zig +++ b/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 diff --git a/src/main.zig b/src/main.zig index bd57c1f14f..d435fb5ea4 100644 --- a/src/main.zig +++ b/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,