#!/bin/bash # Build spectrogram viewer for the web using Emscripten # Usage: ./build_web.sh [debug|release] set -e # Get script directory (project root) SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR" BUILD_TYPE=${1:-release} RAYLIB_DIR="$SCRIPT_DIR/build/external/raylib-master" SRC_DIR="$SCRIPT_DIR/src" BUILD_DIR="$SCRIPT_DIR/bin/web" RAYLIB_BUILD="$BUILD_DIR/raylib_build" OUTPUT="$BUILD_DIR/rspektrum.html" # Create build directories mkdir -p "$BUILD_DIR" "$RAYLIB_BUILD" echo "=== Building Spectrogram Viewer for Web ($BUILD_TYPE) ===" echo "Raylib dir: $RAYLIB_DIR" # Common compile flags for raylib RAYLIB_CFLAGS="-Os -Wall -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2" if [ "$BUILD_TYPE" = "debug" ]; then RAYLIB_CFLAGS="-g -O0 -Wall -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2" fi echo "=== Step 1: Compiling raylib for web ===" # raylib rarely changes; skip the (slow) rebuild if the archive already exists. # Delete "$RAYLIB_BUILD/libraylib.a" to force a clean raylib rebuild. if [ ! -f "$RAYLIB_BUILD/libraylib.a" ]; then # Compile raylib source files emcc -c "$RAYLIB_DIR/src/rcore.c" $RAYLIB_CFLAGS -o "$RAYLIB_BUILD/rcore.o" emcc -c "$RAYLIB_DIR/src/rshapes.c" $RAYLIB_CFLAGS -o "$RAYLIB_BUILD/rshapes.o" emcc -c "$RAYLIB_DIR/src/rtextures.c" $RAYLIB_CFLAGS -o "$RAYLIB_BUILD/rtextures.o" emcc -c "$RAYLIB_DIR/src/rtext.c" $RAYLIB_CFLAGS -o "$RAYLIB_BUILD/rtext.o" emcc -c "$RAYLIB_DIR/src/rmodels.c" $RAYLIB_CFLAGS -o "$RAYLIB_BUILD/rmodels.o" emcc -c "$RAYLIB_DIR/src/raudio.c" $RAYLIB_CFLAGS -o "$RAYLIB_BUILD/raudio.o" # Create static library cd "$RAYLIB_BUILD" emar rcs libraylib.a rcore.o rshapes.o rtextures.o rtext.o rmodels.o raudio.o cd "$SCRIPT_DIR" else echo "libraylib.a found, skipping raylib rebuild" fi # Compile the application modules (web version — no subprocess support). # platform_web.c provides stub implementations for spawn/error functions. # # Auto-discovered from src/*.c (same as the desktop Makefile) so adding a module # needs no edit here. The web target keeps platform_web.c and drops the desktop # backends (platform_linux.c / platform_win32.c). echo "=== Step 2: Compiling spectrogram modules for web ===" cd "$SCRIPT_DIR" APP_MODULES="" for f in "$SRC_DIR"/*.c; do m=$(basename "$f" .c) case "$m" in platform_linux|platform_win32) continue ;; # desktop-only backends esac APP_MODULES="$APP_MODULES $m" done APP_OPT="-Os" if [ "$BUILD_TYPE" = "debug" ]; then APP_OPT="-g -O0" fi APP_INCLUDES="-I$RAYLIB_DIR/src -I$RAYLIB_DIR/src/external -I$RAYLIB_DIR/src/external/glfw/include -Iinclude" # NOTE: do NOT pass -DPLATFORM_WEB to the app modules. Our code selects web # behavior by linking platform_web.c (not via the macro), and PLATFORM_WEB is # also an enumerator in platform.h — defining it as a macro breaks that enum. # (raylib itself is built with -DPLATFORM_WEB above; it needs the macro.) OBJECTS="" for m in $APP_MODULES; do echo " CC $m.c" emcc -c $APP_OPT -Wall $APP_INCLUDES \ "$SRC_DIR/$m.c" -o "$RAYLIB_BUILD/$m.o" OBJECTS="$OBJECTS $RAYLIB_BUILD/$m.o" done # Linker flags # The font lives at resources/fonts/DejaVuSansMono.ttf and is loaded relative to # the resources dir at runtime, so the resources@resources preload covers it. # INITIAL_MEMORY + ALLOW_MEMORY_GROWTH: the web build now computes the full STFT # up front, so the heap must be able to grow for longer recordings. LDFLAGS="-s USE_GLFW=3 -s ASYNCIFY -s INITIAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 -s FORCE_FILESYSTEM=1 --preload-file resources@resources --shell-file $SCRIPT_DIR/web_shell.html -s NO_EXIT_RUNTIME=1" if [ "$BUILD_TYPE" = "debug" ]; then LDFLAGS="$LDFLAGS -g -O0 -s ASSERTIONS=1" else LDFLAGS="$LDFLAGS -O2" fi # Compile and link emcc -o "$OUTPUT" \ $OBJECTS \ -I"$RAYLIB_DIR/src" \ -I"$RAYLIB_DIR/src/external" \ -I"$RAYLIB_DIR/src/external/glfw/include" \ -Iinclude \ "$RAYLIB_BUILD/libraylib.a" \ $LDFLAGS echo "" echo "=== Build complete ===" echo "Output: $OUTPUT" echo "" echo "To test locally, run:" echo " cd $BUILD_DIR && python3 -m http.server 8080" echo "Then open http://localhost:8080/rspektrum.html in your browser"