# Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause # Copy in Qt HTML/JS launch files for apps. function(_qt_internal_wasm_add_target_helpers target) _qt_test_emscripten_version() get_target_property(targetType "${target}" TYPE) if("${targetType}" STREQUAL "EXECUTABLE") if(QT6_INSTALL_PREFIX) set(WASM_BUILD_DIR "${QT6_INSTALL_PREFIX}") elseif(QT_BUILD_DIR) set(WASM_BUILD_DIR "${QT_BUILD_DIR}") endif() get_target_property(output_name ${target} OUTPUT_NAME) if(output_name) set(_target_output_name "${output_name}") else() set(_target_output_name "${target}") endif() set(APPNAME ${_target_output_name}) _qt_internal_wasm_export_name_for_target(_export_name ${target}) set(APPEXPORTNAME ${_export_name}) # Shared library builds preload plugins and qml imports by default. # The json files are generated by scripts in qtbase/util/wasm/preload if (QT_FEATURE_shared) set(PRELOAD "preload: ['qt_plugins.json', 'qt_qml_imports.json'],") else() set(PRELOAD "") endif() get_target_property(target_output_directory ${target} RUNTIME_OUTPUT_DIRECTORY) get_target_property(is_test ${target} _qt_is_test_executable) get_target_property(is_manual_test ${target} _qt_is_manual_test) if(is_test AND NOT is_manual_test) # Keep in sync with testrunner_files in testlib/CMakeLists.txt configure_file("${WASM_BUILD_DIR}/libexec/batchedtestrunner.html" "${target_output_directory}/${_target_output_name}.html" COPYONLY) configure_file("${WASM_BUILD_DIR}/libexec/qtestoutputreporter.css" "${target_output_directory}/qtestoutputreporter.css" COPYONLY) configure_file("${WASM_BUILD_DIR}/libexec/batchedtestrunner.js" "${target_output_directory}/batchedtestrunner.js" COPYONLY) configure_file("${WASM_BUILD_DIR}/libexec/emrunadapter.js" "${target_output_directory}/emrunadapter.js" COPYONLY) configure_file("${WASM_BUILD_DIR}/libexec/qwasmjsruntime.js" "${target_output_directory}/qwasmjsruntime.js" COPYONLY) configure_file("${WASM_BUILD_DIR}/libexec/qwasmtestmain.js" "${target_output_directory}/qwasmtestmain.js" COPYONLY) configure_file("${WASM_BUILD_DIR}/libexec/qtestoutputreporter.js" "${target_output_directory}/qtestoutputreporter.js" COPYONLY) configure_file("${WASM_BUILD_DIR}/libexec/util.js" "${target_output_directory}/util.js" COPYONLY) else() get_target_property(no_wasm_files ${target} NO_WASM_DEFAULT_FILES) if(target_output_directory) set(_target_directory "${target_output_directory}") else() set(_target_directory "${CMAKE_CURRENT_BINARY_DIR}") endif() if (NOT no_wasm_files) configure_file("${WASM_BUILD_DIR}/plugins/platforms/wasm_shell.html" "${_target_directory}/${_target_output_name}.html" @ONLY) if(CMAKE_CONFIGURATION_TYPES) # if multiconfig generator add_custom_command( TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_target_directory}/${_target_output_name}.html" ${_target_directory}/$/${_target_output_name}.html ) add_custom_command( TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${WASM_BUILD_DIR}/plugins/platforms/qtloader.js" ${_target_directory}/$/qtloader.js ) add_custom_command( TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${WASM_BUILD_DIR}/plugins/platforms/qtlogo.svg" ${_target_directory}/$/qtlogo.svg ) else() configure_file("${WASM_BUILD_DIR}/plugins/platforms/qtloader.js" ${_target_directory}/qtloader.js COPYONLY) configure_file("${WASM_BUILD_DIR}/plugins/platforms/qtlogo.svg" ${_target_directory}/qtlogo.svg COPYONLY) if(QT_FEATURE_shared) set(TARGET_DIR "${_target_directory}") set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(QT_HOST_DIR "${QT_HOST_PATH}") set(QT_WASM_DIR "${WASM_BUILD_DIR}") set(QT_INSTALL_DIR "${QT6_INSTALL_PREFIX}") configure_file("${WASM_BUILD_DIR}/libexec/generate_default_preloads.sh.in" "${_target_directory}/generate_default_preloads_for_${target}.sh" @ONLY) endif() endif() endif() endif() if(QT_FEATURE_thread) set(POOL_SIZE 4) get_target_property(_tmp_poolSize "${target}" QT_WASM_PTHREAD_POOL_SIZE) if(_tmp_poolSize) set(POOL_SIZE ${_tmp_poolSize}) elseif(DEFINED QT_WASM_PTHREAD_POOL_SIZE) set(POOL_SIZE ${QT_WASM_PTHREAD_POOL_SIZE}) endif() target_link_options("${target}" PRIVATE "SHELL:-s PTHREAD_POOL_SIZE=${POOL_SIZE}") message(DEBUG "Setting PTHREAD_POOL_SIZE to ${POOL_SIZE} for ${target}") endif() # Set initial memory size, either from user setting or to a minimum amount required by Qt. get_target_property(_tmp_initialMemory "${target}" QT_WASM_INITIAL_MEMORY) if(_tmp_initialMemory) set(QT_WASM_INITIAL_MEMORY "${_tmp_initialMemory}") elseif(NOT DEFINED QT_WASM_INITIAL_MEMORY) set(QT_WASM_INITIAL_MEMORY "50MB") endif() target_link_options("${target}" PRIVATE "SHELL:-s INITIAL_MEMORY=${QT_WASM_INITIAL_MEMORY}") # Set maximum memory size, either from user setting or to 4GB (the 32-bit maximum) get_target_property(_tmp_maximumMemory "${target}" QT_WASM_MAXIMUM_MEMORY) if(_tmp_maximumMemory) set(QT_WASM_MAXIMUM_MEMORY "${_tmp_maximumMemory}") elseif(NOT DEFINED QT_WASM_MAXIMUM_MEMORY) if(QT_FEATURE_wasm_jspi) # Work around Emscripten >2GB and JSPI compatibility issue. set(QT_WASM_MAXIMUM_MEMORY "2GB") else() set(QT_WASM_MAXIMUM_MEMORY "4GB") endif() endif() target_link_options("${target}" PRIVATE "SHELL:-s MAXIMUM_MEMORY=${QT_WASM_MAXIMUM_MEMORY}") endif() endfunction() function(_qt_internal_add_wasm_extra_exported_methods target) get_target_property(wasm_extra_exported_methods "${target}" QT_WASM_EXTRA_EXPORTED_METHODS) set(wasm_default_exported_methods "UTF16ToString,stringToUTF16,JSEvents,specialHTMLTargets,FS,callMain") if(NOT wasm_extra_exported_methods) set(wasm_extra_exported_methods ${QT_WASM_EXTRA_EXPORTED_METHODS}) endif() if(wasm_extra_exported_methods) target_link_options("${target}" PRIVATE "SHELL:-s EXPORTED_RUNTIME_METHODS=${wasm_default_exported_methods},${wasm_extra_exported_methods}" ) else() # an errant dangling comma will break this target_link_options("${target}" PRIVATE "SHELL:-s EXPORTED_RUNTIME_METHODS=${wasm_default_exported_methods}" ) endif() # TODO: Remove these flags when LLVM got fixed - QTBUG-131279 if(QT_FEATURE_thread) target_link_options("${target}" PRIVATE "SHELL:-s EXPORTED_FUNCTIONS=_main,__embind_initialize_bindings") endif() endfunction() function(_qt_internal_set_wasm_export_name target) _qt_internal_wasm_export_name_for_target(export_name ${target}) target_link_options("${target}" PRIVATE "SHELL:-s MODULARIZE=1") target_link_options("${target}" PRIVATE "SHELL:-s EXPORT_NAME=${export_name}") endfunction() function(_qt_internal_wasm_export_name_for_target out target) get_target_property(export_name "${target}" QT_WASM_EXPORT_NAME) if(export_name) set(${out} "${export_name}" PARENT_SCOPE) else() # Modify target name to remove characters which are not valid in # JavaScript identifiers. # Prefix leading digit with '_' (2dpaint -> _2dpaint) if("${target}" MATCHES "^[0-9]") set(targ "_${target}") else() set(targ "${target}") endif() # Replace remaining non-legal chars with '_' (target-foo -> target_foo) string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" targ "${targ}") # Append "_entry" and return set(${out} "${targ}_entry" PARENT_SCOPE) endif() endfunction() function(_qt_internal_set_wasm_embind_option target) target_link_libraries("${target}" PRIVATE embind) endfunction() function(_qt_internal_finalize_wasm_app target) _qt_internal_set_wasm_export_name("${target}") _qt_internal_add_wasm_extra_exported_methods("${target}") _qt_internal_wasm_add_target_helpers("${target}") _qt_internal_set_wasm_embind_option("${target}") endfunction()