Try it now with QQuickStaticHelloWorld. This is a minimal CMake project for Qt application compatible with Wasm.
This project aim is to provide a CMake function to replicate qmake
behavior when building a project with Qt for WebAssembly. The script provide a function add_qt_wasm_app
that will set linker flags required by Qt to work with Emscripten. It will also deploy Qt template file that can load your application.
This generates the following files:
Generated file | Brief Description |
---|---|
YourApp.html | HTML container |
qtloader.js | JS API for loading Qt apps |
YourApp.js | JS API for loading Qt apps |
YourApp.wasm | emscripten app binary |
add_qt_wasm_app(YourApp
NAME "index"
DISABLE_DEPLOYMENT
INITIAL_MEMORY 512MB
MAXIMUM_MEMORY 4GB)
NAME
Specify the name of the HTML container. By default it will be the target name. This option can be useful to automatically generate a index.html
.
DISABLE_DEPLOYMENT
Disable the deployment of Qt file. The compilation will only leave you with a YourApp.js
and YourApp.wasm
. You will need to provide your own qtloader.js
that load the qt application, and an html file to embed the app into a canvas
.
NAME doesn't have any effect with this option set.
INITIAL_MEMORY
Size of the module, can be expressed in bytes, or with KB/MB/GB/TB. Example: 512MB.
MAXIMUM_MEMORY
Optionally support 2GB+ heap sizes. To do this we make the JS code have unsigned pointers (we need all 32 bits in them now), which can slightly increase code size (>>> instead of >>). This only happens when the heap size may be over 2GB, which you must opt into explicitly, by setting MAXIMUM_MEMORY
to a higher value (i.e. by default you do not get support for 2GB+ heaps).
Just calling add_qt_wasm_app
won't be enough if you are using QML plugins. Since we are linking with a version of qt that is static, you need to add a few extra steps.
Those steps won't be necessary in the future when Qt will have better support of Qt.
The easiest way is to use QtStaticCMake.
get_target_property(QT_TARGET_TYPE Qt5::Core TYPE)
if(${QT_TARGET_TYPE} STREQUAL "STATIC_LIBRARY")
include(QtStaticCMake.cmake)
qt_generate_plugin_import(YourApp VERBOSE)
# This function assert that your qml are in qml/
qt_generate_qml_plugin_import(YourApp
QML_SRC ${CMAKE_CURRENT_SOURCE_DIR}/qml)
endif()
Soon you will be able to replace this with qt5_import_qml_plugins
and qt5_import_plugins
.
Then simply use this script function.
if(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
include(QtWasmCMake.cmake)
add_qt_wasm_app(YourApp)
endif()
Since you are cross compiling, when executing cmake you need to add a cmake toolchain.
cmake -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_PREFIX_PATH=$QT_WASM ..
emsdk
also come with emcmake
command that set the toolchain variable for you.
emcmake cmake -DCMAKE_PREFIX_PATH=$QT_WASM ..
You can also use a docker container that will make your life way easier. Checkout reivilo1234/qt-webassembly-cmake. In this container cmake
is already aliases as emcmake cmake
and qt sdk is installed so it is immediatly found by cmake. You can just run cmake ..
in this container.
- This whole work is based on forderud
- Using Docker to test Qt WebAssembly
- CMake Toolchain
- QtStaticMake
- ManmanFred docker container