std.os: add APIs to determine whether Zig std requires libc for a target

This is distinct from the question of whether the target formally considers libc
to be the only stable syscall interface; for example, FreeBSD and NetBSD have
stable syscalls, but we don't yet have syscall layers for them in std.os.
This commit is contained in:
Alex Rønne Petersen
2026-04-14 14:08:32 +02:00
parent adb1f3efc2
commit 5464392e11
3 changed files with 43 additions and 14 deletions
+41
View File
@@ -1,4 +1,5 @@
const builtin = @import("builtin"); const builtin = @import("builtin");
const std = @import("std.zig");
const native_os = builtin.os.tag; const native_os = builtin.os.tag;
pub const linux = @import("os/linux.zig"); pub const linux = @import("os/linux.zig");
@@ -8,6 +9,46 @@ pub const wasi = @import("os/wasi.zig");
pub const emscripten = @import("os/emscripten.zig"); pub const emscripten = @import("os/emscripten.zig");
pub const windows = @import("os/windows.zig"); pub const windows = @import("os/windows.zig");
/// Returns whether the Zig standard library requires libc in order to interface
/// with the operating system on the given target.
pub fn targetRequiresLibC(target: *const std.Target) bool {
if (target.requiresLibC()) return true;
return switch (target.os.tag) {
.linux => switch (target.cpu.arch) {
// https://codeberg.org/ziglang/zig/issues/30940
.alpha,
// https://codeberg.org/ziglang/zig/issues/30942
.csky,
// https://codeberg.org/ziglang/zig/issues/30943
.hppa,
.hppa64,
// https://codeberg.org/ziglang/zig/issues/30944
.microblaze,
.microblazeel,
// https://codeberg.org/ziglang/zig/issues/30946
.sh,
.sheb,
// https://codeberg.org/ziglang/zig/issues/30945
.sparc,
// https://codeberg.org/ziglang/zig/issues/30947
.xtensa,
.xtensaeb,
=> true,
else => false,
},
.freebsd => true, // https://codeberg.org/ziglang/zig/issues/30981
.netbsd => true, // https://codeberg.org/ziglang/zig/issues/30980
.openbsd => true, // https://codeberg.org/ziglang/zig/issues/30982
else => false,
};
}
/// Returns whether the Zig standard library requires libc in order to interface
/// with the operating system on the current target.
pub fn requiresLibC() bool {
return targetRequiresLibC(&builtin.target);
}
test { test {
_ = linux; _ = linux;
if (native_os == .uefi) _ = uefi; if (native_os == .uefi) _ = uefi;
+1 -10
View File
@@ -234,19 +234,10 @@ pub fn resolve(options: Options) ResolveError!Config {
break :b true; break :b true;
} }
if (options.link_libc) |x| break :b x; if (options.link_libc) |x| break :b x;
switch (target.os.tag) {
// These targets don't require libc, but we don't yet have a syscall layer for them,
// so we default to linking libc for now.
.freebsd,
.netbsd,
.openbsd,
=> break :b true,
else => {},
}
if (options.ensure_libc_on_non_freestanding and target.os.tag != .freestanding) if (options.ensure_libc_on_non_freestanding and target.os.tag != .freestanding)
break :b true; break :b true;
break :b target.requiresLibC(); break :b std.os.targetRequiresLibC(target);
}; };
const link_mode = b: { const link_mode = b: {
+1 -4
View File
@@ -58,10 +58,7 @@ fn addCaseTarget(
.fuchsia => false, .fuchsia => false,
else => true, else => true,
}; };
const both_libc = switch (target.result.os.tag) { const both_libc = !std.os.targetRequiresLibC(&target.result);
.freebsd, .netbsd, .openbsd => false,
else => !target.result.requiresLibC(),
};
// See `std.debug.StackIterator.fp_usability` logic. // See `std.debug.StackIterator.fp_usability` logic.
const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.result.cpu.arch) { const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.result.cpu.arch) {