Qt for WebAssembly: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(Different command lines for python2/python3 HTTP servers)
m (Protected "Qt for WebAssembly": This is being moved into the official documentation, so please don't edit now ([Edit=Allow only autoconfirmed users] (indefinite) [Move=Allow only autoconfirmed users] (indefinite)))
(21 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Qt for WebAssembly makes it possible to build Qt applications as WebAssembly modules in order to target Web browsers.
Qt for WebAssembly makes it possible to build Qt applications for the web platform.


Qt for WebAssembly is currently in development. Qt 5.12 features a tech preview of Qt for WebAssembly. Qt 5.13 is planned to have Qt for WebAssembly as a supported platform.
Qt for WebAssembly is currently in development. Qt 5.12 features a tech preview of Qt for WebAssembly. Qt 5.13 is planned to have Qt for WebAssembly as a supported platform.


The main development tracking bug is https://bugreports.qt.io/browse/QTBUG-63917.
=== Licensing ===
 
Qt for WebAssembly is available for commercial usage under the Qt Commercial license, and for open source usage under the [https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3]. For more information, please check the [https://www.qt.io/licensing/ general licensing information] of Qt.
 
=== Getting Started ===
Qt-based applications are built for WebAssembly using the Emscripten SDK. Supported host/build platforms are Linux, macOS, and [https://docs.microsoft.com/en-us/windows/wsl/install-win10 Windows Subsystem for Linux] . Qt 5.13 will in addition support Windows with MinGW.
 
The getting started steps are:
# Install the Emscripten SDK
# Build Qt from source
# Build and run applications
 
==== Install the Emscripten SDK ====
Install [http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html Emscripten] according to instructions.


===== Getting the code =====
Each Qt minor release supports a known-good Emscripten version. This version has been tested to work well with the given Qt minor version, and will continue to be supported for the lifetime of that Qt version. We aim to make Qt work with newer Emscripten versions as well. Older Emscripten versions are not supported.


The sources can be downloaded from your Qt Account, in the Downloads section. For the latest revision of the code, you can also check it out from our git repositories directly: http://code.qt.io/cgit/qt/qt5.git/
The known-good versions are:
* Qt 5.12: 1.38.16
* Qt 5.13: 1.38.27 (multithreading: 1.38.30)
Use emsdk to install specific emscripten versions (example):
* ./emsdk install sdk-1.38.16-64bit
* ./emsdk activate --embedded sdk-1.38.16-64bit
You may want to install multiple versions of the SDK, in which case the "-embedded" option is useful. It locates all configuration and cache files inside the SDK dir so that multiple versions do not conflict. The "64bit" in the SDK version refers to the host bit-ness.


===== Building Qt =====
==== Build Qt from source ====
The Qt sources can be downloaded from your Qt Account, in the Downloads section. For the latest revision of the code, you can also check it out from our git repositories directly: http://code.qt.io/cgit/qt/qt5.git/


Requirements: [http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html Emscripten]
Configure Qt as a cross-compile build for the "wasm-emscripten" platform. This will implicitly set the "-static" and "-no-feature-thread" options. The Qt examples are not built by default in order to minimize build size and time. Pass the "-compile-examples" option to enable examples.<blockquote>./configure -xplatform wasm-emscripten -nomake examples -prefix $PWD/qtbase</blockquote>
* known-good versions
** Qt 5.12: 1.38.16
** Qt 5.13: 1.38.27


Supported host dev platforms: Linux, macOS, [https://docs.microsoft.com/en-us/windows/wsl/install-win10 Windows Subsystem for Linux] (5.13: "Standard" Windows is supported)
On Windows, make sure you have MinGW as well as [http://gnuwin32.sourceforge.net/packages/sed.htm sed] in your PATH and configure with the following:


Configure Qt as a cross-compile build for the "wasm-emscripten" platform. This will implicitly set the "-static" and "-no-feature-thread" options.
<blockquote>configure -no-warnings-are-errors -xplatform wasm-emscripten -platform win32-g++ -nomake examples -prefix %CD%\qtbase</blockquote>
<blockquote>./configure -xplatform wasm-emscripten -nomake examples -prefix $PWD/qtbase</blockquote>


Build required modules:
Build required modules:
<blockquote>make module-qtbase module-qtdeclarative [other modules] </blockquote>
<blockquote>make module-qtbase module-qtdeclarative [other modules] </blockquote>


===== Building and running applications =====
==== Build and run applications ====
<blockquote>/path/to/qmake && make</blockquote>
We support the qmake build system. Run qmake from the Qt for WebAssembly build in the directory which contains the applications .pro file:<blockquote>/path/to/qtbase/bin/qmake && make</blockquote>
 
The build process will produce several files: (with "appname" substituted for the actual application name)
{| class="wikitable"
!Name
!Description
|-
|appname.wasm
|Main application binary
|-
|appname.js
|Emscripten JavaScript runtime
|-
|appname.html
|Html container
|-
|qtloader.js
|Qt JavaScript runtime
|}
Run the application by loading the appname.html file in a web browser. The files must be served by a web server using http(s).  Start a web server (e.g. "python3 -m http.server"), open e.g. localhost:8000/app.html in a web browser. We test on Chrome, Firefox, and Safari (all desktop). Wasm compiling and loading performance wary between the browsers; test several and find one which works for you.
 
You can also use:<blockquote>/path/to/emscripten/emrun --browser=firefox appname.html</blockquote>Debug and logging output go to the browser's debug console. If you are using Firefox, you can use CTRL+SHIFT+K to open the debug console.


Start a web server (e.g. "python2 -m SimpleHTTPServer" or "python3 -m http.server"), open e.g. localhost:8000/appname.html in a web browser. We test on Chrome, Firefox, and Safari (all desktop). Firefox (nightly) currently has the most performant wasm compiler, and is recommended for dev work.
=== Platform Notes ===
The Qt for WebAssembly platform port has limitations; these are due to the sandboxed nature of the web platform, the platform APIs provided (or not provided), and the incomplete nature of the Qt port. This section describes several topics which may be of interest for application developers.


You can also use:<blockquote>/path/to/emscripten/emrun --browser=firefox appname.html</blockquote><blockquote></blockquote>
==== Supported target browsers/devices ====
Desktop:
* Chrome
* FireFox
* Safari
* Edge (Chrome)
If the browser supports WebAssembly then Qt should run. Note that Qt has fixed WebGL requirement, also for apps that do not use WebGL directly. Browsers often blacklist WebGL for older/unsupported GPUs.


Note: If you are using Firefox, you can use CTRL+SHIFT+K to open the debug console.
Mobile:
* Android Browser
* Mobile Safari
'''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 5.12 Platform notes =====
In general, Qt does not make direct use of operating system features and it makes no difference if e.g. FireFox runs on Windows or macOS. Qt does use some operating system adaptions, for example for ctrl/cmd key handling on macOS.
 
==== Supported Qt Modules ====
Qt for WebAssembly supports a subset of the Qt modules. The following lists the currently tested modules. (You can can paste in the list as arguments to "make", which should then build the modules)
* module-qtbase module-qtdeclarative module-qtquickcontrols2 module-qtwebsockets module-qtsvg module-qtcharts module-qtmqtt
Other modules are generally untested and may work.
 
Not supported: QtMultimedia, QtWebView
 
==== Qt 5.12 Notes ====
* Recommended emsdk version: 1.38.16  
* Recommended emsdk version: 1.38.16  
* Supported development host systems: Linux and MacOS, and [https://docs.microsoft.com/en-us/windows/wsl/install-win10 Windows Subsystem for Linux].
* Supported development host systems: Linux and MacOS, and [https://docs.microsoft.com/en-us/windows/wsl/install-win10 Windows Subsystem for Linux].
Line 39: Line 95:
* The Qt for WebAssembly build has multithreading disabled. Enabling it is not possible.
* The Qt for WebAssembly build has multithreading disabled. Enabling it is not possible.


===== Qt 5.13 Platform notes (next release) =====
==== Qt 5.13 Notes (next release) ====
* Recommended emsdk version: 1.38.27
* Recommended emsdk version: 1.38.27 (multithreading: 1.38.30)
* Supported development host systems: Linux, MacOS, and Windows
* Supported development host systems: Linux, MacOS, and Windows (MinGW)
* Qt supports copying and pasting text to the system clipboard
** Browsers that support the [https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API Clipboard API] are preferred. Note that a requirement for this API is that the web page is served over a secure connection (e.g. https).
*** Chrome supports the Clipboard API
*** Firefox supports the Clipboard API behind a flag: dom.events.asyncClipboard.dataTransfer
** Browsers that will send clipboard events to Qt's canvas element are also supported
*** This mode supports the CTRL+x/c/v keyboard shortcuts only
*** Ongoing work. Firefox works well, other browsers have some hiccups.
* Multithreading is now possible, and opt-in by building Qt from source and passing the "-feature-thread" flag to the configure script.   
* Multithreading is now possible, and opt-in by building Qt from source and passing the "-feature-thread" flag to the configure script.   
** Emscripten pthreads documentation: [https://emscripten.org/docs/porting/pthreads.html?highlight=pthreads Emscripten pthread docs].
** Emscripten pthreads documentation: [https://emscripten.org/docs/porting/pthreads.html?highlight=pthreads Emscripten pthread docs].
** Recommended emsdk version: 1.38.30, due to [https://github.com/emscripten-core/emscripten/issues/8238 emscripten issue 8238]
** Enable support by building Qt from source and passing the -feature-thread argument to the configure script.
** Enable support by building Qt from source and passing the -feature-thread argument to the configure script.
** Binaries with thread support enabled will not load on browsers that do not support wasm threads.
** Web browser thread support is required for thread-enabled builds. The error messages for missing thread support are not straightforward, e.g. "Wasm decoding failed: invalid memory limits flags"
** Thread support may have to be enabled in the browser:
*** Chrome: chrome://flags  "WebAssembly threads support"
*** FireFox: about:config "javascript.options.shared_memory"
** Thread Pool Size
** Thread Pool Size
*** Applications should set the expected number of concurrent threads at build time. This can be done by setting QMAKE_WASM_PTHREAD_POOL_SIZE in the .pro file (maps to Emscripten PTHREAD_POOL_SIZE).
*** Applications should set the expected number of concurrent threads at build time. This can be done by setting QMAKE_WASM_PTHREAD_POOL_SIZE in the .pro file (maps to Emscripten PTHREAD_POOL_SIZE).
Line 57: Line 124:
** QThread::idealThreadCount() returns the number of CPU cores available (maps to navigator.hardwareConcurrency).
** QThread::idealThreadCount() returns the number of CPU cores available (maps to navigator.hardwareConcurrency).


===== General Platform notes =====
==== General Notes ====
* Supported browsers: We develop and test mainly on desktop systems. Tested browsers include Chrome, Safari, Opera and Firefox. Some mobile testing is done on Android and iOS devices. Safari on iOS currently failing to load Qt applications with an "out of executable memory" error. 
* Supported Qt modules, in "make module-foo" form:
** module-qtbase module-qtdeclarative module-qtquickcontrols2 module-qtwebsockets module-qtmqtt module-qtsvg module-qtcharts
** These should build without error; other modules may work but have not been verified.
* Debugging: Qt debug and logging output is printed on the JavaScript console, which can be accessed via browser "Developer Tools" or similar.
* Debugging: Qt debug and logging output is printed on the JavaScript console, which can be accessed via browser "Developer Tools" or similar.
* Nested event loops are not supported. Applications should not call e.g. QDialog::exec() or create a new QEventLoop object.
* Nested event loops are not supported. Applications should not call e.g. QDialog::exec() or create a new QEventLoop object.
Line 96: Line 159:


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.
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 Development ====
The main development tracking bug is https://bugreports.qt.io/browse/QTBUG-63917.

Revision as of 12:57, 14 May 2019

Qt for WebAssembly makes it possible to build Qt applications for the web platform.

Qt for WebAssembly is currently in development. Qt 5.12 features a tech preview of Qt for WebAssembly. Qt 5.13 is planned to have Qt for WebAssembly as a supported platform.

Licensing

Qt for WebAssembly is available for commercial usage under the Qt Commercial license, and for open source usage under the GNU General Public License version 3. For more information, please check the general licensing information of Qt.

Getting Started

Qt-based applications are built for WebAssembly using the Emscripten SDK. Supported host/build platforms are Linux, macOS, and Windows Subsystem for Linux . Qt 5.13 will in addition support Windows with MinGW.

The getting started steps are:

  1. Install the Emscripten SDK
  2. Build Qt from source
  3. Build and run applications

Install the Emscripten SDK

Install Emscripten according to instructions.

Each Qt minor release supports a known-good Emscripten version. This version has been tested to work well with the given Qt minor version, and will continue to be supported for the lifetime of that Qt version. We aim to make Qt work with newer Emscripten versions as well. Older Emscripten versions are not supported.

The known-good versions are:

  • Qt 5.12: 1.38.16
  • Qt 5.13: 1.38.27 (multithreading: 1.38.30)

Use emsdk to install specific emscripten versions (example):

  • ./emsdk install sdk-1.38.16-64bit
  • ./emsdk activate --embedded sdk-1.38.16-64bit

You may want to install multiple versions of the SDK, in which case the "-embedded" option is useful. It locates all configuration and cache files inside the SDK dir so that multiple versions do not conflict. The "64bit" in the SDK version refers to the host bit-ness.

Build Qt from source

The Qt sources can be downloaded from your Qt Account, in the Downloads section. For the latest revision of the code, you can also check it out from our git repositories directly: http://code.qt.io/cgit/qt/qt5.git/

Configure Qt as a cross-compile build for the "wasm-emscripten" platform. This will implicitly set the "-static" and "-no-feature-thread" options. The Qt examples are not built by default in order to minimize build size and time. Pass the "-compile-examples" option to enable examples.

./configure -xplatform wasm-emscripten -nomake examples -prefix $PWD/qtbase

On Windows, make sure you have MinGW as well as sed in your PATH and configure with the following:

configure -no-warnings-are-errors -xplatform wasm-emscripten -platform win32-g++ -nomake examples -prefix %CD%\qtbase

Build required modules:

make module-qtbase module-qtdeclarative [other modules]

Build and run applications

We support the qmake build system. Run qmake from the Qt for WebAssembly build in the directory which contains the applications .pro file:

/path/to/qtbase/bin/qmake && make

The build process will produce several files: (with "appname" substituted for the actual application name)

Name Description
appname.wasm Main application binary
appname.js Emscripten JavaScript runtime
appname.html Html container
qtloader.js Qt JavaScript runtime

Run the application by loading the appname.html file in a web browser. The files must be served by a web server using http(s). Start a web server (e.g. "python3 -m http.server"), open e.g. localhost:8000/app.html in a web browser. We test on Chrome, Firefox, and Safari (all desktop). Wasm compiling and loading performance wary between the browsers; test several and find one which works for you.

You can also use:

/path/to/emscripten/emrun --browser=firefox appname.html

Debug and logging output go to the browser's debug console. If you are using Firefox, you can use CTRL+SHIFT+K to open the debug console.

Platform Notes

The Qt for WebAssembly platform port has limitations; these are due to the sandboxed nature of the web platform, the platform APIs provided (or not provided), and the incomplete nature of the Qt port. This section describes several topics which may be of interest for application developers.

Supported target browsers/devices

Desktop:

  • Chrome
  • FireFox
  • Safari
  • Edge (Chrome)

If the browser supports WebAssembly then Qt should run. Note that Qt has fixed WebGL requirement, also for apps that do not use WebGL directly. Browsers often blacklist WebGL for older/unsupported GPUs.

Mobile:

  • Android Browser
  • Mobile Safari

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.

In general, Qt does not make direct use of operating system features and it makes no difference if e.g. FireFox runs on Windows or macOS. Qt does use some operating system adaptions, for example for ctrl/cmd key handling on macOS.

Supported Qt Modules

Qt for WebAssembly supports a subset of the Qt modules. The following lists the currently tested modules. (You can can paste in the list as arguments to "make", which should then build the modules)

  • module-qtbase module-qtdeclarative module-qtquickcontrols2 module-qtwebsockets module-qtsvg module-qtcharts module-qtmqtt

Other modules are generally untested and may work.

Not supported: QtMultimedia, QtWebView

Qt 5.12 Notes

  • Recommended emsdk version: 1.38.16
  • Supported development host systems: Linux and MacOS, and Windows Subsystem for Linux.
  • Clipboard support: The application clipboard is currently not integrated with the system clipboard.
  • The Qt for WebAssembly build has multithreading disabled. Enabling it is not possible.

Qt 5.13 Notes (next release)

  • Recommended emsdk version: 1.38.27 (multithreading: 1.38.30)
  • Supported development host systems: Linux, MacOS, and Windows (MinGW)
  • Qt supports copying and pasting text to the system clipboard
    • Browsers that support the Clipboard API are preferred. Note that a requirement for this API is that the web page is served over a secure connection (e.g. https).
      • Chrome supports the Clipboard API
      • Firefox supports the Clipboard API behind a flag: dom.events.asyncClipboard.dataTransfer
    • Browsers that will send clipboard events to Qt's canvas element are also supported
      • This mode supports the CTRL+x/c/v keyboard shortcuts only
      • Ongoing work. Firefox works well, other browsers have some hiccups.
  • Multithreading is now possible, and opt-in by building Qt from source and passing the "-feature-thread" flag to the configure script.
    • Emscripten pthreads documentation: Emscripten pthread docs.
    • Recommended emsdk version: 1.38.30, due to emscripten issue 8238
    • Enable support by building Qt from source and passing the -feature-thread argument to the configure script.
    • Web browser thread support is required for thread-enabled builds. The error messages for missing thread support are not straightforward, e.g. "Wasm decoding failed: invalid memory limits flags"
    • Thread support may have to be enabled in the browser:
      • Chrome: chrome://flags "WebAssembly threads support"
      • FireFox: about:config "javascript.options.shared_memory"
    • Thread Pool Size
      • Applications should set the expected number of concurrent threads at build time. This can be done by setting QMAKE_WASM_PTHREAD_POOL_SIZE in the .pro file (maps to Emscripten PTHREAD_POOL_SIZE).
      • Applications can exceed PTHREAD_POOL_SIZE, provided they return main thread control to the browser before waiting on the new thread, for example by returning from the event handler that started the new thread. This allows the browser to start another web worker. Immediately waiting for the new thread on the main thread (using QThread::wait() or similar) will deadlock.
      • Qt sets PTHREAD_POOL_SIZE to 4 by default.
    • Heap Memory Size
      • Applications should set the heap memory size at build time, since growing the heap is not supported with pthreads enabled. This can be be done by setting QMAKE_WASM_TOTAL_MEMORY in the .pro file (maps to Emscripten TOTAL_MEMORY).
      • Browsers typically limit the initial WASM memory allocation size to 1GB.
      • Qt sets TOTAL_MEMORY to 1GB by default (for -feature-thread enabled builds)
    • QWaitCondition::wait() with a timeout different than ULONG_MAX does not wait. Will/is possibly fixed in emscripten
    • QThread::idealThreadCount() returns the number of CPU cores available (maps to navigator.hardwareConcurrency).

General Notes

  • Debugging: Qt debug and logging output is printed on the JavaScript console, which can be accessed via browser "Developer Tools" or similar.
  • Nested event loops are not supported. Applications should not call e.g. QDialog::exec() or create a new QEventLoop object.
  • Qt renders application content to a canvas element, and does not use (other) native DOM elements. This means accessibility (screen readers) are not supported and that text inputs won't trigger virtual keyboards.
  • WebGL is required, even for applications which do not use OpenGL themselves. All relevant browsers support WebGL, but note that some browsers blacklist certain older GPUs. The Qt loader will detect this and display an error message.
  • Child OpenGL windows are not supported. The window compositor (in the Qt for Wasm platform plugin) supports raster windows only.
  • Qt will detect OpenGL support as OpenGL ES. In reality the browser will be providing WebGL. WebGL is based on ES and is very similar, but there are some incompatibilities. See WebGL and OpenGL Differences
  • Applications do not have access to system fonts. Font files must be distributed with the application, for example in Qt resources. Qt for WebAssembly itself embeds one such font.
  • High-DPI and scaling: High-DPI rendering is supported, and so is setting the overall UI visual size using the browser zoom feature. Browser font size (and type) settings have no effect on Qt applications.
  • There may be artifacts of uninitialized graphics memory on some Qt Quick Controls 2 components, such as checkboxes.
  • Network access: The web sandbox limits network access to a subset of what is available for native apps.
    • QNetworkAccessManager http requests to the web page origin server, or to a server which supports CORS.
    • QWebScoket connections to any host.
    • TCP and UDP socked tunneling using over WebSockets using a websockify server [implemented by Emscripten, not tested].
      • Websockify v0.8.0 can be used to tunnel TCP connections with QT5.12 but it is MANDATORY to specify the base64 or binary subprotocols before calling QWebSocket::open(). For example:

QWebSocket socket;

QUrl url{QString("ws://server:port")};

QNetworkRequest request{url};

request.setRawHeader("Sec-WebSocket-Protocol", "binary");

socket.open(request);

  • Link-time warnings of the form: "cannot represent a NaN literal '0x7fdae4bde910' with custom bit pattern", are expected.
  • 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 Development

The main development tracking bug is https://bugreports.qt.io/browse/QTBUG-63917.