[Development] Qt for WebAssembly
Morten.Sorvig at qt.io
Fri Mar 9 13:57:49 CET 2018
As you may have noticed work on Qt for WebAssembly is underway. With the
recent updates the wip/webassembly branches are now based on Qt 5.11, which
they will continue to be while we work on bringing up Qt Quick. The tracking
bug for the project is QTBUG-63917 (with subtasks). This is a continuation of
the initial port at https://codereview.qt-project.org/#/c/178543/
I think this may be a good time to discuss how we want to support Qt for
WebAssembly and what direction the project should take. I’ll start out
by describing some recent developments:
* We are targeting WebAssembly using Emscripten as the SDK. The platform plugin
is implemented (mainly) using the html5.h API from emscripten.
The platform define is Q_OS_HTML5. We have wip branches for qtbase and
qtdeclarative. If (minor) adjustments are needed in other modules then
those could be submitted to the 5.11 branch under the Q_OS_HTML5 define.
* Binary sizes: We are using static builds. The minimal Qt demos (QtCore + QtGui) come
out at 2.1M compressed. The SensorTag demo (QtCore + QtGui + QtWidgets + QtQuick + QtCharts)
(as seen on Embedded World) is 6.3M.
In the end it may be that application assets will contribute significantly to
the overall application size. We can look into building an asset download
pipeline using web service workers.
* Load times: In addition to the network connection this depends on the browser
wasm implementation, Firefox has recently gotten very fast and can download and
instantiate the small Qt demos in a couple of seconds.
* Qt Applications as web page components
Qt for WebAssembly draws to a HTML <canvas> element. The default Qt html template
makes the canvas cover the entire browser viewport, but any layout is possible.
The size and position of the canvas may very well be outside of the applications
control. Multiple canvases per “process” is possible but not yet supported.
On the Qt side each canvas corresponds to a QScreen. The application is responsible
for positioning windows on the screen(s). Qt::WindowFullScreen windows fill the entire
canvas area with application content, normal windows get window decorations.
(Here we have the luxury of using modern JS features due to the natural selection
of browsers that the wasm requirement provides.)
We don’t have access to system font files. This means fonts must me embedded in
the application binary or downloaded on demand.
Exact font style matches with “native” system fonts will probably remain out of
scope, but should still be able to match the font size setting. Page zoom is
handled via the high-dpi implementation.
* (No) thread support
Wasm and Emscripten do have pthreads support. However this requires SharedArrayBuffer,
which has been disabled in all major browser after recent security incidents.
So we are looking to upstream a no-thread configure option, and modules that
want to work on the web should support it. It’s still possible to develop with
pthreads enabled by enabling SharedArrayBuffer for your browser.
No-thread could be implemented either by removing QThread (and friends), or by
making QThread::start() a no-op.
* QML interpretation vs compilation
We’re currently using the QML interpreter, which is working reasonably well
for development purposes. The end state is to compile to wasm, ahead of time.
There has been some discussion on whether compilation should be implemented
before anything is merged to the main Qt branches, or be handled later on.
We are looking there approaches: (not mutually exclusive)
- A QNetworkAccessManager backend implemented using XMLHttpRequest/Fetch.
This allows making HTTP REST requests back to the origin server, or to other servers
by using CORS.
- A QWebSocket (client) backend implemented using HTML5 WebSocket
This would allow making websocket connections to any server.
- Using the emscripten sockets implementation and websockify.
This is a tunneling solution where the server runs e.g. websockify and will forward
to a pre-determined target. Supports (unix) TCP and UDP sockets, so no work
is needed in Qt.
Very open for contributions :)
Further information including getting started instructions is available on QTBUG-63917,
and also or on QTBUG-65198 (platform documentation).
Thanks for reading!
More information about the Development