diff --git a/.gitignore b/.gitignore index 67b9111..634e8d8 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,8 @@ old-ocaml/ .claude/ probe probe.c + +# raylib built for the browser: a 1.6MB archive and the pinned checkout it +# came from. vendor/raylib/build-web.sh makes both, and the path is named to a +# build through FLAN_RAYLIB_WEB, not committed. +vendor/raylib/web/ diff --git a/vendor/raylib/build-web.sh b/vendor/raylib/build-web.sh new file mode 100644 index 0000000..1cc7388 --- /dev/null +++ b/vendor/raylib/build-web.sh @@ -0,0 +1,76 @@ +#!/bin/sh +# raylib, built for the browser. +# +# The host half of this package needs no build: Fedora ships libraylib.so.550 +# and `link` names it. The browser has no such thing, so the archive has to be +# made here, once, out of raylib's own sources with emscripten's clang. +# +# Pinned to the tag whose shared library the host links — 5.5 against +# libraylib.so.550 — because `raylib.flan` carries struct layouts and enum +# values that are raylib's, not ours, and a build where the two targets are +# different raylibs would disagree about them silently. +# +# The output is a plain static archive plus nothing else: no headers are +# installed, because the generated FFI shim declares the prototypes it uses +# (see BUILT.md, "No raylib headers are needed"). +# +# sh vendor/raylib/build-web.sh +# +# It prints the line to export. `vendor/raylib/link` points at the archive +# through ${FLAN_RAYLIB_WEB}, and a web build that names raylib with the +# variable unset is refused by name rather than met at the linker. +# +# Environment: +# FLAN_RAYLIB_TAG the raylib tag to build (default 5.5) +# FLAN_RAYLIB_WEB_DIR where to put it (default vendor/raylib/web) +# FLAN_RAYLIB_SRC an existing raylib checkout to build instead of cloning +set -eu + +tag=${FLAN_RAYLIB_TAG:-5.5} +here=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +out=${FLAN_RAYLIB_WEB_DIR:-$here/web} +archive=$out/libraylib-$tag.a + +command -v emcc > /dev/null 2>&1 || { + echo "build-web.sh: no emcc on PATH. Source an emsdk's emsdk_env.sh." >&2 + exit 1 +} + +if [ -f "$archive" ]; then + echo "already built: $archive" >&2 +else + mkdir -p "$out" + if [ -n "${FLAN_RAYLIB_SRC:-}" ]; then + src=$FLAN_RAYLIB_SRC + else + src=$out/raylib-$tag + [ -d "$src" ] || git clone --depth 1 --branch "$tag" \ + https://github.com/raysan5/raylib "$src" + fi + + objs=$out/obj-$tag + rm -rf "$objs" + mkdir -p "$objs" + + # GRAPHICS_API_OPENGL_ES2 is what WebGL is. PLATFORM_WEB makes rcore.c + # include platforms/rcore_web.c, whose WindowShouldClose() is an + # emscripten_sleep that returns false — see BUILT.md on why that is the whole + # reason a Flan `until` loop needs no rewriting for the browser. + # + # rglfw.c is not in the list: the web platform uses emscripten's own GLFW + # (-sUSE_GLFW=3, in `link`), not a compiled-in one. + for m in rcore rshapes rtextures rtext rmodels raudio utils; do + [ -f "$src/src/$m.c" ] || continue + echo " emcc $m.c" >&2 + (cd "$src/src" && emcc -c -O2 -std=gnu99 \ + -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2 \ + -I. -Iexternal/glfw/include \ + "$m.c" -o "$objs/$m.o") + done + + emar rcs "$archive" "$objs"/*.o + rm -rf "$objs" +fi + +echo +echo "export FLAN_RAYLIB_WEB=$archive" diff --git a/vendor/raylib/link b/vendor/raylib/link index 21fde4d..b8317b5 100644 --- a/vendor/raylib/link +++ b/vendor/raylib/link @@ -1,2 +1,31 @@ --l:libraylib.so.550 --lm +# Extra linker arguments for this package, one per line. A line may be +# addressed to one target — @native, @wasi, @web — and an untagged line +# applies to all of them. ${NAME} expands from the environment. The selection +# and the expansion happen in Build, which is the only place that knows which +# target is being built; Load reads these lines and passes them through. + +# The host. Fedora's package installs the versioned soname and no unversioned +# symlink, so -lraylib finds nothing and the file has to be named. +@native -l:libraylib.so.550 +@native -lm + +# The browser. No shared library exists for wasm, so this is a static archive +# built out of raylib's own sources by vendor/raylib/build-web.sh, pinned to +# the 5.5 tag that matches the host's .so.550 — raylib.flan carries raylib's +# struct layouts and enum values, and two targets built from different raylibs +# would disagree about them without saying so. +# +# FLAN_RAYLIB_WEB is where that archive is. Unset, a web build that reaches +# raylib is refused by name here rather than met as a page of undefined GLFW +# symbols; build-web.sh prints the line to export. +@web ${FLAN_RAYLIB_WEB} + +# raylib's web platform is GLFW on emscripten's own port, not the rglfw.c it +# compiles in natively, and WebGL is GLES2. GL_ENABLE_GET_PROC_ADDRESS because +# rlgl asks for extension pointers by name. +@web -sUSE_GLFW=3 +@web -sGL_ENABLE_GET_PROC_ADDRESS + +# -sASYNCIFY is not here: Build adds it to every web link, because the reason +# for it is the browser's event loop and not raylib. See Build's comment on the +# main loop.