From 88d1258e08e668e620d5f8f4681315e555acbcd2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 23 Feb 2022 13:25:10 -0700 Subject: [PATCH] stage2: make -lgcc_s additionally link libunwind Previously, Zig ignored -lgcc_s with a warning that this dependency is redundant because it is satisfied by compiler-rt. However, sfackler pointed out that it also provides exception handling functions. So if Zig sees -lgcc_s on the linker line, it needs to fulfill this dependency with libunwind. I also made link_libc inferred to be on if libunwind is linked since libunwind depends on libc. --- src/Compilation.zig | 2 +- src/main.zig | 23 ++++++++++++++--------- src/target.zig | 16 ++++++++++++---- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 7e31592cb9..b2ac9b249c 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -962,7 +962,7 @@ 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 + const link_libc = link_libcpp or options.link_libc or options.link_libunwind or target_util.osRequiresLibC(options.target); const link_libunwind = options.link_libunwind or diff --git a/src/main.zig b/src/main.zig index 32275c4cf3..ff78d16803 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2048,19 +2048,24 @@ fn buildOutputType( system_libs.orderedRemoveAt(i); continue; } - if (mem.eql(u8, lib_name, "unwind")) { - link_libunwind = true; - system_libs.orderedRemoveAt(i); - continue; - } - if (target_util.is_compiler_rt_lib_name(target_info.target, lib_name)) { - std.log.warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name}); - system_libs.orderedRemoveAt(i); - continue; + switch (target_util.classifyCompilerRtLibName(target_info.target, lib_name)) { + .none => {}, + .only_libunwind, .both => { + link_libunwind = true; + system_libs.orderedRemoveAt(i); + continue; + }, + .only_compiler_rt => { + std.log.warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name}); + system_libs.orderedRemoveAt(i); + continue; + }, } + if (std.fs.path.isAbsolute(lib_name)) { fatal("cannot use absolute path as a system library: {s}", .{lib_name}); } + if (target_info.target.os.tag == .wasi) { if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { try wasi_emulated_libs.append(crt_file); diff --git a/src/target.zig b/src/target.zig index 63bd1db0b5..aec37b6394 100644 --- a/src/target.zig +++ b/src/target.zig @@ -427,14 +427,22 @@ pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool { eqlIgnoreCase(ignore_case, name, "c++abi"); } -pub fn is_compiler_rt_lib_name(target: std.Target, name: []const u8) bool { +pub const CompilerRtClassification = enum { none, only_compiler_rt, only_libunwind, both }; + +pub fn classifyCompilerRtLibName(target: std.Target, name: []const u8) CompilerRtClassification { if (target.abi.isGnu() and std.mem.eql(u8, name, "gcc_s")) { - return true; + // libgcc_s includes exception handling functions, so if linking this library + // is requested, zig needs to instead link libunwind. Otherwise we end up with + // the linker unable to find `_Unwind_RaiseException` and other related symbols. + return .both; } if (std.mem.eql(u8, name, "compiler_rt")) { - return true; + return .only_compiler_rt; } - return false; + if (std.mem.eql(u8, name, "unwind")) { + return .only_libunwind; + } + return .none; } pub fn hasDebugInfo(target: std.Target) bool {