1//! Multi-target implementation of libc, providing ABI compatibility with
2//! bundled libcs.
3//!
4//! mingw-w64 libc is not fully statically linked, so some symbols don't need
5//! to be exported.
6
7const builtin = @import("builtin");
8const std = @import("std");
9
10// Avoid dragging in the runtime safety mechanisms into this .o file, unless
11// we're trying to test zigc.
12pub const panic = if (builtin.is_test)
13 std.debug.FullPanic(std.debug.defaultPanic)
14else
15 std.debug.no_panic;
16
17/// It is possible that this libc is being linked into a different test
18/// compilation, as opposed to being tested itself. In such case,
19/// `builtin.link_libc` will be `true` along with `builtin.is_test`.
20///
21/// When we don't have a complete libc, `builtin.link_libc` will be `false` and
22/// we will be missing externally provided symbols, such as `_errno` from
23/// ucrtbase.dll. In such case, we must avoid analyzing otherwise exported
24/// functions because it would cause undefined symbol usage.
25///
26/// Unfortunately such logic cannot be automatically done in this function body
27/// since `func` will always be analyzed by the time we get here, so `comptime`
28/// blocks will need to each check for `builtin.link_libc` and skip exports
29/// when the exported functions have libc dependencies not provided by this
30/// compilation unit.
31pub inline fn symbol(comptime func: *const anyopaque, comptime name: []const u8) void {
32 @export(func, .{
33 .name = name,
34 // Normally, libc goes into a static archive, making all symbols
35 // overridable. However, Zig supports including the libc functions as part
36 // of the Zig Compilation Unit, so to support this use case we make all
37 // symbols weak.
38 .linkage = .weak,
39 // For WebAssembly, hidden visibility allows the symbol to be resolved to
40 // other modules, but will not export it to the host runtime.
41 .visibility = .hidden,
42 });
43}
44
45/// Given a low-level syscall return value, sets errno and returns `-1`, or on
46/// success returns the result.
47pub fn errno(syscall_return_value: usize) c_int {
48 return switch (builtin.os.tag) {
49 .linux => {
50 const signed: isize = @bitCast(syscall_return_value);
51 const casted: c_int = @intCast(signed);
52 if (casted < 0) {
53 @branchHint(.unlikely);
54 std.c._errno().* = -casted;
55 return -1;
56 }
57 return casted;
58 },
59 else => comptime unreachable,
60 };
61}
62
63comptime {
64 _ = @import("c/ctype.zig");
65 _ = @import("c/fcntl.zig");
66 _ = @import("c/inttypes.zig");
67 if (!builtin.target.isMinGW()) {
68 _ = @import("c/malloc.zig");
69 }
70 _ = @import("c/math.zig");
71 _ = @import("c/pthread.zig");
72 _ = @import("c/search.zig");
73 _ = @import("c/stdlib.zig");
74 _ = @import("c/string.zig");
75 _ = @import("c/strings.zig");
76 _ = @import("c/stropts.zig");
77
78 _ = @import("c/sys/capability.zig");
79 _ = @import("c/sys/file.zig");
80 _ = @import("c/sys/mman.zig");
81 _ = @import("c/sys/reboot.zig");
82 _ = @import("c/sys/utsname.zig");
83
84 _ = @import("c/unistd.zig");
85 _ = @import("c/wchar.zig");
86}