Files
puzzles/cmake/platforms/emscripten.cmake
Simon Tatham 43db4aa38e Support user preferences in the Emscripten frontend.
Here, user preferences are stored in localStorage, so that they can
persist when you come back to the same puzzle page later.

localStorage is global across a whole web server, which means we need
to take care to put our uses of it in a namespace reasonably unlikely
to collide with unrelated web pages on the same server. Ben suggested
that a good way to do this would be to store things in localStorage
under keys derived from location.pathname. In this case I've appended
a fragment id "#preferences" to that, so that space alongside it
remains for storing other things we might want in future (such as
serialised saved-game files used as quick-save slots).

When loading preferences, I've chosen to pass the whole serialised
preferences buffer from Javascript to C as a single C string argument
to a callback, rather than reusing the existing system for C to read
the save file a chunk at a time. Partly that's because preferences
data is bounded in size whereas saved games can keep growing; also
it's because the way I'm storing preferences data means it will be a
UTF-8 string, and I didn't fancy trying to figure out byte offsets in
the data on the JS side.

I think at this point I should stop keeping a list in the docs of
which frontends support preferences. Most of the in-tree ones do now,
and that means the remaining interesting frontends are ones I don't
have a full list of. At this moment I guess no out-of-tree frontends
support preferences (unless someone is _very_ quick off the mark), but
as and when that changes, I won't necessarily know, and don't want to
have to keep updating the docs when I find out.
2023-04-24 10:17:33 +01:00

156 lines
5.3 KiB
CMake

set(platform_common_sources emcc.c)
set(platform_gui_libs)
set(platform_libs)
set(CMAKE_EXECUTABLE_SUFFIX ".js")
set(WASM ON
CACHE BOOL "Compile to WebAssembly rather than plain JavaScript")
# The minimal versions here are the ones that Puzzles' own JavaScript
# is written for. For most browsers, that's the earliest version with
# WebAssembly support according to https://caniuse.com/wasm. For
# Firefox we go back to Firefox 48 because that's what KaiOS 2.5 is
# based on.
set(MIN_FIREFOX_VERSION 48 CACHE STRING
"Oldest major version of Firefox to target")
set(MIN_SAFARI_VERSION 110000 CACHE STRING
"Oldest version of desktop Safari to target (XXYYZZ for version XX.YY.ZZ)")
set(MIN_EDGE_VERSION 16 CACHE STRING
"Oldest version of (non-Chromium-based) Edge to target")
set(MIN_CHROME_VERSION 57 CACHE STRING
"Oldest version of Chrome to target")
find_program(HALIBUT halibut)
if(NOT HALIBUT)
message(WARNING "HTML documentation cannot be built (did not find halibut)")
endif()
set(emcc_export_list
# Event handlers for mouse and keyboard input
_mouseup
_mousedown
_mousemove
_key
# Callback when the program activates timing
_timer_callback
# Callback from button presses in the UI outside the canvas
_command
# Game-saving and game-loading functions
_get_save_file
_free_save_file
_load_game
# Callbacks to return values from dialog boxes
_dlg_return_sval
_dlg_return_ival
# Callbacks when the resizing controls are used
_resize_puzzle
_restore_puzzle_size
# Callback when device pixel ratio changes
_rescale_puzzle
# Callback for loading user preferences
_prefs_load_callback
# Main program, run at initialisation time
_main)
list(TRANSFORM emcc_export_list PREPEND \")
list(TRANSFORM emcc_export_list APPEND \")
string(JOIN "," emcc_export_string ${emcc_export_list})
set(CMAKE_C_LINK_FLAGS "\
-s ALLOW_MEMORY_GROWTH=1 \
-s ENVIRONMENT=web \
-s EXPORTED_FUNCTIONS='[${emcc_export_string}]' \
-s EXPORTED_RUNTIME_METHODS='[cwrap]' \
-s MIN_FIREFOX_VERSION=${MIN_FIREFOX_VERSION} \
-s MIN_SAFARI_VERSION=${MIN_SAFARI_VERSION} \
-s MIN_EDGE_VERSION=${MIN_EDGE_VERSION} \
-s MIN_CHROME_VERSION=${MIN_CHROME_VERSION} \
-s MIN_NODE_VERSION=0x7FFFFFFF \
-s STRICT_JS=1")
if(WASM)
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -s WASM=1")
else()
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -s WASM=0")
endif()
set(build_cli_programs FALSE)
set(build_gui_programs FALSE)
function(get_platform_puzzle_extra_source_files OUTVAR NAME)
set(${OUTVAR} PARENT_SCOPE)
endfunction()
function(set_platform_gui_target_properties TARGET)
endfunction()
function(set_platform_puzzle_target_properties NAME TARGET)
em_link_pre_js(${TARGET} ${CMAKE_SOURCE_DIR}/emccpre.js)
em_link_js_library(${TARGET} ${CMAKE_SOURCE_DIR}/emcclib.js)
endfunction()
function(build_platform_extras)
if(HALIBUT)
set(help_dir ${CMAKE_CURRENT_BINARY_DIR}/help)
add_custom_command(OUTPUT ${help_dir}/en
COMMAND ${CMAKE_COMMAND} -E make_directory ${help_dir}/en)
add_custom_command(OUTPUT ${help_dir}/en/index.html
COMMAND ${HALIBUT} --html -Chtml-template-fragment:%k
${CMAKE_CURRENT_SOURCE_DIR}/puzzles.but
${CMAKE_CURRENT_SOURCE_DIR}/emcccopy.but
DEPENDS
${help_dir}/en
${CMAKE_CURRENT_SOURCE_DIR}/puzzles.but
${CMAKE_CURRENT_SOURCE_DIR}/emcccopy.but
WORKING_DIRECTORY ${help_dir}/en)
add_custom_target(kaios_help ALL
DEPENDS ${help_dir}/en/index.html)
endif()
# This is probably not the right way to set the destination.
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH
"Installation path" FORCE)
add_custom_target(kaios-extras ALL)
foreach(name ${puzzle_names})
add_custom_command(
OUTPUT ${name}-manifest.webapp
COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/kaios/manifest.pl
"${name}" "${displayname_${name}}" "${description_${name}}"
"${objective_${name}}" > "${name}-manifest.webapp"
VERBATIM
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/kaios/manifest.pl)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/kaios)
add_custom_command(
OUTPUT ${name}-kaios.html
COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/kaios/apppage.pl
"${name}" "${displayname_${name}}" > "${name}-kaios.html"
VERBATIM
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/kaios/apppage.pl)
add_custom_target(${name}-kaios-extras
DEPENDS ${name}-manifest.webapp ${name}-kaios.html)
add_dependencies(kaios-extras ${name}-kaios-extras)
install(TARGETS ${name} DESTINATION kaios/${name})
# Release builds generate an initial memory image alongside the
# JavaScript, but CMake doesn't seem to know about it to install
# it.
install(FILES $<TARGET_FILE:${name}>.mem OPTIONAL
DESTINATION kaios/${name})
install(FILES ${ICON_DIR}/${name}-56kai.png ${ICON_DIR}/${name}-112kai.png
DESTINATION kaios/${name} OPTIONAL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}-kaios.html
RENAME ${name}.html
DESTINATION kaios/${name})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}-manifest.webapp
RENAME manifest.webapp
DESTINATION kaios/${name})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/kaios/kaiads-glue.js
DESTINATION kaios/${name})
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/help OPTIONAL
DESTINATION kaios/${name})
endforeach()
endfunction()