initial commit

This commit is contained in:
2026-08-30 20:45:54 -06:00
commit 32ab1213fb
20 changed files with 1349 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Builds the WebAssembly ("web") build of DESI Explorer with Odin
# (js_wasm32) + emscripten. Output: build/web/index.html (+ index.wasm, odin.js).
#
# Requires:
# - `odin` on PATH with the js_wasm32 target
# - emcc / emscripten active in PATH
# Optional:
# - ODIN_ROOT (defaults to `odin root`)
# - OUT_DIR (defaults to build/web)
set -euo pipefail
OUT_DIR="${OUT_DIR:-build/web}"
ODIN_ROOT="${ODIN_ROOT:-$(odin root)}"
mkdir -p lib/local
mkdir -p "$OUT_DIR"
# The Odin compiler emits a wasm object; raylib's C code is linked later by
# emcc. `-define:RAYLIB_WASM_LIB=env.o` stops the compiler from trying to
# link the raylib lib itself (emcc does that; it ends up in the final module).
odin build src \
-target:js_wasm32 \
-build-mode:obj \
-define:RAYLIB_WASM_LIB=env.o \
-o:speed \
-collection:lib=lib/local \
-out:"${OUT_DIR}/game"
# Odin's JS runtime glue; the generated module imports functions from it.
cp "${ODIN_ROOT}/core/sys/wasm/js/odin.js" "${OUT_DIR}/odin.js"
# Link with emscripten against raylib's prebuilt web library. Flags mirror the
# known-good karl-zylinski/odin-raylib-web template.
emcc \
-o "${OUT_DIR}/index.html" \
"${OUT_DIR}/game.obj" \
"${ODIN_ROOT}/vendor/raylib/wasm/libraylib.web.a" \
--shell-file scripts/web/index_template.html \
-sEXPORTED_RUNTIME_METHODS="['HEAPF32']" \
-sUSE_GLFW=3 \
-sWASM_BIGINT \
-sWARN_ON_UNDEFINED_SYMBOLS=0 \
-sASSERTIONS
rm -f "${OUT_DIR}/game.obj"
echo "Web build created in ${OUT_DIR}"
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Installs the pinned Odin release matching the runner's native architecture.
# The Odin release tarballs are named odin-linux-{amd64,arm64}-<version>.tar.gz;
# on an arm64 runner the amd64 Odin binary only runs under emulation and emits
# amd64 objects, which a natively-installed clang/ld cannot link ("Relocations
# in generic ELF (EM: 62)").
set -euo pipefail
VERSION="${ODIN_VERSION:-dev-2026-07}"
ARCH="$(uname -m)"
case "$ARCH" in
x86_64 | amd64) OBJ_ARCH="amd64" ;;
aarch64 | arm64) OBJ_ARCH="arm64" ;;
*)
echo "Unsupported runner architecture: $ARCH" >&2
exit 1
;;
esac
curl -fL -o /tmp/odin.tar.gz \
"https://github.com/odin-lang/Odin/releases/download/${VERSION}/odin-linux-${OBJ_ARCH}-${VERSION}.tar.gz"
mkdir -p /tmp/odin
tar -xzf /tmp/odin.tar.gz -C /tmp/odin --strip-components=1
# Work around an Odin binding bug: for ODIN_ARCH == .arm64 the vendored
# raylib references `vendor/raylib/linux-arm/libraylib.a`, but the release
# tarball ships it under `linux-arm64/` (see vendor/raylib/raylib.odin).
if [ "${OBJ_ARCH}" = "arm64" ] \
&& [ -d /tmp/odin/vendor/raylib/linux-arm64 ] \
&& [ ! -e /tmp/odin/vendor/raylib/linux-arm ]; then
ln -s linux-arm64 /tmp/odin/vendor/raylib/linux-arm
fi
if [ -n "${GITHUB_PATH:-}" ]; then
echo "/tmp/odin" >> "$GITHUB_PATH"
fi
echo "Installed Odin ${VERSION} (host arch: ${ARCH}, release arch: ${OBJ_ARCH})"
+50
View File
@@ -0,0 +1,50 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>DESI Explorer</title>
<meta name="viewport" content="width=device-width">
<style>
body {
margin: 0;
overflow: hidden;
background: #05050f;
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas id="canvas" tabindex="-1" oncontextmenu="event.preventDefault()"></canvas>
<!-- Odin's JS runtime glue; required by the generated wasm module. -->
<script src="odin.js"></script>
<script>
var odinMemoryInterface = new odin.WasmMemoryInterface();
odinMemoryInterface.setIntSize(4);
var odinImports = odin.setupDefaultImports(odinMemoryInterface);
var Module = {
instantiateWasm: function(imports, successCallback) {
var newImports = Object.assign({}, odinImports, imports);
return WebAssembly.instantiateStreaming(fetch("index.wasm"), newImports).then(
function(output) {
var e = output.instance.exports;
odinMemoryInterface.setExports(e);
odinMemoryInterface.setMemory(e.memory);
return successCallback(output.instance);
}
);
},
onRuntimeInitialized: function() {
var e = wasmExports;
if (e._start) { e._start(); }
},
canvas: document.getElementById("canvas")
};
</script>
{{{ SCRIPT }}}
</body>
</html>