WebAssembly (or Wasm) is a binary bytecode format intended to be executed in a virtual machine inside a web browser. This allows an application to be deployed to a device with a compliant web browser without going through any installation steps. The application will run inside a secure sandbox in the web browser. This format is nearly as fast as native machine code, and is now supported by all major web browsers. This makes it appropriate for applications that do not need full access to the device capabilities, but benefits from a swift and uncomplicated installation process.
Qt for WebAssembly is a platform plugin that lets you build Qt applications, which can be integrated into your web pages. It doesn't require any client-side installations and reduces the server-side resource usage.
Note: Qt for WebAssembly is currently in Tech Preview.
emscripten is a toolchain for compiling to WebAssembly. It lets you run Qt on the web at near-native speed without plugins.
Refer to the emscripten documentation for more information about installing the Emscripten SDK.
After installation, you should have the Emscripten compiler in your path. Check this with the following command:
em++ --version
Each Qt minor version targets a specific minimum Emcsripten version, which will not change for the lifetime of that Qt minor version. Qt's binary packages are built using this version of the Emscripten SDK. We recommend installing the minimum Emcsripten version corresponding to the Qt version you are using, especially if you are using the binary pckages.
Newer versions of Emscripten above the minimum version may work (and often do), but may introduce behavior changes which require changes to Qt.
The minimum versions are:
Use emsdk
to install specific emscripten
versions. For example, to install it for Qt 6.2 enter:
After installation, on Windows, you should have emscripten in your path. On macOS or Linux you need to add it to your path, like this:
source /path/to/emsdk/emsdk_env.sh
Check this with the following command:
em++ --version
The binary builds can be downloaded in the Downloads section using your Qt account.
Alternatively, you could download the Qt sources in the Downloads section, and build Qt from it.
Configure Qt as a cross-compile build for the wasm-emscripten
platform. This will implicitly set the -static
, -no-feature-thread
, and -no-make examples
configure options. Thread support and building of the examples can be enabled by removing the corresponding disabling option. Shared library builds are not supported at this time.
For Qt 6, you will need a host build of the same version of Qt and add that path to QT_HOST_PATH by using the -qt-host-path
configure argument.
Although it should be detected, you may optionally set the CMAKE_TOOLCHAIN_PATH to the Emscripten.cmake toolchain file that comes with Emscripten sdk, by using the -DCMAKE_TOOLCHAIN_FILE= configure argument.
./configure -qt-host-path /path/to/Qt/6.2.0/platform -xplatform wasm-emscripten -prefix $PWD/qtbase
On Windows, make sure you have MinGW
in your PATH
and configure with the following:
configure -qt-host-path C:\Path\to\Qt6 -no-warnings-are-errors -xplatform wasm-emscripten -platform win32-g++ -prefix %CD%\qtbase
Build required modules:
cmake --build . -t qtbase -t qtdeclarative [-t another_module]
$ /path/to/qt-wasm/qtbase/bin/qt-cmake $ make
This generates the following files:
Generated file | Brief Description |
---|---|
app.html | HTML container |
qtloader.js | JS API for loading Qt apps |
app.js | JS API for loading Qt apps |
app.wasm | emscripten app binary |
When deploying the app, the compression is typically handled on the server side. We recommend to compress the wasm binaries because this typically reduces the size of the binary by 50 %.
Qt for Webassembly has several additional configuration arguments available.
Configure Argument | Brief Description |
---|---|
-sse2 | This enables autovectorization and Wasm SIMD support by adding the compiler argument -msimd128. In addition, emulated and native optcode SSE instructions are utilized (at which point Qt's SSE code paths will also be used). SSE1, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, and 128-bit AVX instructions only. Simd support may need to be enabled in browsers advanced configurations, such as 'about:config' or 'chrome:flags'. There may be performance issues when used with certain SIMD instructions that are emulated and that have no native optcode supported by the browser. For more information see https://emscripten.org/docs/porting/simd.html |
-feature-thread | Multi-threaded wasm |
-device-option QT_WASM_SOURCE_MAP=1 | Debugging option for creating source maps |
-feature-opengles3 | Use opengles3 in addition to the default opengles2 |
You can test-run your application in the following way:
/path/to/emscripten/emrun --browser=firefox appname.html
If the browser supports WebAssembly, then Qt should run.
Note: Qt has a fixed WebGL requirement, also for apps that do not use WebGL directly. Browsers often blacklist WebGL for older/unsupported GPUs.
Note: There is currently no support for text input using the virtual keyboard. Safari currently does not support wasm modules of the size Qt produces.
Qt does not make direct use of operating system features and it makes no difference if, for example, FireFox runs on Windows or macOS. Qt does use some operating system adaptations, for example for ctrl/cmd key handling on macOS.
Qt for WebAssembly supports a subset of the Qt modules and features. The list below lists the currently tested modules.
Note that changes and updates to browsers may also change Wasm platform behavior, thus this documentation and listed limitations below may not be up-to-date.
Threads on Qt for WebAssembly are not officially supported yet and may not work exactly like posix threads do. Refer to Pthreads Support.
Qt on WebAssembly can run multithreads, however support is disabled by default in order to be compatible with as many browsers as possible. Thread support can be enabled by building Qt from source and using the "-feature-thread" configure flag.
The Qt for WebAssembly binary release packages do not support multithreading.
The minimum Emscripten SDK version is 1.38.30. The Emscripten pthreads documentation contains relevant documentation for multithreading.
Threads are supported by some (but not all) browsers. Configuration changes may be required. The [1] demo can be used to determine if thread support is available. Note that it is the build mode which determines if browser thread support is required, not whether the application starts a thread or not.
In Firefox versions before 79, open about:config and make sure the following option is enabled:
Thread support will only be enabled provided that that the web server sets two additional headers:
(These are the COOP and COEP headers, respectively)
Mozilla bug 1619649 tracks the Firefox defaults change. In the mean time, its possible to manually bypass or enable the header check:
Firefox Nightly or Beta - bypass header check:
Firefox Release - enable header check:
After enabling the header check, make sure your web server sets the required headers. See QTBUG-79087 for an example python-based development server.
Application developers may need to add two settings to its .pro or CMakeFiles.txt file when enabling threads:
Using cmake, such as:
set(QT_WASM_PTHREAD_POOL_SIZE, 10)
The web sandbox limits network access to a subset of what is available for native apps.
File system access is sandboxed on the web, and this has implications for how the application works with files. The Web platform provides APIs for accessing the local file system in a way which is under user control, as well as APIs for accessing persistent storage. Emscripten and Qt wraps these features and provides APIs which are easier to use from C++ and Qt-based applications.
The web platform provides features for accessing local files and persistent storage:
Emscripten provides several file systems with a POSIX like API. These include:
Emscripten mounts a temporary MEMFS filesystem to "/" at app startup. This means that QFile can be used, and will read and write files to memory by default. Qt provides other API as well:
Qt supports copying and pasting text to the system clipboard but there are browser specific differences you need to take into account in your code.
Known limitations and issues with Qt Quick Controls 2:
Wasm debugging is done on browser javascript console, debugging applications on Wasm directly within Qt Creator is not possible.
Expected footprint (download size): Wasm modules as produced by the compiler can be large, but compress well:
Example | gzip | brotli |
---|---|---|
helloglwindow (QtCore + QtGui) | 2.8M | 2.1M |
wiggly widget (QtCore + QtGui + QtWidgets) | 4.3M | 3.2M |
SensorTag (QtCore + QtGui + QtWidgets + QtQuick + QtCharts) | 8.6M | 6.3M |
Compression is typically handled on the web server side, using standard compression features: the server compresses automatically or picks up pre-compressed versions of the files. There's generally no need to have special handling of wasm files.
Qt for WebAssembly is available under commercial licenses from The Qt Company. In addition, it is available under the GNU General Public License, version 3. See Qt Licensing for further details.
See also WebAssembly Resource site, Getting Started with Qt for WebAssembly, and Remote UIs with WebGL and WebAssembly.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/wasm.html