compiler: Link libunwind when linking glibc statically.

glibc's libc.a depends on the functions provided by libunwind.
This commit is contained in:
Alex Rønne Petersen 2025-05-03 06:32:15 +02:00
parent f6476e9cae
commit d2f92e1797
No known key found for this signature in database
3 changed files with 14 additions and 1 deletions

View file

@ -129,6 +129,7 @@ pub const ResolveError = error{
LldCannotIncrementallyLink, LldCannotIncrementallyLink,
LtoRequiresLld, LtoRequiresLld,
SanitizeThreadRequiresLibCpp, SanitizeThreadRequiresLibCpp,
LibCRequiresLibUnwind,
LibCppRequiresLibUnwind, LibCppRequiresLibUnwind,
OsRequiresLibC, OsRequiresLibC,
LibCppRequiresLibC, LibCppRequiresLibC,
@ -312,7 +313,7 @@ pub fn resolve(options: Options) ResolveError!Config {
break :b false; break :b false;
}; };
const link_libunwind = b: { var link_libunwind = b: {
if (link_libcpp and target_util.libCxxNeedsLibUnwind(target)) { if (link_libcpp and target_util.libCxxNeedsLibUnwind(target)) {
if (options.link_libunwind == false) return error.LibCppRequiresLibUnwind; if (options.link_libunwind == false) return error.LibCppRequiresLibUnwind;
break :b true; break :b true;
@ -379,6 +380,13 @@ pub fn resolve(options: Options) ResolveError!Config {
break :b .static; 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 import_memory = options.import_memory orelse (options.output_mode == .Obj);
const export_memory = b: { const export_memory = b: {
if (link_mode == .dynamic) { if (link_mode == .dynamic) {

View file

@ -4206,6 +4206,7 @@ fn createModule(
error.LldCannotIncrementallyLink => fatal("self-hosted backends do not support linking with LLD", .{}), error.LldCannotIncrementallyLink => fatal("self-hosted backends do not support linking with LLD", .{}),
error.LtoRequiresLld => fatal("LTO requires using 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.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.LibCppRequiresLibUnwind => fatal("libc++ requires linking libunwind", .{}),
error.OsRequiresLibC => fatal("the target OS requires using libc as the stable syscall interface", .{}), error.OsRequiresLibC => fatal("the target OS requires using libc as the stable syscall interface", .{}),
error.LibCppRequiresLibC => fatal("libc++ requires linking libc", .{}), error.LibCppRequiresLibC => fatal("libc++ requires linking libc", .{}),

View file

@ -23,6 +23,10 @@ pub fn osRequiresLibC(target: std.Target) bool {
return target.os.requiresLibC(); 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 { pub fn libCxxNeedsLibUnwind(target: std.Target) bool {
return switch (target.os.tag) { return switch (target.os.tag) {
.macos, .macos,