[Development] Qt for WebAssembly

Morten Sørvig Morten.Sorvig at qt.io
Fri Mar 9 13:57:49 CET 2018


Hi all,

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.

  We provide a Javascript API (qtloader.js) for managing the application process.
  (Here we have the luxury of using modern JS features due to the natural selection
  of browsers that the wasm requirement provides.)

* Fonts

  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.

* Networking

  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.

* QtMultimedia
  
   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!
Morten



More information about the Development mailing list