- Clone and install SDK
- save
$EMSDKas environment var in your.profile/.zprofile/.bashrc/zshrcto make it easier later installwill run for a long time
- save
git clone --depth=1 --recurse-submodules --shallow-submodules https://github.com/emscripten-core/emsdk.git
cd emsdk
export EMSDK=$(pwd) # save in you .profile or .bashrc/.zshrc
$EMSDK/emsdk install --shallow sdk-main-64bit # this takes a long time
# ??? # $EMSDK/emsdk install --shallow emscripten-main-64bit- Anytime you want to use Emscripten, activate the enviroment
$EMSDK/emsdk activate sdk-main-64bit
# ??? # $EMSDK/emsdk activate emscripten-main-64bit
$EMSDK/source "$EMSDK/emsdk_env.sh"- To compile C use
emccand C++ useem++- options
-smay vary between projects --preload-file ../assetssaves all files inassetsas one large .data file that can be loaded by the program
- options
$EMSDK/source "$EMSDK/emsdk_env.sh"
mkdir -p build_em
cd build_em
export ProjectName=MyProject
em++ -std=c++17 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_LIBPNG=1 ../*.cpp -o $ProjectName.html --preload-file ../assets- If the project uses
CMakeLists.txt, configure withemcmake cmake ..
$EMSDK/source "$EMSDK/emsdk_env.sh"
mkdir -p build_emcmake
cd build_emcmake
emcmake cmake ..
cmake --build . -j10- Emscripten will generate files
.data,.html,.jsand.wasm - Run with
$EMSDK/source "$EMSDK/emsdk_env.sh"
emrun $ProjectName.htmlor
python -m http.server 8080Emscripten can't open shared libraries .so/..dll files when linking, need to get the source code or install STATIC libraries in $EMSDK/emscripten/main/cache/sysroot (on Windows %EMSDK%/upstream/emscripten/cache/sysroot).
In CMakeLists.txt, add the library source directory add_subdirectory(${SDL3_SOURCE} SDL-build).
# with source code
add_subdirectory(${SDL3_SOURCE} SDL)
add_subdirectory(${SDL3IMAGE_SOURCE} SDL_image)
add_subdirectory(${SDL3MIXER_SOURCE} SDL_mixer)
add_subdirectory(${GLM_SOURCE} glm)
add_subdirectory(${TINYXML2_SOURCE} tinyxml2)
# or .a/.lib installed in $EMSDK/emscripten/main/cache/sysroot
find_package(SDL3 REQUIRED)
find_package(SDL3_image REQUIRED)
find_package(SDL3_mixer REQUIRED)
find_package(glm REQUIRED)
find_package(tinyxml2 REQUIRED)In CLion, add Emscripten in a Toolchain, and add a CMake profile that uses the toolchain
- open
Settings->Buid, Execution, Deployment->Toolchains - Click on Add button
+- Name:
Emscripten(will be used in next step) - Environment file: put the path
$EMSDK/emsdk_env.sh - CMake: we need to execute
emcmake cmakewhen configuring, but onlycmakewhen building.- create the script below, put it in
$EMSDK/emscripten/main(or anywhere in$PATH). - Use this script as
CMakein CLion.
Windows#!/bin/sh for arg in "$@"; do # if there is --target, we are building if [ "$arg" = "--target" ]; then cmake $@ exit $? fi done # there is no --target, we are configuring emcmake cmake $@
@echo off setlocal set found_target=0 rem Loop through all parameters for %%a in (%*) do ( if "%%a"=="--target" set found_target=1 ) if %found_target%==1 ( cmake %* ) else ( emcmake cmake %* ) endlocal
- create the script below, put it in
- Build Tool: leave blank (default ninja)
- C Compiler:
emcc - C++ Compiler:
em++ - Debugger: leave as Bundled GDB
- Name:
- open
Settings->Buid, Execution, Deployment->CMake - Click on Add button
+- Name:
Debug-EM(any name you want) - Build type: choose
Debug/Release - Toolchain:
Emscripten(the name you chose as Toolchain above) - Generator: leave Use default
- CMake options: these options are added by default by
emcmake, but not by CLion- there is no need to add these if you are using the CMake script above.
-DCMAKE_TOOLCHAIN_FILE=$EMSDK/emscripten/main/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_CROSSCOMPILING_EMULATOR=$EMSDK/node/20.18.0_64bit/bin/node- Add more options for your project
- All other options will vary depending on each project
- Name:
Choose between these options (I don't know if they can be together).
embed-filewith every single file
foreach (res IN LISTS DATA_FILES)
get_filename_component(res_name "${res}" NAME)
get_filename_component(res_dir "${res}" DIRECTORY)
string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/ "" RELPATH ${res_dir})
target_link_options(sdl3-demo PRIVATE "SHELL:--embed-file \"${res}@${RELPATH}/${res_name}\"")
endforeach ()preload-file- concatenate all files into a single Blob
target_link_options(sdl3-demo PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/data@data")More robust solution:
set(resources_dir ${CMAKE_CURRENT_SOURCE_DIR}/resources)
if (EXISTS ${resources_dir})
# The local resources path needs to be mapped to /resources virtual path
string(APPEND resources_dir "@resources")
target_link_options(${PROJECT_NAME} PRIVATE --preload-file "${resources_dir}")
endif ()Set target suffix to .html, and enable -sALLOW_MEMORY_GROWTH=1.
set_property(TARGET ${MYPROGRAM} PROPERTY SUFFIX ".html")
target_link_options(${MYPROGRAM} PRIVATE -sALLOW_MEMORY_GROWTH=1)Compile options
-g3maximum debug info (keeps everything, including local var. There are 0,1,2,3.
Link options
-gsource-map --source-map-base http://127.0.0.1:8081/specifically tells Emscripten to emit a .wasm.map file that browsers can use to show your original C/C++ source in DevTools-sALLOW_MEMORY_GROWTH=1-sEXPORTED_RUNTIME_METHODS=[requestFullscreen]allow page to open Fullscreen-sUSE_GLFW=3use GLFW 3 from Emscripten dependencies-sSTACK_SIZE=131072increase stack size (default 65536)-sASYNCIFY=1allow "emscripten_sleep()" in main thread-sASSERTIONS=2enable assertions (good for logic errors, null derefs, etc.)--shell-file "$ENV{EMSCRIPTEN}/src/shell.html"select a different shell file-sSAFE_HEAP=1helps detect invalid memory reads/writes by instrumenting memory access
Default page created by Emscripten uses a template called shell.html located at $EMSDK/emscripten/main/src/shell.html.
It wraps your program in a html page with a Emscripten banner and shows a console output.
Emscripten provides a shell_minimal.html, but it just reduces the banner size.
I have created the file below with a bare minimal shell. It only centralizes the program on the screen.
From this bare minimal, you can customize it for your project (add background, favicon, header, footer, etc).
Tell Emscripten linker to use the new shell.
target_link_options(${MYPROGRAM} PRIVATE --shell-file "/path/to/my_shell.html")On Linux we can use "$ENV{EMSCRIPTEN}/src/shell.html", but on Windows it is "${EMSCRIPTEN_ROOT_PATH}/../../emscripten/main/src/shell.html"