authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-14 14:08:32+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-17 12:07:57+02:00
log5464392e116b590cc9c2b662e967bc544b7d0a64
tree962fa999dd3b447e7aeb587ba1850aa39060fe92
parentadb1f3efc21adad67fe2638c889178401ca602a1
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

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.

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

lib/std/os.zig+41
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std.zig");
2const native_os = builtin.os.tag;3const native_os = builtin.os.tag;
34
4pub const linux = @import("os/linux.zig");5pub const linux = @import("os/linux.zig");
...@@ -8,6 +9,46 @@ pub const wasi = @import("os/wasi.zig");...@@ -8,6 +9,46 @@ pub const wasi = @import("os/wasi.zig");
8pub const emscripten = @import("os/emscripten.zig");9pub const emscripten = @import("os/emscripten.zig");
9pub const windows = @import("os/windows.zig");10pub const windows = @import("os/windows.zig");
1011
12/// Returns whether the Zig standard library requires libc in order to interface
13/// with the operating system on the given target.
14pub fn targetRequiresLibC(target: *const std.Target) bool {
15 if (target.requiresLibC()) return true;
16 return switch (target.os.tag) {
17 .linux => switch (target.cpu.arch) {
18 // https://codeberg.org/ziglang/zig/issues/30940
19 .alpha,
20 // https://codeberg.org/ziglang/zig/issues/30942
21 .csky,
22 // https://codeberg.org/ziglang/zig/issues/30943
23 .hppa,
24 .hppa64,
25 // https://codeberg.org/ziglang/zig/issues/30944
26 .microblaze,
27 .microblazeel,
28 // https://codeberg.org/ziglang/zig/issues/30946
29 .sh,
30 .sheb,
31 // https://codeberg.org/ziglang/zig/issues/30945
32 .sparc,
33 // https://codeberg.org/ziglang/zig/issues/30947
34 .xtensa,
35 .xtensaeb,
36 => true,
37 else => false,
38 },
39 .freebsd => true, // https://codeberg.org/ziglang/zig/issues/30981
40 .netbsd => true, // https://codeberg.org/ziglang/zig/issues/30980
41 .openbsd => true, // https://codeberg.org/ziglang/zig/issues/30982
42 else => false,
43 };
44}
45
46/// Returns whether the Zig standard library requires libc in order to interface
47/// with the operating system on the current target.
48pub fn requiresLibC() bool {
49 return targetRequiresLibC(&builtin.target);
50}
51
11test {52test {
12 _ = linux;53 _ = linux;
13 if (native_os == .uefi) _ = uefi;54 if (native_os == .uefi) _ = uefi;
src/Compilation/Config.zig+1-10
...@@ -234,19 +234,10 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -234,19 +234,10 @@ pub fn resolve(options: Options) ResolveError!Config {
234 break :b true;234 break :b true;
235 }235 }
236 if (options.link_libc) |x| break :b x;236 if (options.link_libc) |x| break :b x;
237 switch (target.os.tag) {
238 // These targets don't require libc, but we don't yet have a syscall layer for them,
239 // so we default to linking libc for now.
240 .freebsd,
241 .netbsd,
242 .openbsd,
243 => break :b true,
244 else => {},
245 }
246 if (options.ensure_libc_on_non_freestanding and target.os.tag != .freestanding)237 if (options.ensure_libc_on_non_freestanding and target.os.tag != .freestanding)
247 break :b true;238 break :b true;
248239
249 break :b target.requiresLibC();240 break :b std.os.targetRequiresLibC(target);
250 };241 };
251242
252 const link_mode = b: {243 const link_mode = b: {
test/src/StackTrace.zig+1-4
...@@ -58,10 +58,7 @@ fn addCaseTarget(...@@ -58,10 +58,7 @@ fn addCaseTarget(
58 .fuchsia => false,58 .fuchsia => false,
59 else => true,59 else => true,
60 };60 };
61 const both_libc = switch (target.result.os.tag) {61 const both_libc = !std.os.targetRequiresLibC(&target.result);
62 .freebsd, .netbsd, .openbsd => false,
63 else => !target.result.requiresLibC(),
64 };
6562
66 // See `std.debug.StackIterator.fp_usability` logic.63 // See `std.debug.StackIterator.fp_usability` logic.
67 const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.result.cpu.arch) {64 const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.result.cpu.arch) {