wasm: add cmake build support

A few configure defines get changed:
QMAKE_WASM_PTHREAD_POOL_SIZE is now QT_WASM_PTHREAD_POOL_SIZE
QMAKE_WASM_TOTAL_MEMORY is now QT_WASM_INITIAL_MEMORY
QMAKE_WASM_SOURCE_MAP_BASE is now QT_WASM_SOURCE_MAP_BASE

device-option EMSCRIPTEN_ASYNCIFY=1 is QT_EMSCRIPTEN_ASYNCIFY=1

To create source maps for debugging. use
device-option QT_WASM_SOURCE_MAP=1

Task-number: QTBUG-78647
Change-Id: If9f30cd7fb408c386d6d69b5f7b1beecf1ab44b5
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Lorn Potter 2020-09-03 18:29:41 +10:00
parent 5bf4133c17
commit 4972fdb350
26 changed files with 370 additions and 42 deletions

View File

@ -341,7 +341,7 @@ qt_feature("android-style-assets" PRIVATE
)
qt_feature("shared" PUBLIC
LABEL "Building shared libraries"
AUTODETECT NOT UIKIT
AUTODETECT NOT UIKIT AND NOT WASM
CONDITION BUILD_SHARED_LIBS
)
qt_feature_definition("shared" "QT_STATIC" NEGATE PREREQUISITE "!defined(QT_SHARED) && !defined(QT_STATIC)")
@ -837,7 +837,7 @@ qt_feature_definition("concurrent" "QT_NO_CONCURRENT" NEGATE VALUE "1")
qt_feature("dbus" PUBLIC PRIVATE
LABEL "Qt D-Bus"
AUTODETECT NOT UIKIT AND NOT ANDROID
CONDITION QT_FEATURE_thread
CONDITION QT_FEATURE_thread AND NOT WASM
)
qt_feature_definition("dbus" "QT_NO_DBUS" NEGATE VALUE "1")
qt_feature("dbus-linked" PRIVATE
@ -866,7 +866,7 @@ qt_feature("printsupport" PRIVATE
)
qt_feature("sql" PRIVATE
LABEL "Qt Sql"
CONDITION QT_FEATURE_thread
CONDITION QT_FEATURE_thread AND NOT WASM
)
qt_feature("testlib" PRIVATE
LABEL "Qt Testlib"
@ -1034,12 +1034,18 @@ qt_configure_add_summary_entry(ARGS "pkg-config")
qt_configure_add_summary_entry(ARGS "libudev")
qt_configure_add_summary_entry(ARGS "system-zlib")
qt_configure_add_summary_entry(ARGS "zstd")
qt_configure_add_summary_entry(ARGS "thread")
qt_configure_end_summary_section() # end of "Support enabled for" section
qt_configure_add_report_entry(
TYPE NOTE
MESSAGE "Using static linking will disable the use of dynamically loaded plugins. Make sure to import all needed static plugins, or compile needed modules into the library."
CONDITION NOT QT_FEATURE_shared
)
qt_configure_add_report_entry(
TYPE NOTE
MESSAGE "Using pthreads"
CONDITION QT_FEATURE_thread
)
qt_configure_add_report_entry(
TYPE ERROR
MESSAGE "Debug build wihtout Release build is not currently supported on ios see QTBUG-71990. Use -debug-and-release."

View File

@ -94,6 +94,12 @@ if(NOT QT_BUILD_STANDALONE_TESTS)
# Needed when building qtbase for android.
include(src/corelib/Qt6AndroidMacros.cmake)
if(WASM)
# Needed when building for WebAssembly.
include(cmake/QtWasmHelpers.cmake)
qt_internal_setup_wasm_target_properties(Platform)
endif()
# Set up optimization flags like in qmake.
# This function must be called after the global QT_FEATURE_xxx variables have been set up,
# aka after QtBaseGlobalTargets is processed.

View File

@ -5,6 +5,64 @@
# Make sure to not run detection when building standalone tests, because the detection was already
# done when initially configuring qtbase.
function(qt_auto_detect_wasm)
if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "wasm-emscripten" AND DEFINED ENV{EMSDK})
if(NOT DEFINED QT_AUTODETECT_WASM)
set(QT_AUTODETECT_WASM TRUE CACHE BOOL "")
# detect EMSCRIPTEN_ROOT path
file(READ "$ENV{EMSDK}/.emscripten" ver)
string(REGEX MATCH "EMSCRIPTEN_ROOT.*$" EMROOT "${ver}")
string(REGEX MATCH "'([^' ]*)'" EMROOT2 "${EMROOT}")
string(REPLACE "'" "" EMROOT_PATH "${EMROOT2}")
# get emscripten version
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
set (EXECUTE_COMMANDPATH "$ENV{EMSDK}/${EMROOT_PATH}/emcc.bat")
else()
set (EXECUTE_COMMANDPATH "$ENV{EMSDK}/${EMROOT_PATH}/emcc")
endif()
file(TO_NATIVE_PATH "${EXECUTE_COMMANDPATH}" EXECUTE_COMMAND)
execute_process(COMMAND ${EXECUTE_COMMAND} --version
OUTPUT_VARIABLE emOutput
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE emrun_error
RESULT_VARIABLE result)
if(NOT emOutput)
message(FATAL_ERROR
"Can't determine Emscripten version! Error: ${emrun_error}")
endif()
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CMAKE_EMSDK_REGEX_VERSION "${emOutput}")
set(EMCC_VERSION "${CMAKE_EMSDK_REGEX_VERSION}" CACHE STRING INTERNAL FORCE)
# find toolchain file
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(wasm_toolchain_file "$ENV{EMSDK}/${EMROOT_PATH}/cmake/Modules/Platform/Emscripten.cmake")
set(CMAKE_TOOLCHAIN_FILE "${wasm_toolchain_file}" CACHE STRING "" FORCE)
endif()
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
message(STATUS "Emscripten ${CMAKE_EMSDK_REGEX_VERSION} toolchain file detected at ${CMAKE_TOOLCHAIN_FILE}")
else()
message(FATAL_ERROR "Cannot find the toolchain file Emscripten.cmake. "
"Please specify the toolchain file with -DCMAKE_TOOLCHAIN_FILE=<file>.")
endif()
if(NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build Qt statically or dynamically" FORCE)
endif()
if(BUILD_SHARED_LIBS)
message(FATAL_ERROR
"Building Qt for ${CMAKE_SYSTEM_NAME} as shared libraries is not supported.")
endif()
# this version of Qt needs this version of emscripten
set(QT_EMCC_RECOMMENDED_VERSION 2.0.14 CACHE STRING INTERNAL FORCE)
endif()
endif()
endfunction()
function(qt_auto_detect_cmake_generator)
if(NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT QT_SILENCE_CMAKE_GENERATOR_WARNING)
message(WARNING
@ -340,3 +398,4 @@ qt_auto_detect_ios()
qt_auto_detect_android()
qt_auto_detect_vpckg()
qt_auto_detect_pch()
qt_auto_detect_wasm()

View File

@ -32,7 +32,7 @@ function(qt_run_config_test_architecture)
# With emscripten the application entry point is a .js file (to be run with node for example),
# but the real "data" is in the .wasm file, so that's where we need to look for the ABI, etc.
# information.
if (EMSCRIPTEN)
if (WASM)
set(_arch_file_suffix ".wasm")
endif()

View File

@ -214,6 +214,7 @@ qt_copy_or_install(FILES
cmake/QtTestHelpers.cmake
cmake/QtToolchainHelpers.cmake
cmake/QtToolHelpers.cmake
cmake/QtWasmHelpers.cmake
cmake/QtWrapperScriptHelpers.cmake
cmake/QtWriteArgsFile.cmake
DESTINATION "${__GlobalConfig_install_dir}"

View File

@ -302,7 +302,7 @@ elseif(IOS)
set(QT_DEFAULT_MKSPEC macx-ios-clang)
elseif(APPLE)
set(QT_DEFAULT_MKSPEC macx-clang)
elseif(EMSCRIPTEN)
elseif(WASM)
set(QT_DEFAULT_MKSPEC wasm-emscripten)
elseif(QNX)
# Certain POSIX defines are not set if we don't compile with -std=gnuXX

View File

@ -120,7 +120,7 @@ function(qt_build_internals_disable_pkg_config_if_needed)
set(pkg_config_enabled ON)
qt_build_internals_find_pkg_config_executable()
if(APPLE OR WIN32 OR QNX OR ANDROID OR (NOT PKG_CONFIG_EXECUTABLE))
if(APPLE OR WIN32 OR QNX OR ANDROID OR WASM OR (NOT PKG_CONFIG_EXECUTABLE))
set(pkg_config_enabled OFF)
endif()

View File

@ -136,7 +136,7 @@ endif()
# TODO: Missing mkspecs flags we don't handle below: win32-clang-g++, win32-clang-msvc, rtems-base
#
# gcc and clang base
if(GCC OR CLANG)
if(GCC OR CLANG AND NOT WASM)
set(QT_CFLAGS_OPTIMIZE "-O2")
set(QT_CFLAGS_OPTIMIZE_FULL "-O3")
set(QT_CFLAGS_OPTIMIZE_DEBUG "-Og")
@ -187,3 +187,10 @@ if(ICC)
set(QT_CFLAGS_OPTIMIZE_SIZE "-Os")
endif()
endif()
if(WASM)
set(QT_CFLAGS_OPTIMIZE "-O2")
set(QT_CFLAGS_OPTIMIZE_FULL "-O3")
set(QT_CFLAGS_OPTIMIZE_SIZE "-Os")
set(QT_CFLAGS_OPTIMIZE_DEBUG "-g2")
endif()

View File

@ -33,6 +33,9 @@ function(qt_internal_add_executable name)
PROPERTY EXCLUDE_FROM_ALL "$<NOT:$<CONFIG:${QT_MULTI_CONFIG_FIRST_CONFIG}>>")
endif()
if(WASM)
qt6_wasm_add_target_helpers("${name}")
endif()
if (arg_VERSION)
if(arg_VERSION MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+")
# nothing to do

View File

@ -88,7 +88,7 @@ function(qt_internal_apply_gc_binaries target visibility)
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
endif()
if ((GCC OR CLANG) AND NOT EMSCRIPTEN AND NOT UIKIT AND NOT MSVC)
if ((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
if(APPLE)
set(gc_sections_flag "-Wl,-dead_strip")
elseif(SOLARIS)
@ -101,7 +101,7 @@ function(qt_internal_apply_gc_binaries target visibility)
target_link_options("${target}" ${visibility} "${gc_sections_flag}")
endif()
if((GCC OR CLANG OR ICC) AND NOT EMSCRIPTEN AND NOT UIKIT AND NOT MSVC)
if((GCC OR CLANG OR ICC) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
set(split_sections_flags "-ffunction-sections" "-fdata-sections")
endif()
if(split_sections_flags)

View File

@ -552,7 +552,9 @@ set(QT_CMAKE_EXPORT_NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE})")
PRIVATE_HEADER DESTINATION ${INSTALL_INCLUDEDIR}/${module_include_name}/${PROJECT_VERSION}/${module}/private
)
qt_apply_rpaths(TARGET "${target}" INSTALL_PATH "${INSTALL_LIBDIR}" RELATIVE_RPATH)
if(BUILD_SHARED_LIBS)
qt_apply_rpaths(TARGET "${target}" INSTALL_PATH "${INSTALL_LIBDIR}" RELATIVE_RPATH)
endif()
if (ANDROID AND NOT arg_HEADER_MODULE)
# Record install library location so it can be accessed by

View File

@ -16,7 +16,7 @@ qt_set01(QNX CMAKE_SYSTEM_NAME STREQUAL "QNX") # FIXME: How to identify this?
qt_set01(OPENBSD CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") # FIXME: How to identify this?
qt_set01(FREEBSD CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") # FIXME: How to identify this?
qt_set01(NETBSD CMAKE_SYSTEM_NAME STREQUAL "NetBSD") # FIXME: How to identify this?
qt_set01(WASM CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
qt_set01(WASM CMAKE_SYSTEM_NAME STREQUAL "Emscripten" OR EMSCRIPTEN)
qt_set01(BSD APPLE OR OPENBSD OR FREEBSD OR NETBSD)

View File

@ -338,7 +338,9 @@ function(qt_internal_add_plugin target)
NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE}::
DESTINATION "${config_install_dir}"
)
qt_apply_rpaths(TARGET "${target}" INSTALL_PATH "${install_directory}" RELATIVE_RPATH)
if(BUILD_SHARED_LIBS)
qt_apply_rpaths(TARGET "${target}" INSTALL_PATH "${install_directory}" RELATIVE_RPATH)
endif()
endif()
if (NOT arg_ALLOW_UNDEFINED_SYMBOLS)

View File

@ -563,7 +563,6 @@ QT_PATCH_VERSION = ${PROJECT_VERSION_PATCH}
list(APPEND extra_statements "QT_LIBINFIX = ${QT_LIBINFIX}")
endif()
# TODO: Add QT_EMCC_VERSION when WASM is ported over.
if(APPLECLANG)
set(compiler_version_major_var_name "QT_APPLE_CLANG_MAJOR_VERSION")
set(compiler_version_minor_var_name "QT_APPLE_CLANG_MINOR_VERSION")
@ -603,6 +602,10 @@ QT_PATCH_VERSION = ${PROJECT_VERSION_PATCH}
list(APPEND extra_statements "QT_EDITION = Open Source")
if(WASM)
list(APPEND extra_statements
"QT_EMCC_VERSION = ${EMCC_VERSION}")
endif()
if(extra_statements)
string(REPLACE ";" "\n" extra_statements "${extra_statements}")
string(APPEND content "\n${extra_statements}\n")

92
cmake/QtWasmHelpers.cmake Normal file
View File

@ -0,0 +1,92 @@
function (qt_internal_setup_wasm_target_properties wasmTarget)
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s EXIT_RUNTIME=1"
"SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=1"
"SHELL:-s EXTRA_EXPORTED_RUNTIME_METHODS=[UTF16ToString,stringToUTF16]"
"SHELL:-s USE_WEBGL2=1"
"--bind"
"SHELL:-s FETCH=1")
# Hardcode wasm memory size. Emscripten does not currently support memory growth
# (ALLOW_MEMORY_GROWTH) in pthreads mode, and requires specifying the memory size
# at build time. Further, browsers limit the maximum initial memory size to 1GB.
# QT_WASM_INITIAL_MEMORY must be a multiple of 64KB (i.e. 65536)
if(NOT DEFINED QT_WASM_INITIAL_MEMORY AND QT_FEATURE_thread)
set(QT_WASM_INITIAL_MEMORY "1GB")
endif()
if(DEFINED QT_WASM_INITIAL_MEMORY)
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s INITIAL_MEMORY=${QT_WASM_INITIAL_MEMORY}")
message("Setting INITIAL_MEMORY to ${QT_WASM_INITIAL_MEMORY}")
endif()
if (QT_FEATURE_opengles3)
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s FULL_ES3=1")
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s FULL_ES3=1"
"SHELL:-s MAX_WEBGL_VERSION=2"
"SHELL:-s WEBGL2_BACKWARDS_COMPATIBILITY_EMULATION=1")
else()
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s FULL_ES2=1")
endif()
set(disable_exceptions_catching 1)
if (QT_FEATURE_exceptions)
set(disable_exceptions_catching 0)
endif()
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s DISABLE_EXCEPTION_CATCHING=${disable_exceptions_catching}")
if (QT_FEATURE_thread)
target_compile_options("${wasmTarget}" INTERFACE "SHELL:-s USE_PTHREADS=1")
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s USE_PTHREADS=1")
if(DEFINED QT_WASM_PTHREAD_POOL_SIZE)
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s PTHREAD_POOL_SIZE=${QT_WASM_PTHREAD_POOL_SIZE}")
message("Setting PTHREAD_POOL_SIZE to ${QT_WASM_PTHREAD_POOL_SIZE}")
endif()
else()
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ALLOW_MEMORY_GROWTH=1")
endif()
# debug add_compile_options
if ("QT_WASM_SOURCE_MAP=1" IN_LIST QT_QMAKE_DEVICE_OPTIONS)
set(WASM_SOURCE_MAP_BASE "http://localhost:8000/")
if(DEFINED QT_WASM_SOURCE_MAP_BASE)
set(WASM_SOURCE_MAP_BASE "${QT_WASM_SOURCE_MAP_BASE}")
endif()
# Pass --source-map-base on the linker line. This informs the
# browser where to find the source files when debugging.
# -g4 to make source maps for debugging
target_link_options("${wasmTarget}" INTERFACE "-g4" "--source-map-base" "${WASM_SOURCE_MAP_BASE}")
endif()
# a few good defaults to make console more verbose while debugging
target_link_options("${wasmTarget}" INTERFACE $<$<CONFIG:Debug>:
SHELL:"-s DEMANGLE_SUPPORT=1"
SHELL:"-s GL_DEBUG=1"
SHELL:"-s ASSERTIONS=2"
--profiling-funcs>)
# target_link_options("${wasmTarget}" INTERFACE "SHELL:-s LIBRARY_DEBUG=1") # print out library calls, verbose
# target_link_options("${wasmTarget}" INTERFACE "SHELL:-s SYSCALL_DEBUG=1") # print out sys calls, verbose
# target_link_options("${wasmTarget}" INTERFACE "SHELL:-s FS_LOG=1") # print out filesystem ops, verbose
# target_link_options("${wasmTarget}" INTERFACE "SHELL:-s SOCKET_DEBUG") # print out socket,network data transfer
if ("QT_EMSCRIPTEN_ASYNCIFY=1" IN_LIST QT_QMAKE_DEVICE_OPTIONS)
# Emscripten recommends building with optimizations when using asyncify
# in order to reduce wasm file size, and may also generate broken wasm
# (with "wasm validation error: too many locals" type errors) if optimizations
# are omitted. Enable optimizations also for debug builds.
set(QT_CFLAGS_OPTIMIZE_DEBUG "-Os" CACHE STRING INTERNAL FORCE)
set(QT_FEATURE_optimize_debug ON CACHE BOOL INTERNAL FORCE)
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ASYNCIFY" "-Os")
target_compile_definitions("${wasmTarget}" INTERFACE QT_HAVE_EMSCRIPTEN_ASYNCIFY)
endif()
endfunction()

View File

@ -339,7 +339,7 @@ qt_feature("android-style-assets" PRIVATE
)
qt_feature("shared" PUBLIC
LABEL "Building shared libraries"
AUTODETECT NOT UIKIT
AUTODETECT NOT UIKIT AND NOT WASM
CONDITION BUILD_SHARED_LIBS
)
qt_feature_definition("shared" "QT_STATIC" NEGATE PREREQUISITE "!defined(QT_SHARED) && !defined(QT_STATIC)")
@ -600,6 +600,7 @@ qt_feature("c11" PUBLIC
qt_feature("precompile_header"
LABEL "Using precompiled headers"
CONDITION BUILD_WITH_PCH
AUTODETECT NOT WASM
)
qt_feature_config("precompile_header" QMAKE_PRIVATE_CONFIG)
set(__qt_ltcg_detected FALSE)
@ -848,7 +849,7 @@ qt_feature_definition("concurrent" "QT_NO_CONCURRENT" NEGATE VALUE "1")
qt_feature("dbus" PUBLIC PRIVATE
LABEL "Qt D-Bus"
AUTODETECT NOT UIKIT AND NOT ANDROID
CONDITION QT_FEATURE_thread
CONDITION QT_FEATURE_thread AND NOT WASM
)
qt_feature_definition("dbus" "QT_NO_DBUS" NEGATE VALUE "1")
qt_feature("dbus-linked" PRIVATE
@ -877,7 +878,7 @@ qt_feature("printsupport" PRIVATE
)
qt_feature("sql" PRIVATE
LABEL "Qt Sql"
CONDITION QT_FEATURE_thread
CONDITION QT_FEATURE_thread AND NOT WASM
)
qt_feature("testlib" PRIVATE
LABEL "Qt Testlib"
@ -1050,6 +1051,7 @@ qt_configure_add_summary_entry(ARGS "pkg-config")
qt_configure_add_summary_entry(ARGS "libudev")
qt_configure_add_summary_entry(ARGS "system-zlib")
qt_configure_add_summary_entry(ARGS "zstd")
qt_configure_add_summary_entry(ARGS "thread")
qt_configure_end_summary_section() # end of "Support enabled for" section
qt_configure_add_report_entry(
TYPE NOTE
@ -1094,9 +1096,22 @@ qt_configure_add_report_entry(
MESSAGE "Setting a library infix is not supported for framework builds."
CONDITION QT_FEATURE_framework AND DEFINED QT_LIBINFIX
)
qt_configure_add_report_entry(
TYPE NOTE
MESSAGE "Using pthreads"
CONDITION QT_FEATURE_thread
)
qt_configure_add_report_entry(
TYPE WARNING
MESSAGE "You should use the recommended Wasm version ${QT_EMCC_RECOMMENDED_VERSION} with this Qt. You have ${EMCC_VERSION}."
CONDITION WASM AND NOT ${EMCC_VERSION} MATCHES ${QT_EMCC_RECOMMENDED_VERSION}
)
if(WASM)
qt_extra_definition("QT_EMCC_VERSION" "\"${EMCC_VERSION}\"" PUBLIC)
endif()
# special case end
qt_extra_definition("QT_VERSION_STR" "\"${PROJECT_VERSION}\"" PUBLIC)
qt_extra_definition("QT_VERSION_MAJOR" ${PROJECT_VERSION_MAJOR} PUBLIC)
qt_extra_definition("QT_VERSION_MINOR" ${PROJECT_VERSION_MINOR} PUBLIC)
qt_extra_definition("QT_VERSION_PATCH" ${PROJECT_VERSION_PATCH} PUBLIC)

View File

@ -677,7 +677,7 @@
},
"shared": {
"label": "Building shared libraries",
"autoDetect": "!config.uikit",
"autoDetect": "!config.uikit && !config.wasm",
"condition": "!config.integrity && !config.wasm && !config.rtems",
"output": [
"shared",
@ -1010,6 +1010,7 @@
"precompile_header": {
"label": "Using precompiled headers",
"condition": "tests.precompile_header",
"autodetect": "!config.wasm",
"output": [
"privateConfig",
{ "type": "varRemove", "negative": true, "name": "CONFIG", "value": "'precompile_header'" }
@ -1337,7 +1338,7 @@
"dbus": {
"label": "Qt D-Bus",
"autoDetect": "!config.uikit && !config.android",
"condition": "features.thread",
"condition": "features.thread && !config.wasm",
"output": [ "privateFeature", "feature" ]
},
"dbus-linked": {
@ -1378,7 +1379,7 @@
},
"sql": {
"label": "Qt Sql",
"condition": "features.thread",
"condition": "features.thread && !config.wasm",
"output": [ "privateFeature" ]
},
"testlib": {
@ -1512,8 +1513,9 @@
"message": "Qt requires a compliant STL library."
},
{
"type": "emccVersion",
"condition": "config.wasm"
"type": "note",
"condition": "features.thread",
"message": "Using pthreads"
},
{
"type": "error",
@ -1673,7 +1675,8 @@
"pkg-config",
"libudev",
"system-zlib",
"zstd"
"zstd",
"thread"
]
}
]

View File

@ -13,8 +13,8 @@ exists($$QMAKE_QT_CONFIG) {
# Create worker threads at startup. This is supposed to be an optimization,
# however exceeding the pool size has been obesverved to hang the application.
POOL_SIZE = 4
!isEmpty(QMAKE_WASM_PTHREAD_POOL_SIZE) {
POOL_SIZE = $$QMAKE_WASM_PTHREAD_POOL_SIZE
!isEmpty(QT_WASM_PTHREAD_POOL_SIZE) {
POOL_SIZE = $$QT_WASM_PTHREAD_POOL_SIZE
}
message("Setting PTHREAD_POOL_SIZE to" $$POOL_SIZE)
@ -23,18 +23,18 @@ exists($$QMAKE_QT_CONFIG) {
EMCC_THREAD_LFLAGS += -s ALLOW_MEMORY_GROWTH=1
}
qtConfig(thread) | !isEmpty(QMAKE_WASM_TOTAL_MEMORY) {
qtConfig(thread) | !isEmpty(QT_WASM_INITIAL_MEMORY) {
# Hardcode wasm memory size. Emscripten does not currently support memory growth
# (ALLOW_MEMORY_GROWTH) in pthreads mode, and requires specifying the memory size
# at build time. Further, browsers limit the maximum initial memory size to 1GB.
# QMAKE_WASM_TOTAL_MEMORY must be a multiple of 64KB
TOTAL_MEMORY = 1GB
!isEmpty(QMAKE_WASM_TOTAL_MEMORY) {
TOTAL_MEMORY = $$QMAKE_WASM_TOTAL_MEMORY
# QT_WASM_INITIAL_MEMORY must be a multiple of 64KB
INITIAL_MEMORY = 1GB
!isEmpty(QT_WASM_INITIAL_MEMORY) {
INITIAL_MEMORY = $$QT_WASM_INITIAL_MEMORY
}
message("Setting TOTAL_MEMORY to" $$TOTAL_MEMORY)
EMCC_THREAD_LFLAGS += -s TOTAL_MEMORY=$$TOTAL_MEMORY
message("Setting INITIAL_MEMORY to" $$INITIAL_MEMORY)
EMCC_THREAD_LFLAGS += -s INITIAL_MEMORY=$$INITIAL_MEMORY
}
QMAKE_LFLAGS += $$EMCC_THREAD_LFLAGS
QMAKE_LFLAGS_DEBUG += $$EMCC_THREAD_LFLAGS
@ -117,9 +117,9 @@ qtConfTest_emccVersion()
# Pass --source-map-base on the linker line. This informs the
# browser where to find the source files when debugging.
WASM_SOURCE_MAP_BASE = http://localhost:8000/
!isEmpty(QMAKE_WASM_SOURCE_MAP_BASE):\
WASM_SOURCE_MAP_BASE = $$QMAKE_WASM_SOURCE_MAP_BASE
CONFIG(debug): QMAKE_LFLAGS += --source-map-base $$WASM_SOURCE_MAP_BASE
!isEmpty(QT_WASM_SOURCE_MAP_BASE):\
WASM_SOURCE_MAP_BASE = $$QT_WASM_SOURCE_MAP_BASE
CONFIG(debug): QMAKE_LFLAGS += -g4 --source-map-base $$WASM_SOURCE_MAP_BASE
# Creates the stand-alone version of the library from bitcode
!static:contains(TEMPLATE, .*lib): {

View File

@ -8,11 +8,11 @@ include(../common/clang.conf)
load(device_config)
load(emcc_ver)
# Support enabling asyncify by configuring with "-device-option EMSCRIPTEN_ASYNCIFY=1"
!isEmpty(EMSCRIPTEN_ASYNCIFY): {
!equals(EMSCRIPTEN_ASYNCIFY, 1):!equals(EMSCRIPTEN_ASYNCIFY, 0): \
message(Error: The value for EMSCRIPTEN_ASYNCIFY must be 0 or 1)
equals(EMSCRIPTEN_ASYNCIFY, 1): {
# Support enabling asyncify by configuring with "-device-option QT_EMSCRIPTEN_ASYNCIFY=1"
!isEmpty(QT_EMSCRIPTEN_ASYNCIFY): {
!equals(QT_EMSCRIPTEN_ASYNCIFY, 1):!equals(QT_EMSCRIPTEN_ASYNCIFY, 0): \
message(Error: The value for QT_EMSCRIPTEN_ASYNCIFY must be 0 or 1)
equals(QT_EMSCRIPTEN_ASYNCIFY, 1): {
QMAKE_CFLAGS += -DQT_HAVE_EMSCRIPTEN_ASYNCIFY
QMAKE_CXXFLAGS += -DQT_HAVE_EMSCRIPTEN_ASYNCIFY
QMAKE_LFLAGS += -s ASYNCIFY
@ -56,7 +56,7 @@ EMCC_COMMON_LFLAGS_DEBUG = \
-s GL_DEBUG=1 \
--profiling-funcs
QMAKE_LFLAGS_DEBUG += -g4
QMAKE_LFLAGS_DEBUG += -g2
QMAKE_LFLAGS_RELEASE += -O2
QMAKE_COMPILER += emscripten

View File

@ -20,6 +20,10 @@ if(ANDROID)
set(corelib_extra_cmake_files
"${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidMacros.cmake")
endif()
if(WASM)
set(corelib_extra_cmake_files
"${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}WasmMacros.cmake")
endif()
# special case end
#####################################################################

View File

@ -47,3 +47,7 @@ set(_Qt6CTestMacros "${_Qt6CoreConfigDir}/Qt6CTestMacros.cmake")
if(ANDROID_PLATFORM)
include("${CMAKE_CURRENT_LIST_DIR}/@QT_CMAKE_EXPORT_NAMESPACE@AndroidMacros.cmake")
endif()
if(EMSCRIPTEN)
include("${CMAKE_CURRENT_LIST_DIR}/@QT_CMAKE_EXPORT_NAMESPACE@WasmMacros.cmake")
endif()

View File

@ -559,6 +559,9 @@ function(qt6_finalize_executable target)
qt6_android_generate_deployment_settings("${target}")
qt6_android_add_apk_target("${target}")
endif()
if(EMSCRIPTEN)
qt_wasm_add_target_helpers("${target}")
endif()
endfunction()
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)

View File

@ -0,0 +1,31 @@
function(qt6_wasm_add_target_helpers target)
# copy in Qt HTML/JS launch files for apps
get_target_property(targetType "${target}" TYPE)
if("${targetType}" STREQUAL "EXECUTABLE")
set(APPNAME ${target})
if(QT6_INSTALL_PREFIX)
set(WASM_BUILD_DIR "${QT6_INSTALL_PREFIX}")
elseif(QT_BUILD_DIR)
set(WASM_BUILD_DIR "${QT_BUILD_DIR}")
endif()
configure_file("${WASM_BUILD_DIR}/plugins/platforms/wasm_shell.html"
"${target}.html")
configure_file("${WASM_BUILD_DIR}/plugins/platforms/qtloader.js"
qtloader.js COPYONLY)
configure_file("${WASM_BUILD_DIR}/plugins/platforms/qtlogo.svg"
qtlogo.svg COPYONLY)
endif()
endfunction()
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
function(qt_wasm_add_target_helpers)
if(QT_DEFAULT_MAJOR_VERSION EQUAL 6)
qt6_wasm_add_target_helpers(${ARGV})
endif()
endfunction()
endif()

View File

@ -389,10 +389,19 @@ ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
")
# opengles3
# special case begin
if(WASM)
set(extra_compiler_options "-s FULL_ES3=1")
endif()
# special case end
qt_config_compile_test(opengles3
LABEL "OpenGL ES 3.0"
LIBRARIES
GLESv2::GLESv2
# special case begin
COMPILE_OPTIONS ${extra_compiler_options}
# special case end
CODE
"#ifdef __APPLE__
# include <OpenGLES/ES3/gl.h>

View File

@ -47,7 +47,7 @@ if(HAIKU)
# add_subdirectory(haiku) # special case TODO
endif()
if(WASM)
# add_subdirectory(wasm) # special case TODO
add_subdirectory(wasm)
endif()
if(QT_FEATURE_integrityfb)
# add_subdirectory(integrity) # special case TODO

View File

@ -0,0 +1,78 @@
# Generated from wasm.pro.
#####################################################################
## QWasmIntegrationPlugin Plugin:
#####################################################################
qt_internal_add_plugin(QWasmIntegrationPlugin
OUTPUT_NAME qwasm
DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES wasm # special case
TYPE platforms
STATIC
SOURCES
main.cpp
qwasmclipboard.cpp qwasmclipboard.h
qwasmcompositor.cpp qwasmcompositor.h
qwasmcursor.cpp qwasmcursor.h
qwasmeventdispatcher.cpp qwasmeventdispatcher.h
qwasmeventtranslator.cpp qwasmeventtranslator.h
qwasmfontdatabase.cpp qwasmfontdatabase.h
qwasmintegration.cpp qwasmintegration.h
qwasmoffscreensurface.cpp qwasmoffscreensurface.h
qwasmopenglcontext.cpp qwasmopenglcontext.h
qwasmscreen.cpp qwasmscreen.h
qwasmservices.cpp qwasmservices.h
qwasmstring.cpp qwasmstring.h
qwasmstylepixmaps_p.h
qwasmtheme.cpp qwasmtheme.h
qwasmwindow.cpp qwasmwindow.h
DEFINES
QT_EGL_NO_X11
QT_NO_FOREACH
PUBLIC_LIBRARIES
Qt::Core
Qt::CorePrivate
Qt::Gui
Qt::GuiPrivate
)
# Resources:
set_source_files_properties("${QT_SOURCE_TREE}/src/3rdparty/wasm/Vera.ttf" PROPERTIES QT_RESOURCE_ALIAS "Vera.ttf")
set_source_files_properties("${QT_SOURCE_TREE}/src/3rdparty/wasm/DejaVuSans.ttf" PROPERTIES QT_RESOURCE_ALIAS "DejaVuSans.ttf")
set_source_files_properties("${QT_SOURCE_TREE}/src/3rdparty/wasm/DejaVuSansMono.ttf" PROPERTIES QT_RESOURCE_ALIAS "DejaVuSansMono.ttf")
set(wasmfonts_resource_files
"${QT_SOURCE_TREE}/src/3rdparty/wasm/Vera.ttf"
"${QT_SOURCE_TREE}/src/3rdparty/wasm/DejaVuSans.ttf"
"${QT_SOURCE_TREE}/src/3rdparty/wasm/DejaVuSansMono.ttf"
)
qt_internal_add_resource(QWasmIntegrationPlugin "wasmfonts"
PREFIX
"/fonts"
FILES
${wasmfonts_resource_files}
)
qt_internal_extend_target(QWasmIntegrationPlugin CONDITION QT_FEATURE_opengl
SOURCES
qwasmbackingstore.cpp qwasmbackingstore.h
PUBLIC_LIBRARIES
Qt::OpenGL
Qt::OpenGLPrivate
)
#### Keys ignored in scope 4:.:.:wasm.pro:NOT TARGET___equals____ss_QT_DEFAULT_QPA_PLUGIN:
# PLUGIN_EXTENDS = "-"
qt_copy_or_install(FILES
wasm_shell.html
DESTINATION "${CMAKE_INSTALL_PREFIX}/plugins/platforms/"
)
qt_copy_or_install(FILES
qtloader.js
DESTINATION "${CMAKE_INSTALL_PREFIX}/plugins/platforms/"
)
qt_copy_or_install(FILES
qtlogo.svg
DESTINATION "${CMAKE_INSTALL_PREFIX}/plugins/platforms/"
)