ci: Add WASM build + deploy workflow for live ImGui web demo

Add .github/workflows/deploy-wasm.yml that:
- Installs Emscripten SDK on ubuntu-latest
- Builds example_sdl2_opengl3 with Makefile.emscripten using -sSINGLE_FILE
  (all WASM+JS embedded in a single .html file, no separate .wasm/.js)
- Uses custom shell_imgui_xl.html with loading spinner and WebGL context
  loss handling
- Deploys to gh-pages/wasm/ directory via peaceiris/actions-gh-pages

The resulting live demo at turtle-pb.github.io/imgui_xl/wasm/index.html
will show the ACTUAL Dear ImGui demo window running in the browser via
WebAssembly — not a canvas simulation, but real compiled C++ ImGui.

Triggers on pushes to master that touch ImGui source files, the SDL2/
OpenGL3 backend, the example, or the shell template.
Also supports manual workflow_dispatch.
This commit is contained in:
Turtle Dove 2026-07-14 23:21:15 -05:00
parent 1cd495b522
commit 5a7279bcf0
2 changed files with 125 additions and 0 deletions

63
.github/workflows/deploy-wasm.yml vendored Normal file
View File

@ -0,0 +1,63 @@
name: Deploy ImGui WASM to GitHub Pages
on:
push:
branches: [master]
paths:
- 'imgui.cpp'
- 'imgui.h'
- 'imgui_demo.cpp'
- 'imgui_draw.cpp'
- 'imgui_tables.cpp'
- 'imgui_widgets.cpp'
- 'backends/imgui_impl_sdl2.*'
- 'backends/imgui_impl_opengl3.*'
- 'examples/example_sdl2_opengl3/main.cpp'
- 'examples/example_sdl2_opengl3/Makefile.emscripten'
- 'examples/libs/emscripten/**'
- '.github/workflows/deploy-wasm.yml'
workflow_dispatch:
permissions:
contents: write
pages: write
jobs:
build-and-deploy:
runs-on: ubuntu-latest
name: Build ImGui WASM and deploy to gh-pages
steps:
- name: Checkout imgui_xl
uses: actions/checkout@v6
- name: Install Emscripten
run: |
wget -q https://github.com/emscripten-core/emsdk/archive/master.tar.gz
tar -xzf master.tar.gz
emsdk-master/emsdk update
emsdk-master/emsdk install latest
emsdk-master/emsdk activate latest
sudo apt-get install build-essential
- name: Build SDL2+OpenGL3 ImGui WASM
run: |
pushd emsdk-master
source ./emsdk_env.sh
popd
# Build with custom shell, single-file output (everything embedded in one .html)
make -C examples/example_sdl2_opengl3 -f Makefile.emscripten \
LDFLAGS+="-sSINGLE_FILE --shell-file ../libs/emscripten/shell_imgui_xl.html"
# Verify output
ls -la examples/example_sdl2_opengl3/web/
- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages
publish_dir: examples/example_sdl2_opengl3/web
destination_dir: wasm
keep_files: true

View File

@ -0,0 +1,62 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<title>Dear ImGui — Live Web Demo (imgui_xl)</title>
<style>
body { margin: 0; background-color: #0d0e12; overflow: hidden; font-family: -apple-system, sans-serif; }
.emscripten {
position: absolute; top: 0; left: 0; margin: 0; border: 0;
width: 100%; height: 100%; overflow: hidden; display: block;
}
#canvas:focus { outline: none; }
#loading {
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
text-align: center; color: #6b7080; font-size: 14px; z-index: 10;
}
#loading .spinner {
width: 40px; height: 40px; border: 3px solid #1c1f2b;
border-top-color: #4a9eff; border-radius: 50%;
animation: spin 1s linear infinite; margin: 0 auto 16px;
}
@keyframes spin { to { transform: rotate(360deg); } }
#loading h1 { color: #e8eaf0; font-size: 18px; margin: 0 0 8px; }
#loading p { margin: 0; }
#loading .hint { font-size: 12px; margin-top: 12px; color: #4a6fa5; }
</style>
</head>
<body>
<div id="loading">
<div class="spinner"></div>
<h1>Dear ImGui — Live Web Demo</h1>
<p>Loading WASM build...</p>
<p class="hint">Click the canvas to interact. Right-click works too.</p>
</div>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
<script type='text/javascript'>
var Module = {
preRun: [],
postRun: [],
print: function(text) { console.log(text); },
printErr: function(text) { console.error(text); },
canvas: (function() {
var canvas = document.getElementById('canvas');
canvas.addEventListener("webglcontextlost", function(e) {
alert('WebGL context lost. Please reload the page.');
e.preventDefault();
}, false);
return canvas;
})(),
onRuntimeInitialized: function() {
var loading = document.getElementById('loading');
if (loading) loading.style.display = 'none';
},
setStatus: function(text) { console.log("status: " + text); },
monitorRunDependencies: function(left) {}
};
window.onerror = function() { console.log("onerror: " + event); };
</script>
{{{ SCRIPT }}}
</body>
</html>