floooh / sokol-odin

Odin bindings for the sokol headers (https://github.com/floooh/sokol)
97 stars 16 forks source link

Sokol binaries for wasm #3

Open thePHTest opened 1 year ago

thePHTest commented 1 year ago

I am starting to look into adding a build_clibs_wasm.cmd/sh script and get at least the microui example program working for web. Are there any significant barriers to achieve this? It's my first foray into web assembly so it might take me a bit. Odin's wasm usage isn't as battle tested as other platforms at the moment either.

floooh commented 1 year ago

The sokol headers are using Emscripten specific functions and features (for instance the EM_JS macro to embed Javascript functions into C source code).

In Zig I was able to compile by using a combination of the Zig compiler and the Emscripten SDK (which is needed to provide a 'sysroot', and the linker), see here:

https://github.com/floooh/pacman.zig#experimental-web-support

...last time I checked this didn't work anymore though because of some breaking changes in the Emscripten SDK, it may be that Zig needs to update to the latest LLVM version before it works again, not sure.

thePHTest commented 1 year ago

Ah interesting. Odin has the build flag -target:js_wasm32 to compile for wasm. I believe there is some extra work that will need to be done to setup the Odin runtime on startup as the default allocators with wasm are the nil allocator for that build target. I'll have to see if I need to do anything in particular to expose these EM_JS functions via Odin as well.

If there is anywhere you can point me to to grab an emscripten build command for sokol libs that would be great. Otherwise, I'll see what I can piece together.

floooh commented 1 year ago

Quick and dirty build_clibs_wasm.sh (see https://github.com/floooh/sokol-odin/blob/main/build_clibs_linux.sh for reference):

set -e

build_lib_wasm_release() {
    src=$1
    dst=$2
    backend=$3
    echo $dst
    emcc -c -O2 -DNDEBUG -DIMPL -D$backend c/$src.c
    emar rcs $dst.a $src.o
}

build_lib_wasm_debug() {
    src=$1
    dst=$2
    backend=$3
    echo $dst
    emcc -c -g -DIMPL -D$backend c/$src.c
    emar rcs $dst.a $src.o
}

# wasm + GL + Release
build_lib_wasm_release sokol_gfx sokol/gfx/sokol_gfx_wasm_gl_release SOKOL_GLES3

# wasm + GL + Debug
build_lib_wasm_debug sokol_gfx sokol/gfx/sokol_gfx_wasm_gl_debug SOKOL_GLES3

rm *.o

Expects a 'global' install of the Emscripten SDK so that emcc and emar are in the path. I only tested compilation, not if the resulting link libraries actually work :)

floooh commented 1 year ago

PS: the tricky part will be the linking though... but let me know how it goes :)

colinbellino commented 6 months ago

Very hesitant to restart the conversation here since this issue is more than one year old at that point, so let me know if this is not the right place.

I'm trying to do a similar test with odin & sokol, so i'm very curious if you managed to get it to work for you @thePHTest?

The script (build_clibs_wasm.sh) that @floooh provided worked correctly, at least from what i can see, so thanks for that :) But as you said the linking seemed to be the tricky part and since i'm a little out of my depth here, i was wondering if you had some pointers or insight about that step? (or would this fall on the Odin part of things)

To make discussing this easier, i've setup an example project of what i'm trying to do (one of the sokol odin example). I've changed some of the sokol-odin bindings to import the newly compiled files when the OS is .JS. Then i compile the project on the -target mentioned above: odin build src/ -out=main.wasm --target:js_wasm32 -debug, here again no errors that i could see. But when i run the server, WebAssembly.instantiate() fails with the error below, so i am guessing i forgot or missed something obvious?

runtime.js:1699 Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #1 module="sokol_gfx_wasm_gl_debug.a" error: module is not an object or function

Any help would be very much appreciated!

Edit: I have now researched the subject a little more and have found this project that is doing something similar with raylib, and it made me realise what i am doing in the project above might not be correct.