01 / PROJECT IDENTIFICATION
Project: C / SDL3 application compiled to WebAssembly
Project type: Static website (GitHub Pages)
Primary technologies: C, SDL3, SDL_ttf, FreeType, Emscripten
Build system: Makefile + GitHub Actions
Hosting platform: GitHub Pages (gh-pages branch)
Output: HTML, JavaScript, WASM and packaged data
Document type: Technical documentation
02 / PROJECT OVERVIEW
This project compiles a C application that uses SDL3 into WebAssembly with Emscripten, so it can run in a browser. The result is published as a static website on GitHub Pages.
Primary objectives
- Compile C source code to WebAssembly with
emcc. - Embed the application in a custom HTML page.
- Package fonts, images and sounds with the build.
- Automate the build and deployment with CI/CD.
- Keep dependencies reproducible through Git submodules.
03 / REPOSITORY STRUCTURE
The repository separates source code, assets, libraries, the web template and generated output.
Recommended layout
my-project/ │ ├── .github/ │ └── workflows/ │ └── build.yml ← automatic CI/CD │ ├── src/ ← C source code │ ├── main.c │ ├── game.c / game.h │ ├── render.c / render.h │ └── ... │ ├── assets/ ← resources │ ├── fonts/ │ │ └── font.ttf │ ├── images/ │ └── sounds/ │ ├── libs/ ← libraries (gitignore or submodules) │ ├── SDL3/ │ ├── SDL_ttf/ │ └── freetype/ │ ├── web/ ← website HTML template │ ├── index.html ← main page │ ├── style.css │ └── shell.html ← Emscripten template │ ├── dist/ ← generated by the build (gitignored) │ ├── index.html │ ├── index.js │ ├── index.wasm │ └── index.data ← packaged assets │ ├── Makefile └── README.md
04 / EMSCRIPTEN SHELL TEMPLATE
The shell.html file wraps the WASM application
in a web page. Emscripten replaces the
{{{ SCRIPT }}} placeholder with the generated
loader script.
web/shell.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My SDL3 App</title>
<style>
body { margin: 0; background: #1a1a2e; display: flex;
justify-content: center; align-items: center; height: 100vh; }
canvas { border: 2px solid #444; }
#loading { color: white; font-family: monospace; }
</style>
</head>
<body>
<div id="loading">Loading...</div>
<canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script>
var Module = {
canvas: document.getElementById('canvas'),
onRuntimeInitialized: function() {
document.getElementById('loading').style.display = 'none';
}
};
</script>
{{{ SCRIPT }}} <!-- Emscripten injects here -->
</body>
</html>
05 / MAKEFILE
The Makefile compiles the sources with emcc,
links the WASM builds of the libraries, preloads the assets
and outputs everything into dist/. The
libs target builds the dependencies with CMake.
Makefile
CC = emcc SRC = src/main.c src/game.c src/render.c OUT = dist/index.html INCLUDES = \ -I./libs/SDL3/include \ -I./libs/SDL_ttf \ -I./libs/freetype/include LIBS = \ -L./libs/SDL3/build-wasm \ -L./libs/SDL_ttf/build-wasm \ -L./libs/freetype/build-wasm \ -lSDL3 -lSDL3_ttf -lfreetype FLAGS = \ -s USE_WEBGL2=1 \ -s ASYNCIFY=1 \ -s ALLOW_MEMORY_GROWTH=1 \ -O2 all: $(OUT) $(OUT): $(SRC) mkdir -p dist $(CC) $(SRC) $(INCLUDES) $(LIBS) $(FLAGS) \ --shell-file web/shell.html \ --preload-file assets/ \ -o $(OUT) libs: cd libs/freetype && mkdir -p build-wasm && cd build-wasm && \ emcmake cmake .. -DBUILD_SHARED_LIBS=OFF && emmake make -j4 cd libs/SDL3 && mkdir -p build-wasm && cd build-wasm && \ emcmake cmake .. -DBUILD_SHARED_LIBS=OFF -DSDL_STATIC=ON && emmake make -j4 cd libs/SDL_ttf && mkdir -p build-wasm && cd build-wasm && \ emcmake cmake .. -DBUILD_SHARED_LIBS=OFF && emmake make -j4 clean: rm -rf dist/ .PHONY: all libs clean
Makefile recipe lines must be indented with a tab character, not spaces.
06 / GIT IGNORE RULES
Generated output and compiled library builds are excluded from version control.
.gitignore
# Build dist/ libs/SDL3/build-wasm/ libs/SDL_ttf/build-wasm/ libs/freetype/build-wasm/ # If libs are submodules, otherwise ignore everything # libs/ *.o *.a
07 / LIBRARY MANAGEMENT
Git submodules are the recommended way to track SDL3, SDL_ttf and FreeType at a fixed revision.
Adding the submodules
git submodule add https://github.com/libsdl-org/SDL.git libs/SDL3 git submodule add https://github.com/libsdl-org/SDL_ttf.git libs/SDL_ttf git submodule add https://gitlab.freedesktop.org/freetype/freetype.git libs/freetype
CI configuration
In the workflow, the checkout step must also clone the libraries:
- uses: actions/checkout@v3
with:
submodules: recursive # also clones the libs
Local clone (alternative)
cd C:\Users\killu mkdir my-project cd my-project mkdir libs cd libs git clone https://github.com/libsdl-org/SDL.git SDL3 git clone https://github.com/libsdl-org/SDL_ttf.git SDL_ttf git clone https://gitlab.freedesktop.org/freetype/freetype.git freetype
08 / BUILD AND DEPLOYMENT FLOW
Every push triggers GitHub Actions, which builds the dependencies and the application, then publishes the result.
Pipeline
push code
↓
GitHub Actions
↓
compile FreeType → SDL3 → SDL3_ttf → app
↓
generate dist/ (html + js + wasm + data)
↓
deploy to gh-pages
↓
https://youruser.github.io/my-project/
09 / WINDOWS SETUP (EMSDK)
On Windows, Emscripten is installed through emsdk.
Using cmd.exe or Git Bash is recommended instead
of PowerShell for Emscripten tasks.
Activating the SDK
cd C:\Users\killu\emsdk emsdk activate latest --permanent
Verifying the installation
emcc --version git --version cmake --version
Expected output for the first command is an
emcc version banner (Emscripten gcc/clang-like
replacement + linker).
10 / TROUBLESHOOTING
PowerShell PATH parse error
Running emsdk activate latest in PowerShell can
fail with an "unexpected token" error in
emsdk_set_env.ps1, caused by malformed quotes in
the PATH. Use cmd.exe instead, or run the
environment script through it:
cmd /k "C:\Users\killu\emsdk\emsdk_env.bat"
Truncated PATH after --permanent
The permanent activation can overwrite the PATH and drop existing entries. If Git or CMake are no longer found, add the missing entries back in the system environment variables (Path):
C:\Windows\system32 C:\Windows C:\Program Files\Git\cmd C:\Program Files\CMake\bin
Best practices
- Back up the PATH variable before running
--permanent. - Open a new terminal after changing environment variables.
- Run all Emscripten commands from the same shell.
- Check
emcc --versionbefore building the libraries.
11 / SOURCE CODE AND RESOURCES
SDL3: github.com/libsdl-org/SDL
SDL_ttf: github.com/libsdl-org/SDL_ttf
FreeType: gitlab.freedesktop.org/freetype/freetype
Source management: Git (submodules)
Hosting model: Static web hosting (GitHub Pages)
Documentation format: HTML
This document describes the project's general architecture and build process. Implementation-specific details should be verified against the actual source code.