Skip to content

Instantly share code, notes, and snippets.

@ericoporto
Forked from WesThorburn/1.Instructions.md
Created October 19, 2020 02:10
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ericoporto/8ce679ecb862a12795156d31f3ecac49 to your computer and use it in GitHub Desktop.
Save ericoporto/8ce679ecb862a12795156d31f3ecac49 to your computer and use it in GitHub Desktop.
Linux: Compile C++ to WebAssembly and JavaScript using Emscripten and CMake

Linux: Compile C++ to WebAssembly and JavaScript using Emscripten and CMake

Download and Install Emscripten

  • My preferred installation location is /home/user
  • Get the latest sdk: git clone https://github.com/emscripten-core/emsdk.git
  • Enter the cloned directory: cd emsdk
  • Install the lastest sdk tools: ./emsdk install latest
  • Activate the latest sdk tools: ./emsdk activate latest
  • Activate path variables: source ./emsdk_env.sh
  • Configure emsdk in your bash profile by running: echo 'source "/home/user/emsdk/emsdk_env.sh"' >> $HOME/.bash_profile

Your project structure

build/  
include/  
src/  
public/  
CMakeLists.txt  
  • Build directory starts empty, place header (.h) files inside /include and source (.cpp) files inside /src.

  • The public folder is where the output files will go, also keep the index.html, images and css here too.

  • CMakeLists.txt stays the root directory.

  • In the root directory, set the CMAKE Toolchain file by running: CMAKE_TOOLCHAIN_FILE=/home/user/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake Ensure you update your path with the location of your emsdk installation location

Compile to WASM (default)

cd build  
emcmake cmake ..  
make

Compile to JS

cd build  
emcmake cmake .. -DJS_ONLY=ON  
make

After Editing Files

make

After Adding/Removing Files

emcmake cmake ..  
make

If the emsdk directory is moved

  • From the project root directory run: CMAKE_TOOLCHAIN_FILE=[/path/to]/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake

  • Then from the /build directory, run: emcmake cmake ..

  • Output .js, .wasm.js and wasm.wasm files will appear in the public directory.

  • Make sure you web server serves from /public.

  • The index.html will load a.js if WebAssembly isn't supported by the client browser.

If the error: fatal error: emscripten.h: No such file or directory or The program 'emcmake' is currently not installed or The program 'emconfigure' is currently not installed is seen, check that your CMAKE_TOOLCHAIN_FILE path is correct as this is often the cause. You could also try re-installing by removing the /build directory, and run through emscripten installation again, making sure you run: source ./emsdk_env.sh at end. Then recreate the /build directory and run emcmake cmake .. and make again.

project (client)
cmake_minimum_required(VERSION 3.5.1)
option(JS_ONLY "Compiles to native JS (No WASM)" OFF)
add_definitions(-std=c++11 -O3)
include_directories(include)
file(GLOB SOURCES src/*.cpp)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/public")
add_executable(a ${SOURCES})
if(JS_ONLY)
message(STATUS "Setting compilation target to native JavaScript")
set(CMAKE_EXECUTABLE_SUFFIX ".js")
set_target_properties(a PROPERTIES LINK_FLAGS "-s WASM=0 -s EXPORTED_FUNCTIONS='[_main]'")
else(JS_ONLY)
message(STATUS "Setting compilation target to WASM")
set(CMAKE_EXECUTABLE_SUFFIX ".wasm.js")
set_target_properties(a PROPERTIES LINK_FLAGS "-s WASM=1 -s EXPORTED_FUNCTIONS='[_main]'")
endif(JS_ONLY)
<!DOCTYPE html>
<html>
<head></head>
<body>
<script>
!function(e, t){
console.log("Loading client...");
var n = "a.wasm.js";
if(!e.WebAssembly){
n = "a.js"
}
console.log("Script set to " + n);
var o = t.createElement("script");
o.async = !0, o.type = "text/javascript", o.src = n, o.onerror = function(t) {
console.error("Script Error"), console.error(t), setTimeout(function() {
e.location.reload(!0)
}, 3e3)
};
var r = t.getElementsByTagName("script")[0];
r.parentNode.insertBefore(o, r)
}(window, document);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment