A QML app running as an HTML app

So that looks interesting, right?

In part 1 of Why you should use Qt/QML for your next cross-platform application we mentioned Qt for WebAssembly. This was around 10 months ago.

In software development, things move fast, and Qt for WebAssembly has moved from technology preview to supported platform.

So in this article we are going to explore building Web apps using QML.

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.

WebAssembly

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications. This format is nearly as fast as native machine code, and is now supported by all major web browsers.

In essence, WebAssembly allows code written in different languages to be executed in any environment that embeds a WebAssembly virtual machine.

One of those environments is a web browser and that is what makes it interesting since almost all others platforms Qt already supports.

Setup

The setup may be still a bit tricky but as always official docs on the topic will get you covered.

In essence we need to do two things, setup Emscripten compiler and Qt for Webassembly.

Emscripten

On linux it is something along the lines of:



git clone

cd emsdk

./emsdk install sdk-1.38.30-64bit

./emsdk activate --embedded sdk-1.38.30-64bit

source emsdk_env.sh # fetch Emscripten SDK and install target versiongit clone https://github.com/emscripten-core/emsdk.git cd emsdk./emsdk install sdk-1.38.30-64bit./emsdk activate --embedded sdk-1.38.30-64bitsource emsdk_env.sh

For exact requirements and instructions check the official Emscripten docs.

In the end, if all went well, this will result in at least em++ being in your path.

Note that 1.38.30 is recommended build that also has multi-thread support so for now don’t experiment with others builds as they will have issues (tested :)

source emsdk_env.sh is important to setup a valid Emscripten environment so don’t forget to run it (every time you open a new terminal)

Qt WebAssembly

This is even simpler. Download Qt installer from a Qt download page or open existing Qt Maintenance tool if you have it already installed.

In both cases you just need to select a Qt for WebAssembly, in my case I used latest Qt at the time of writing, 5.13.2.

Installing Qt WebAssembly

After installation is done we are ready for our Hello World.

Hello WebAssembly

So let’s start with an obvious example.

Create a new Qt/Qml project with basic content:

import QtQuick 2.13

import QtQuick.Window 2.13 Window {

visible: true

width: 640

height: 480

title: qsTr("Hello WebAssembly") Text {

anchors.centerIn: parent

text: qsTr("Hello WebAssembly")

color: "black"

}

}

If we build and run it on our native platform we get:

Not much WebAssembly here

Well, exactly what we wanted and works as expected.

Now, let’s continue with real WebAssembly. If you didn’t you have to setup Emscripten enviroment as mentioned above: source /path-to-emsdk/emsdk_env.sh

Go to your new project and create a build directory (or however you want to call it to make an out-of-source build — optional). Then just invoke new qmake with WebAssembly support:

cd /path-to-hello-webassembly-project

mkdir build && cd build

/path-to-qt-with-webassembly/5.13.2/wasm_32/bin/qmake ..

make

This will take a while, especially on first run. Subsequent runs will improve a bit but at the moment it still takes around 2 minutes and 32 seconds on my i7–7700.

Note that make -j flag is not so beneficial as Emscripten build is already parallelized.

After this is done you will get a bunch of files in your build directory, and one of the will be a projectname.html file. To run it in the browser we need as usual a web server. You can use whatever you want to serve these static files, but there is also a convenient emrun command line tool you can use for this purpose as it is already available as part of Emscripten enviroment.

So to open our app in Firefox web browser one can do: emrun — browser=firefox *.html

Looks exactly the same, but this time it’s an HTML app running in the browser

Well, that feels nice doesn’t it. Even the tab title is updated to app title as we would expect.

So we already knew that we can build and run this app on multiple platforms, but now without any code change we are also running it in the Web browser as well. Neat.

“Real” apps

It was fun to build a simple Hello WebAssembly but it would be even nicer to see if this can handle a real app. As a convenience, we can use apps introduced in the previous articles.

Todo app

In part-2 of Why you should use Qt/QML for cross platform development series we developed a small Todo app. Let’s repeat the build process and see if this would work as a Web app.



mkdir build && cd build

/path-to-qt-with-webassembly/5.13.2/wasm_32/bin/qmake ..

make

emrun --browser=firefox *.html git clone https://github.com/pkoretic/Todo && cd Todomkdir build && cd build/path-to-qt-with-webassembly/5.13.2/wasm_32/bin/qmake ..makeemrun --browser=firefox *.html

Todo app developed in QML running as an HTML app

First try and it does work and look almost exactly as we developed it!

Note: we replaced our unicode plus /- heavy signs as those are not supported with current font:

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.

Forecast app

Moving on to something even more complex.

In part-3 we did a TV app. This one is bigger, uses images and network requests.

Todo app developed in QML running as an HTML app

Fully works with no code change, even our key navigation. We didn’t implement touch support at the time so no clicks possible here but that would be a minor addition since Button is already used.

QtCreator

This will need a separate article for details but adding support to QtCreator is as simple as creating a new Kit with Emscripten compiler.

It requires adding custom emcc / em++ compiler to Tools — Options — Kits — Compilers and new qmake to Qt versions. Then the leftover part is creating a Kit using those as described in official docs and building your app.

Conclusion

Even though it’s surprisingly nice, there are still important limitations that you can read about in official platform notes.

Build time is also not the fastest but keep in mind these were optimized builds (-O3) and it is not really necessary to compile the app to HTML on every change as we could test it on our default platform very quickly.

There are also many more examples in the official docs and a really nice one recently released — Web based Qt design viewer so make sure to check those for futher reading.

In the end this is a really nice progress that we can see. Keep in mind that Qt 5.13.x is first release with Qt for WebAssmbly as supported platform so we can expect even better things in the future.

Happy coding.