Make programs using Odin + Sokol that work on the web!
Live example: https://zylinski.se/odin-sokol-web/
This assumes you have a recent Odin compiler installed.
- Install emscripten
- Clone this repository
- Run
build_web.batorbuild_web.shdepending on platform (you may need to open the script and modify the path to emscripten)
Web build is in build/web
Note
Use python -m http.server while inside build/web to launch a web server. Go to localhost:8000 to run your web program.
Launching the index.html in there may not work due to CORS errors.
There is also a build_desktop.bat/sh that makes a desktop version of your program.
Warning
If the desktop build says that there are libraries missing, then you need to go into source/sokol and run one of the build_clibs... build scripts.
- The contents of
sourceis compiled with Odin compiler usingjs_wasm32target. It is compiled inobjbuild mode. This means that no libraries are linked. That instead happens in step (3). - The
odin.jsenvironment is copied from<odin>/core/sys/wasm/js/odin.jstobuild/web - The emscripten compiler is run. It is fed the output of our Odin compilation as well as the Sokol library files. It is also fed a template HTML file that is used as basis for the final
index.htmlfile. The resulting WASM files and are written tobuild/web
Open the resulting build/web/index.html, to see how it starts up the main proc in our Odin code.
- Any C library you use in the Odin code needs to be manually linked into
emcc. - If you get compile errors related to
vendor:libcwhen using any WASM library, then you'll need to remove theimport "vendor:libc"line from that library. Some libraries, such asvendor:box2dandvendor:stb/imageusevendor:libcto remove the need for emscripten. However, this breaks those libs when used in combination with emscripten.
- Replace the contents of folder
source/sokolwith this: https://github.com/floooh/sokol-odin/tree/main/sokol -- Afterwards, run the scripts inside thesource/sokolfolder to compile the libs. - Replace the contents of folder
sokol-shdcwith this: https://github.com/floooh/sokol-tools-bin/tree/master/bin
You probably have a global variable that allocates dynamic memory. Move that allocation into the game's init or main proc. This could also happen if initialize dynamic arrays or maps in the global file scope, like so:
arr := [dynamic]int { 2, 3, 4 }
In that case you can declare it and do the initialization in the init proc instead:
arr: [dynamic]int
main :: proc() {
arr = { 2, 3, 4 }
// bla bla
}
This happens because the context hasn't been initialized with the correct allocator yet.
Try modifying the build_web script and add these flags where it runs emcc:
-sALLOW_MEMORY_GROWTH=1 -sINITIAL_HEAP=16777216 -sSTACK_SIZE=65536
The numbers above are the default values, try bigger ones and see if it helps.
You might be missing the assets folder. It must have at least a single file inside it. You can also remove the --preload assets from the build script.