zig
zig copied to clipboard
wasm32-freestanding target missing errno values
Zig Version
0.11.0-dev.715+cffbb32d3
Steps to Reproduce and Observed Behavior
Create this file bug.c:
#include <errno.h>
int main() { return ENOMEM; }
Compile with:
$ zig build-exe bug.c -lc -target wasm32-freestanding -mcpu generic
error(compilation): clang failed with stderr: bug.c:2:21: error: use of undeclared identifier 'ENOMEM'
bug.c:1:1: error: unable to build C object: clang exited with code 1
Expected Behavior
Compiles successfully.
Extra Notes
Note that the wasm32-wasi target does compile succesfully. Looking at the diff of errno.h between these 2 targets would be a good start to figure out what the correct fix is. In particular the wasi target has a few extra includes like #include <bits/errno.h>, #include <__erno.h> and #include <__errno_values.h>:
$ diff lib/libc/include/wasm-freestanding-musl/errno.h lib/libc/include/wasm-wasi-musl/errno.h
8,14c8,14
< #ifdef WASM_THREAD_MODEL_SINGLE
< extern int errno;
< #else
< #ifdef __cplusplus
< extern thread_local int errno;
< #else
< extern _Thread_local int errno;
---
> #include <features.h>
>
> #ifdef __wasilibc_unmodified_upstream /* Use alternate WASI libc headers */
> #include <bits/errno.h>
>
> #ifdef __GNUC__
> __attribute__((const))
15a16,20
> int *__errno_location(void);
> #define errno (*__errno_location())
> #else
> #include <__errno.h>
> #include <__errno_values.h>
18c23,25
< #define errno errno
---
> #ifdef _GNU_SOURCE
> extern char *program_invocation_short_name, *program_invocation_name;
> #endif
24a32
>
Those values are defined by the operating system. Why should those be defined when targeting freestanding?
I believe they should be defined by libc. I'm a little uninformed about how libc is supposed to work with wasm32-freestanding. It appears that there are header files provided by musl but when I try to load wasm32-freestanding in a browser that contains C code, the libc implementation is missing?
I believe they should be defined by
libc. I'm a little uninformed about how libc is supposed to work withwasm32-freestanding. It appears that there are header files provided by musl but when I try to loadwasm32-freestandingin a browser that contains C code, the libc implementation is missing?
Yes, but those error values can differ per architecture and operating system. As far as I'm aware, the C ISO standard only defines errno, but not the number values. Most of those values are defined by POSIX. In the case of wasm32-freestanding, what should those values be? I'm arguing that neither the architecture (wasm32) nor the operating system (freestanding, so none) define the values in this case and the error you receive is not a bug, but a misundertanding. There's also no syscalls that could possible return those values. The reason why it does exist for wasm-wasi is because they're explicitly defined by the WASI specification (which follows POSIX in this case). Either way, if you believe this to be an issue I think it should be addressed upstream instead.
Most freestanding projects should not use -lc if possible, because libc in such case is crufty baggage. However, Zig provides a freestanding libc in case the project wants to depend on C code that assumes the existence of libc. In this case, the purpose of the libc provided is to "shim" the API and make the C code compile if possible. It's OK however to leave some symbols undefined for the main project to provide them.
So far, I have created a set of headers for this libc for this purpose under this directory: https://github.com/ziglang/zig/tree/master/lib/libc/include/wasm-freestanding-musl
As you can see, it is missing most API. What is here so far is a stub which I encourage contributors to add to. So, indeed, let us add errno constants and other missing stuff too. We can start with math stuff and string manipulation, which one can easily see how it should work. OS stuff such as fopen can be left to solve later. Perhaps we try to piggyback on top of a zig libc implementation and Bring-Your-Own-OS API in the standard library.
Thanks for clarifying Andrew. Sorry for the confusion @marler8997, I was wrong :)
One more note for clarification:
when I try to load
wasm32-freestandingin a browser that contains C code, the libc implementation is missing?
It is intended that zig provides the libc implementation as well. The implementation is in lib/c.zig. You can see that there is even code in there that deals with the wasm32-freestanding target. However it looks like there is a missing mechanism to trigger compilation of this code and then link it into the wasm binary that is produced. It should work similarly to compiler_rt and the logic for this is in Compilation.zig.