From 6376103b23617735044970f08c2a314c46b97c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20=C3=85stholm?= Date: Sun, 11 Jan 2026 21:15:10 +0100 Subject: [PATCH 1/2] wasi-libc: De-deduplicate erroneously removed headers 05d8b565ad1a1d6c0c1e93dc47f1d828043fcafc deduplicated wasi-libc headers that are identical to upstream musl, but because some public headers match the same `#include <>` patterns as private headers, this resulted in unmodified upstream musl headers sometimes getting prioritized when compiling wasi-libc, resulting in incorrect definitions. For example, `UTIME_OMIT` is supposed to be -2 on WASI, but became 0x3ffffffe. The restored headers were sourced from which is the same revision as the most recent wasi-libc sync 07cc32b0041e5e12f72d682fd06a995fe904d556. --- .../musl/src/include/arpa/inet.h | 8 ++++++++ .../libc-top-half/musl/src/include/stdlib.h | 19 ++++++++++++++++++ .../libc-top-half/musl/src/include/string.h | 11 ++++++++++ .../libc-top-half/musl/src/include/sys/mman.h | 20 +++++++++++++++++++ .../libc-top-half/musl/src/include/sys/stat.h | 9 +++++++++ .../libc-top-half/musl/src/include/sys/time.h | 8 ++++++++ 6 files changed, 75 insertions(+) create mode 100644 lib/libc/wasi/libc-top-half/musl/src/include/arpa/inet.h create mode 100644 lib/libc/wasi/libc-top-half/musl/src/include/stdlib.h create mode 100644 lib/libc/wasi/libc-top-half/musl/src/include/string.h create mode 100644 lib/libc/wasi/libc-top-half/musl/src/include/sys/mman.h create mode 100644 lib/libc/wasi/libc-top-half/musl/src/include/sys/stat.h create mode 100644 lib/libc/wasi/libc-top-half/musl/src/include/sys/time.h diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/arpa/inet.h b/lib/libc/wasi/libc-top-half/musl/src/include/arpa/inet.h new file mode 100644 index 0000000000000000000000000000000000000000..1e6debf49669aa9cbf48802f76fa351728b2e43d --- /dev/null +++ b/lib/libc/wasi/libc-top-half/musl/src/include/arpa/inet.h @@ -0,0 +1,8 @@ +#ifndef ARPA_INET_H +#define ARPA_INET_H + +#include "../../../include/arpa/inet.h" + +hidden int __inet_aton(const char *, struct in_addr *); + +#endif diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/stdlib.h b/lib/libc/wasi/libc-top-half/musl/src/include/stdlib.h new file mode 100644 index 0000000000000000000000000000000000000000..812b04de2fd6b6efb1576a72eea4fa16007fc2ad --- /dev/null +++ b/lib/libc/wasi/libc-top-half/musl/src/include/stdlib.h @@ -0,0 +1,19 @@ +#ifndef STDLIB_H +#define STDLIB_H + +#include "../../include/stdlib.h" + +hidden int __putenv(char *, size_t, char *); +hidden void __env_rm_add(char *, char *); +hidden int __mkostemps(char *, int, int); +hidden int __ptsname_r(int, char *, size_t); +hidden char *__randname(char *); +hidden void __qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *); + +hidden void *__libc_malloc(size_t); +hidden void *__libc_malloc_impl(size_t); +hidden void *__libc_calloc(size_t, size_t); +hidden void *__libc_realloc(void *, size_t); +hidden void __libc_free(void *); + +#endif diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/string.h b/lib/libc/wasi/libc-top-half/musl/src/include/string.h new file mode 100644 index 0000000000000000000000000000000000000000..2133b5c1eead4f94b5cb7f9a70c21788678cd3be --- /dev/null +++ b/lib/libc/wasi/libc-top-half/musl/src/include/string.h @@ -0,0 +1,11 @@ +#ifndef STRING_H +#define STRING_H + +#include "../../include/string.h" + +hidden void *__memrchr(const void *, int, size_t); +hidden char *__stpcpy(char *, const char *); +hidden char *__stpncpy(char *, const char *, size_t); +hidden char *__strchrnul(const char *, int); + +#endif diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/sys/mman.h b/lib/libc/wasi/libc-top-half/musl/src/include/sys/mman.h new file mode 100644 index 0000000000000000000000000000000000000000..57c5bd3d9621daf1c9d40fde24c0d05f464489b6 --- /dev/null +++ b/lib/libc/wasi/libc-top-half/musl/src/include/sys/mman.h @@ -0,0 +1,20 @@ +#ifndef SYS_MMAN_H +#define SYS_MMAN_H + +#include "../../../include/sys/mman.h" + +hidden void __vm_wait(void); +hidden void __vm_lock(void); +hidden void __vm_unlock(void); + +hidden void *__mmap(void *, size_t, int, int, int, off_t); +hidden int __munmap(void *, size_t); +hidden void *__mremap(void *, size_t, size_t, int, ...); +hidden int __madvise(void *, size_t, int); +hidden int __mprotect(void *, size_t, int); + +hidden const unsigned char *__map_file(const char *, size_t *); + +hidden char *__shm_mapname(const char *, char *); + +#endif diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/sys/stat.h b/lib/libc/wasi/libc-top-half/musl/src/include/sys/stat.h new file mode 100644 index 0000000000000000000000000000000000000000..59339beecb17e2dc4bf7793ce8ed984c138b2f33 --- /dev/null +++ b/lib/libc/wasi/libc-top-half/musl/src/include/sys/stat.h @@ -0,0 +1,9 @@ +#ifndef SYS_STAT_H +#define SYS_STAT_H + +#include "../../../include/sys/stat.h" + +hidden int __fstat(int, struct stat *); +hidden int __fstatat(int, const char *restrict, struct stat *restrict, int); + +#endif diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/sys/time.h b/lib/libc/wasi/libc-top-half/musl/src/include/sys/time.h new file mode 100644 index 0000000000000000000000000000000000000000..fb9622e51fcf9608bcf604794a4a18e0790a2f7a --- /dev/null +++ b/lib/libc/wasi/libc-top-half/musl/src/include/sys/time.h @@ -0,0 +1,8 @@ +#ifndef SYS_TIME_H +#define SYS_TIME_H + +#include "../../../include/sys/time.h" + +hidden int __futimesat(int, const char *, const struct timeval [2]); + +#endif -- 2.54.0 From 0a8e8e67d7e67e8381f2dcdb8e5ede8e42a71649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20=C3=85stholm?= Date: Sun, 11 Jan 2026 21:52:21 +0100 Subject: [PATCH 2/2] Misc. `std.Io` fixes for WASI and Emscripten - Corrects WASI `UTIME_*` definitions now that the libc build has been fixed (see previous commit), and adds the corresponding definitions for Emscripten which were missing. - Fixes `dirReadUnimplemented()`, which didn't compile. - Prevents a dependency on `pthread_kill` from being pulled in in single-threaded Emscripten builds, where it isn't defined. With these changes, Emscripten can now participate in juicy main. --- lib/std/Io/Threaded.zig | 8 ++++++-- lib/std/c.zig | 8 ++++++-- lib/std/os/emscripten.zig | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 212ee2fba18bcff3c33bcdaf8ae66fb7dff8fd9c..055b5e879a825a08500c8679f90f71c218c963bc 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -2024,6 +2024,7 @@ fn groupConcurrent( fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) Io.Cancelable!void { _ = initial_token; // we need to load `token` *after* the group finishes + if (builtin.single_threaded) unreachable; // nothing to await const t: *Threaded = @ptrCast(@alignCast(userdata)); const g: Group = .{ .ptr = type_erased }; @@ -2082,6 +2083,7 @@ fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *any fn groupCancel(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) void { _ = initial_token; + if (builtin.single_threaded) unreachable; // nothing to cancel const t: *Threaded = @ptrCast(@alignCast(userdata)); const g: Group = .{ .ptr = type_erased }; @@ -2152,6 +2154,7 @@ fn await( result_alignment: Alignment, ) void { _ = result_alignment; + if (builtin.single_threaded) unreachable; // nothing to await const t: *Threaded = @ptrCast(@alignCast(userdata)); const future: *Future = @ptrCast(@alignCast(any_future)); @@ -2218,6 +2221,7 @@ fn cancel( result_alignment: Alignment, ) void { _ = result_alignment; + if (builtin.single_threaded) unreachable; // nothing to cancel const t: *Threaded = @ptrCast(@alignCast(userdata)); const future: *Future = @ptrCast(@alignCast(any_future)); @@ -4959,7 +4963,7 @@ fn dirReadUnimplemented(userdata: ?*anyopaque, dir_reader: *Dir.Reader, buffer: _ = userdata; _ = dir_reader; _ = buffer; - return error.Unimplemented; + return error.Unexpected; } const dirRealPathFile = switch (native_os) { @@ -13224,7 +13228,7 @@ fn processSpawnPath(userdata: ?*anyopaque, dir: Dir, options: process.SpawnOptio } const processSpawn = switch (native_os) { - .wasi, .ios, .tvos, .visionos, .watchos => processSpawnUnsupported, + .wasi, .emscripten, .ios, .tvos, .visionos, .watchos => processSpawnUnsupported, .windows => processSpawnWindows, else => processSpawnPosix, }; diff --git a/lib/std/c.zig b/lib/std/c.zig index 6f8370ee14a0db8e5d7bc13ee71b9401b25c4304..a59ecfd3a7bb8aa45c7905d3078c424efaa81f11 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -97,6 +97,7 @@ pub const off_t = switch (native_os) { pub const timespec = switch (native_os) { .linux => linux.timespec, .emscripten => emscripten.timespec, + // lib/libc/include/wasm-wasi-musl/__struct_timespec.h .wasi => extern struct { sec: time_t, nsec: isize, @@ -115,16 +116,18 @@ pub const timespec = switch (native_os) { @as(wasi.timestamp_t, @intCast(ts.nsec)); } + // lib/libc/include/wasm-wasi-musl/__header_sys_stat.h + /// For use with `utimensat` and `futimens`. pub const NOW: timespec = .{ .sec = 0, - .nsec = 0x3fffffff, + .nsec = -1, }; /// For use with `utimensat` and `futimens`. pub const OMIT: timespec = .{ .sec = 0, - .nsec = 0x3ffffffe, + .nsec = -2, }; }, // https://github.com/SerenityOS/serenity/blob/0a78056453578c18e0a04a0b45ebfb1c96d59005/Kernel/API/POSIX/time.h#L17-L20 @@ -7007,6 +7010,7 @@ pub const time_t = switch (native_os) { .linux => linux.time_t, .emscripten => emscripten.time_t, .haiku, .dragonfly => isize, + // lib/libc/include/wasm-wasi-musl/__typedef_time_t.h // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L47 else => i64, }; diff --git a/lib/std/os/emscripten.zig b/lib/std/os/emscripten.zig index 119f0041e02a9b034b353d1a131851ec0cd6ef90..648407b20cf187f44ccf74234ed1b0621d206039 100644 --- a/lib/std/os/emscripten.zig +++ b/lib/std/os/emscripten.zig @@ -729,6 +729,7 @@ pub const sockaddr = c.sockaddr; pub const blksize_t = i32; pub const nlink_t = u32; +// https://github.com/emscripten-core/emscripten/blob/946ab574ae39401b51e75cd5257d894ae732ab54/system/lib/libc/musl/arch/emscripten/bits/alltypes.h#L140 pub const time_t = i64; pub const mode_t = u32; pub const off_t = i64; @@ -765,9 +766,24 @@ pub const stack_t = extern struct { size: usize, }; +// https://github.com/emscripten-core/emscripten/blob/946ab574ae39401b51e75cd5257d894ae732ab54/system/lib/libc/musl/arch/emscripten/bits/alltypes.h#L284 pub const timespec = extern struct { sec: time_t, nsec: isize, + + // https://github.com/emscripten-core/emscripten/blob/d72d7226f4733af8ff993dec70198cf09a24142d/system/lib/libc/musl/include/sys/stat.h#L77-L78 + + /// For use with `utimensat` and `futimens`. + pub const NOW: timespec = .{ + .sec = 0, + .nsec = 0x3fffffff, + }; + + /// For use with `utimensat` and `futimens`. + pub const OMIT: timespec = .{ + .sec = 0, + .nsec = 0x3ffffffe, + }; }; pub const timezone = extern struct { -- 2.54.0