| 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 | |
| 7 | const builtin = @import("builtin"); |
| 8 | const std = @import("std"); |
| 9 | |
| 10 | // Avoid dragging in the runtime safety mechanisms into this .o file, unless |
| 11 | // we're trying to test zigc. |
| 12 | pub const panic = if (builtin.is_test) |
| 13 | std.debug.FullPanic(std.debug.defaultPanic) |
| 14 | else |
| 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. |
| 31 | pub 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. |
| 47 | pub 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 | |
| 63 | comptime { |
| 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 | } |