I'm currently tinkering with bringing one of my toy Zig projects to the web via
Alon's nice gist here which uses emcc only for the linker step:
...and it *nearly* works except for code that uses EM_JS() macros.
The project (
https://github.com/floooh/pacman.zig) consists of some C code (my cross-platform 'sokol headers') which uses EM_JS() quite extensively (very handy for STB-style single-file libraries), and at the top, the "game code" is written in Zig.
I'm compiling all code with Zig with the wasm32-wasi target (wasm32-emscripten exists, but currently doesn't seem to be supported by the Zig compiler), and then use emcc for linking.
Long story short, it works except for the one problem that emcc cannot resolve any functions which have been defined with EM_JS(). If I compile the same library with emcc instead of Zig it works.
So my question is: does emcc also do some "EM_JS() magic" when compiling the source code which contains EM_JS macros? Maybe I'm missing some Clang command line options which emcc inserts?
The errors look like this:
error: undefined symbol: sapp_js_add_clipboard_listener (referenced by top-level compiled C/C++ code)
Followed by:
warning: _sapp_js_add_clipboard_listener may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
...there's also a single warning about malloc:
...if I compile with "-s ERROR_ON_UNDEFINED_SYMBOLS=0", then the code breaks at runtime failing to resolve those EM_JS() functions, e.g.:
"missing function: sapp_js_pointer_init"
Compiling the same static link library with emcc, it magically works.
If I look at both libraries with nm I don't see much of a difference, e.g. here's the relevant parts from the emcc-compiled library, every EM_JS symbol has an "D __em_js..." entry, and a matching "U sapp_js..." entry, e.g.:
0000185f D __em_js__sapp_js_add_beforeunload_listener
...
U sapp_js_add_beforeunload_listener
...
The Zig-compiled library has the same entries:
00001841 D __em_js__sapp_js_add_beforeunload_listener
...
U sapp_js_add_beforeunload_listener
...
...yet one library (the zig-compiled) produces linker errors for those symbols, and the other (emcc-compiled) works.
Clearly I'm missing something. I was expecting that all the EM_JS() magic is in the linker (by extracting the __em_js_* Javascript source code strings, and then "somehow" providing the C function import). Any ideas what I'm missing?
Thanks!
-Floh.