Created
January 28, 2021 01:16
-
-
Save devappd/039722ab383a88212c1c7648c04dc84e to your computer and use it in GitHub Desktop.
CMake Emscripten sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# CMakeLists.txt | |
# Entry-point for build configuration. | |
# | |
# Copyright (c) 2021 David Apollo (77db70f775fa0b590889c45371a70a1d23e99869d4565976a5207c11606fb6aa) | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining | |
# a copy of this software and associated documentation files (the | |
# "Software"), to deal in the Software without restriction, including | |
# without limitation the rights to use, copy, modify, merge, publish, | |
# distribute, sublicense, and/or sell copies of the Software, and to | |
# permit persons to whom the Software is furnished to do so, subject to | |
# the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be | |
# included in all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
######################################################################## | |
# Config | |
######################################################################## | |
set(PUBLISHER_NAME "MyCompany") | |
set(PUBLISHER_LONG_NAME "My Company Inc.") | |
set(MAIN_NAME "MyProject") | |
set(MAIN_LONG_NAME "My Project") | |
set(MAIN_VERSION "1.0.0") | |
set(MAIN_DESCRIPTION "My description.") | |
set(TARGET_NAME "${MAIN_NAME}") | |
set(PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}") | |
######################################################################## | |
# Setup | |
######################################################################## | |
project("${MAIN_NAME}" | |
VERSION "${MAIN_VERSION}" | |
LANGUAGES C CXX | |
) | |
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti -Wall") | |
set(CMAKE_CXX_STANDARD 11) | |
set(CMAKE_CXX_STANDARD_REQUIRED ON) | |
set(CMAKE_CXX_EXTENSIONS OFF) | |
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") | |
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") | |
add_executable("${TARGET_NAME}") | |
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "${TARGET_NAME}") | |
target_sources("${TARGET_NAME}" | |
PRIVATE "${PROJECT_PATH}/main.cpp" | |
# Other sources... | |
) | |
if(${CMAKE_SYSTEM_NAME} MATCHES "Emscripten") | |
include(SetupEmscripten) | |
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SetupEmscripten.cmake | |
# Build configuration specific to Emscripten. | |
# | |
# Copyright (c) 2021 David Apollo (77db70f775fa0b590889c45371a70a1d23e99869d4565976a5207c11606fb6aa) | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining | |
# a copy of this software and associated documentation files (the | |
# "Software"), to deal in the Software without restriction, including | |
# without limitation the rights to use, copy, modify, merge, publish, | |
# distribute, sublicense, and/or sell copies of the Software, and to | |
# permit persons to whom the Software is furnished to do so, subject to | |
# the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be | |
# included in all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
######################################################################## | |
# Config | |
######################################################################## | |
IF(NOT DEFINED EMCC_OUTPUT_TYPE) | |
set(EMCC_OUTPUT_TYPE ".js" CACHE STRING "Output file type for target: .mjs, .js, .html, .a") | |
endif() | |
IF(NOT DEFINED EMCC_MODULARIZE) | |
set(EMCC_MODULARIZE OFF CACHE BOOL "Output JS as an object module.") | |
endif() | |
IF(NOT DEFINED EMCC_USE_PTHREADS) | |
set(EMCC_USE_PTHREADS OFF CACHE BOOL "Enable multithreading.") | |
endif() | |
if(NOT DEFINED EMCC_ASYNCIFY) | |
set(EMCC_ASYNCIFY OFF CACHE BOOL "Enable compatibility with browser async behavior.") | |
endif() | |
if(NOT DEFINED EMCC_WEBGL2) | |
set(EMCC_WEBGL2 ON CACHE BOOL "Enable support for WebGL 2.") | |
endif() | |
# This should be set by the CMake project, not the user. | |
# if(NOT DEFINED EMCC_EXPORTS) | |
# set(EMCC_EXPORTS "" CACHE STRING | |
# "Comma-separated list of C/++ function names to expose to JS. Here, all names are prefixed by underscore. E.g., '_function_name','_function_name2','_function_name3'") | |
# endif() | |
if(NOT DEFINED EMCC_EXTRA_EXPORTS) | |
set(EMCC_EXTRA_EXPORTS "" CACHE STRING | |
"Comma-separated list of Emscripten function names to expose to JS. Do not prefix names. E.g., 'function_name','function_name2','function_name3'") | |
endif() | |
if(NOT DEFINED EMCC_PRELOAD_PATH) | |
set(EMCC_PRELOAD_PATH "" CACHE STRING | |
"Path to directory or file to preload on Emscripten startup. If path is a directory, then all files in the directory will be preloaded.") | |
endif() | |
if(NOT DEFINED EMCC_SHELL_FILE) | |
set(EMCC_SHELL_FILE "" CACHE STRING | |
"Path to shell HTML file. Optional.") | |
endif() | |
if(NOT DEFINED EMCC_SINGLE_FILE) | |
set(EMCC_SINGLE_FILE OFF CACHE BOOL "Compile one output file that combines JS, WASM, and HTML.") | |
endif() | |
######################################################################## | |
# Parameter Setup | |
######################################################################## | |
if(NOT DEFINED EMCC_INITIAL_MEMORY) | |
set(EMCC_INITIAL_MEMORY "8192000") | |
# CACHE STRING "Memory size to initialize Emscripten. Multiple of 65536.") | |
endif() | |
if(CMAKE_BUILD_TYPE MATCHES "Debug") | |
add_definitions(-DDEBUG) | |
set(OPTIMIZATION_LEVEL "0") | |
set(DEBUG_FLAG "-g") | |
# set(WEBGL_DEBUG "-s GL_ASSERTIONS=1 ") | |
else() | |
set(OPTIMIZATION_LEVEL "3") | |
set(DEBUG_FLAG "") | |
endif() | |
if (EMCC_MODULARIZE) | |
set(MODULARIZE "-s MODULARIZE=1 ") | |
endif() | |
if (EMCC_USE_PTHREADS) | |
set(USE_PTHREADS "-s USE_PTHREADS=1 ") | |
set(ENVIRONMENT "-s ENVIRONMENT='web,worker' -s EXPORT_NAME=Mod ") | |
if (EMCC_MODULARIZE) | |
set(MODULARIZE "${MODULARIZE} -s EXPORT_ES6=1 ") | |
endif() | |
else() | |
set(ENVIRONMENT "-s ENVIRONMENT='web' ") | |
endif() | |
if (EMCC_ASYNCIFY) | |
# Add trailing space for compiler parsing | |
set(ASYNCIFY "-s ASYNCIFY=1 ") | |
add_definitions(-DASYNCIFY) | |
else() | |
set(ASYNCIFY "") | |
endif() | |
if(EMCC_WEBGL2) | |
set(WEBGL2 "-s USE_WEBGL2=1 ") | |
add_definitions(-DUSE_ES3) | |
else() | |
set(WEBGL2 "") | |
endif() | |
# Set preload path | |
if(EXISTS "${EMCC_PRELOAD_PATH}") | |
# Dodge error about path below current directory | |
file(COPY "${EMCC_PRELOAD_PATH}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") | |
# Get base name | |
get_filename_component(EMCC_PRELOAD_NAME "${EMCC_PRELOAD_PATH}" NAME) | |
# Prepare linker flag | |
if(IS_DIRECTORY "${EMCC_PRELOAD_PATH}") | |
set(EMCC_PRELOAD "--preload-file \"${CMAKE_CURRENT_BINARY_DIR}/${EMCC_PRELOAD_NAME}\"@\"/\"") | |
else() | |
set(EMCC_PRELOAD "--preload-file \"${CMAKE_CURRENT_BINARY_DIR}/${EMCC_PRELOAD_NAME}\"@\"/${EMCC_PRELOAD_NAME}\"") | |
endif() | |
elseif(EMCC_PRELOAD_PATH) # Is non-empty | |
message(SEND_ERROR "Preload path not found:\n" | |
" ${EMCC_PRELOAD_PATH}") | |
endif() | |
if(EXISTS "${EMCC_SHELL_FILE}") | |
# Retrieve latest copy into build cache | |
file(COPY "${EMCC_SHELL_FILE}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") | |
# Get base name | |
get_filename_component(EMCC_SHELL_NAME "${EMCC_SHELL_FILE}" NAME) | |
# Build parameter | |
set(EMCC_SHELL "--shell-file \"${CMAKE_CURRENT_BINARY_DIR}/${EMCC_SHELL_NAME}\"") | |
elseif(EMCC_SHELL_FILE) # Is non-empty | |
message(SEND_ERROR "Shell HTML file not found:\n" | |
" ${EMCC_SHELL_FILE}") | |
endif() | |
if(EMCC_SINGLE_FILE) | |
set(SINGLE_FILE "-s SINGLE_FILE=1") | |
endif() | |
######################################################################## | |
# Compiler Setup | |
######################################################################## | |
add_definitions(-DEMSCRIPTEN) | |
# Export functions to JS. | |
# First set standard list, not closed by bracket so we can append | |
set(EMCC_EXPORT_LIST "\"['_main',") | |
# Now append custom exports | |
if(EMCC_EXPORTS) | |
set(EMCC_EXPORT_LIST "${EMCC_EXPORT_LIST},${EMCC_EXPORTS}]\"") | |
else() | |
set(EMCC_EXPORT_LIST "${EMCC_EXPORT_LIST}]\"") | |
endif() | |
set(EMCC_EXTRA_EXPORT_LIST "\"['ccall'") | |
if(EMCC_EXTRA_EXPORTS) | |
set(EMCC_EXTRA_EXPORT_LIST "${EMCC_EXTRA_EXPORT_LIST},${EMCC_EXTRA_EXPORTS}]\"") | |
else() | |
set(EMCC_EXTRA_EXPORT_LIST "${EMCC_EXTRA_EXPORT_LIST}]\"") | |
endif() | |
# Set compiler args | |
# We use semicolons so that CMake does not pass the entire string as one quoted flag | |
set(EMCC_ARGS "SHELL: \ | |
${ASYNCIFY} \ | |
-O${OPTIMIZATION_LEVEL} \ | |
--llvm-opts ${OPTIMIZATION_LEVEL} \ | |
${DEBUG_FLAG} \ | |
-s FULL_ES2=1 \ | |
-s FULL_ES3=1 \ | |
-s DEMANGLE_SUPPORT=1 \ | |
${USE_PTHREADS}" | |
) | |
# Set linker args | |
set(EMCC_LINK_ARGS "SHELL: \ | |
${SINGLE_FILE} \ | |
-s TOTAL_MEMORY=${EMCC_INITIAL_MEMORY} \ | |
-s ALLOW_MEMORY_GROWTH=1 \ | |
-s EXPORTED_FUNCTIONS=${EMCC_EXPORT_LIST} \ | |
-s EXTRA_EXPORTED_RUNTIME_METHODS=${EMCC_EXTRA_EXPORT_LIST} \ | |
${ENVIRONMENT} \ | |
${USE_PTHREADS} \ | |
${WEBGL2} \ | |
${WEBGL_DEBUG} \ | |
${EMCC_PRELOAD} ${EMCC_SHELL} \ | |
${MODULARIZE} \ | |
-lidbfs.js" | |
) | |
######################################################################## | |
# Libraries | |
######################################################################## | |
target_compile_options(${TARGET_NAME} PRIVATE "SHELL:-s USE_SDL=2 -s USE_SDL_MIXER=2") | |
target_link_options(${TARGET_NAME} PRIVATE "SHELL:-s USE_SDL=2 -s USE_SDL_MIXER=2") | |
######################################################################## | |
# Install target | |
######################################################################## | |
if(NOT INSTALL_SUBPREFIX) | |
set(INSTALL_SUBPREFIX ".") | |
endif() | |
if(NOT DEFINED OUTPUT_NAME) | |
set(OUTPUT_NAME "${TARGET_NAME}") | |
endif() | |
# Set install path to project dir by default | |
get_filename_component(ABS_PROJECT_PATH "${PROJECT_PATH}" ABSOLUTE) | |
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | |
set (CMAKE_INSTALL_PREFIX "${PROJECT_PATH}/emscripten/data" CACHE PATH "Install location for the program." FORCE) | |
endif() | |
# Print info message | |
get_filename_component(ABS_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}" ABSOLUTE) | |
message(STATUS "Project install directory is set to:\n" | |
"\n" | |
" ${ABS_INSTALL_PATH}/${INSTALL_SUBPREFIX}\n" | |
) | |
# Install program binaries and preloaded data | |
install(DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/" | |
DESTINATION "${INSTALL_SUBPREFIX}" | |
FILES_MATCHING | |
PATTERN "${OUTPUT_NAME}.data" | |
PATTERN "${OUTPUT_NAME}.html" | |
PATTERN "${OUTPUT_NAME}.js" | |
PATTERN "${OUTPUT_NAME}.worker.js" | |
PATTERN "${OUTPUT_NAME}.mjs" | |
PATTERN "${OUTPUT_NAME}.a" | |
PATTERN "${OUTPUT_NAME}.wasm" | |
PATTERN "${OUTPUT_NAME}.wasm.map" | |
) | |
######################################################################## | |
# Wire it all together | |
######################################################################## | |
set(CMAKE_EXECUTABLE_SUFFIX ${EMCC_OUTPUT_TYPE}) | |
target_compile_options(${TARGET_NAME} PRIVATE ${EMCC_ARGS}) | |
target_link_options(${TARGET_NAME} PRIVATE ${EMCC_ARGS}) | |
target_link_options(${TARGET_NAME} PRIVATE ${EMCC_LINK_ARGS}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment