diff options
26 files changed, 370 insertions, 42 deletions
diff --git a/.prev_configure.cmake b/.prev_configure.cmake index 3d76317909..f796eddc8a 100644 --- a/.prev_configure.cmake +++ b/.prev_configure.cmake @@ -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,6 +1034,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 @@ -1041,6 +1042,11 @@ qt_configure_add_report_entry( 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." CONDITION IOS AND QT_FEATURE_debug AND NOT QT_FEATURE_debug_and_release diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e05aa52e8..18eaf95c50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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. diff --git a/cmake/QtAutoDetect.cmake b/cmake/QtAutoDetect.cmake index d3173dfad0..b32258e929 100644 --- a/cmake/QtAutoDetect.cmake +++ b/cmake/QtAutoDetect.cmake @@ -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() diff --git a/cmake/QtBaseConfigureTests.cmake b/cmake/QtBaseConfigureTests.cmake index cbd482bd59..67cee65d4a 100644 --- a/cmake/QtBaseConfigureTests.cmake +++ b/cmake/QtBaseConfigureTests.cmake @@ -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() diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index 03f4b4d76a..580e84f80a 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -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}" diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 9766e7f683..f31a215a4a 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -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 diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake index 9cd5c6ecfb..6192d809a3 100644 --- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake +++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake @@ -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() diff --git a/cmake/QtCompilerOptimization.cmake b/cmake/QtCompilerOptimization.cmake index ed6921da53..c8c3da78d5 100644 --- a/cmake/QtCompilerOptimization.cmake +++ b/cmake/QtCompilerOptimization.cmake @@ -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() diff --git a/cmake/QtExecutableHelpers.cmake b/cmake/QtExecutableHelpers.cmake index d96f2edaa1..c25a9ae8a3 100644 --- a/cmake/QtExecutableHelpers.cmake +++ b/cmake/QtExecutableHelpers.cmake @@ -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 diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake index 003e1a45ec..cbc39cbf1a 100644 --- a/cmake/QtFlagHandlingHelpers.cmake +++ b/cmake/QtFlagHandlingHelpers.cmake @@ -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) diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index 4a3237d4ea..95272d3932 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -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 diff --git a/cmake/QtPlatformSupport.cmake b/cmake/QtPlatformSupport.cmake index 02c0c0fb63..94ff238418 100644 --- a/cmake/QtPlatformSupport.cmake +++ b/cmake/QtPlatformSupport.cmake @@ -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) diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake index e2289a0561..86d59cb8ab 100644 --- a/cmake/QtPluginHelpers.cmake +++ b/cmake/QtPluginHelpers.cmake @@ -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) diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake index 47be8a6194..e425a4ec2b 100644 --- a/cmake/QtPriHelpers.cmake +++ b/cmake/QtPriHelpers.cmake @@ -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") diff --git a/cmake/QtWasmHelpers.cmake b/cmake/QtWasmHelpers.cmake new file mode 100644 index 0000000000..1bbe5c928f --- /dev/null +++ b/cmake/QtWasmHelpers.cmake @@ -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() diff --git a/configure.cmake b/configure.cmake index 7d015717ed..b477499915 100644 --- a/configure.cmake +++ b/configure.cmake @@ -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) + diff --git a/configure.json b/configure.json index c6790eab78..b656ad1bda 100644 --- a/configure.json +++ b/configure.json @@ -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" ] } ] diff --git a/mkspecs/features/wasm/wasm.prf b/mkspecs/features/wasm/wasm.prf index 2e886fc4a5..882d2e49c8 100644 --- a/mkspecs/features/wasm/wasm.prf +++ b/mkspecs/features/wasm/wasm.prf @@ -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): { diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf index 2b108a5e90..2788d925c4 100644 --- a/mkspecs/wasm-emscripten/qmake.conf +++ b/mkspecs/wasm-emscripten/qmake.conf @@ -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 diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 54b756d2a6..af6bba2dbe 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -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 ##################################################################### diff --git a/src/corelib/Qt6CoreConfigExtras.cmake.in b/src/corelib/Qt6CoreConfigExtras.cmake.in index e7892bbcc3..25b3f5acd5 100644 --- a/src/corelib/Qt6CoreConfigExtras.cmake.in +++ b/src/corelib/Qt6CoreConfigExtras.cmake.in @@ -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() diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index b4ffa54578..54edcd102f 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -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) diff --git a/src/corelib/Qt6WasmMacros.cmake b/src/corelib/Qt6WasmMacros.cmake new file mode 100644 index 0000000000..e9c19160a3 --- /dev/null +++ b/src/corelib/Qt6WasmMacros.cmake @@ -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() diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake index 0e2482e380..449bd838b7 100644 --- a/src/gui/configure.cmake +++ b/src/gui/configure.cmake @@ -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> diff --git a/src/plugins/platforms/CMakeLists.txt b/src/plugins/platforms/CMakeLists.txt index f6206942ea..8ef533ad43 100644 --- a/src/plugins/platforms/CMakeLists.txt +++ b/src/plugins/platforms/CMakeLists.txt @@ -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 diff --git a/src/plugins/platforms/wasm/CMakeLists.txt b/src/plugins/platforms/wasm/CMakeLists.txt new file mode 100644 index 0000000000..10e247b7dd --- /dev/null +++ b/src/plugins/platforms/wasm/CMakeLists.txt @@ -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/" +) |