authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-23 13:25:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-23 13:25:10-07:00
log88d1258e08e668e620d5f8f4681315e555acbcd2
tree930e8dabe93e60af9fc4f0e54c17e07db2672aa1
parentacec06cfaf9a82ec8037a23993ff36fa72eb6e82

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.

3 files changed, 27 insertions(+), 14 deletions(-)

src/Compilation.zig+1-1
...@@ -962,7 +962,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -962,7 +962,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
962 const tsan = options.want_tsan orelse false;962 const tsan = options.want_tsan orelse false;
963 // TSAN is implemented in C++ so it requires linking libc++.963 // TSAN is implemented in C++ so it requires linking libc++.
964 const link_libcpp = options.link_libcpp or tsan;964 const link_libcpp = options.link_libcpp or tsan;
965 const link_libc = link_libcpp or options.link_libc or965 const link_libc = link_libcpp or options.link_libc or options.link_libunwind or
966 target_util.osRequiresLibC(options.target);966 target_util.osRequiresLibC(options.target);
967967
968 const link_libunwind = options.link_libunwind or968 const link_libunwind = options.link_libunwind or
src/main.zig+14-9
...@@ -2048,19 +2048,24 @@ fn buildOutputType(...@@ -2048,19 +2048,24 @@ fn buildOutputType(
2048 system_libs.orderedRemoveAt(i);2048 system_libs.orderedRemoveAt(i);
2049 continue;2049 continue;
2050 }2050 }
2051 if (mem.eql(u8, lib_name, "unwind")) {2051 switch (target_util.classifyCompilerRtLibName(target_info.target, lib_name)) {
2052 link_libunwind = true;2052 .none => {},
2053 system_libs.orderedRemoveAt(i);2053 .only_libunwind, .both => {
2054 continue;2054 link_libunwind = true;
2055 }2055 system_libs.orderedRemoveAt(i);
2056 if (target_util.is_compiler_rt_lib_name(target_info.target, lib_name)) {2056 continue;
2057 std.log.warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name});2057 },
2058 system_libs.orderedRemoveAt(i);2058 .only_compiler_rt => {
2059 continue;2059 std.log.warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name});
2060 system_libs.orderedRemoveAt(i);
2061 continue;
2062 },
2060 }2063 }
2064
2061 if (std.fs.path.isAbsolute(lib_name)) {2065 if (std.fs.path.isAbsolute(lib_name)) {
2062 fatal("cannot use absolute path as a system library: {s}", .{lib_name});2066 fatal("cannot use absolute path as a system library: {s}", .{lib_name});
2063 }2067 }
2068
2064 if (target_info.target.os.tag == .wasi) {2069 if (target_info.target.os.tag == .wasi) {
2065 if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| {2070 if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| {
2066 try wasi_emulated_libs.append(crt_file);2071 try wasi_emulated_libs.append(crt_file);
src/target.zig+12-4
...@@ -427,14 +427,22 @@ pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool {...@@ -427,14 +427,22 @@ pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool {
427 eqlIgnoreCase(ignore_case, name, "c++abi");427 eqlIgnoreCase(ignore_case, name, "c++abi");
428}428}
429429
430pub fn is_compiler_rt_lib_name(target: std.Target, name: []const u8) bool {430pub const CompilerRtClassification = enum { none, only_compiler_rt, only_libunwind, both };
431
432pub fn classifyCompilerRtLibName(target: std.Target, name: []const u8) CompilerRtClassification {
431 if (target.abi.isGnu() and std.mem.eql(u8, name, "gcc_s")) {433 if (target.abi.isGnu() and std.mem.eql(u8, name, "gcc_s")) {
432 return true;434 // libgcc_s includes exception handling functions, so if linking this library
435 // is requested, zig needs to instead link libunwind. Otherwise we end up with
436 // the linker unable to find `_Unwind_RaiseException` and other related symbols.
437 return .both;
433 }438 }
434 if (std.mem.eql(u8, name, "compiler_rt")) {439 if (std.mem.eql(u8, name, "compiler_rt")) {
435 return true;440 return .only_compiler_rt;
436 }441 }
437 return false;442 if (std.mem.eql(u8, name, "unwind")) {
443 return .only_libunwind;
444 }
445 return .none;
438}446}
439447
440pub fn hasDebugInfo(target: std.Target) bool {448pub fn hasDebugInfo(target: std.Target) bool {