Morten Johan Sørvig

Qt for Native Client (and emscripten)

Published Friday September 25th, 2015
15 Comments on Qt for Native Client (and emscripten)
Posted in Qt, Qt Quick

Qt for Native client has been in development for a while, and I’m pleased to announce that the project again has reached working status: running Qt applications (Qt Widgets and Qt Quick) sandboxed in the Chrome browser. In this post I’ll talk about the background of native code on the web and how to get started with Qt.

Qt for Native Client is available as an unsupported tech preview. Get the source code form code.qt.io:

git clone https://code.qt.io/qt/qtbase.git .
git checkout wip/nacl

The above “git clone” will give you qtbase only – If you are interested in using Qt Quick then you probably want a complete Qt checkout with the wip/nacl branch for QtBase.

See the presentation at the the Qt World Summit
Qt for Native Client will be presented at the Qt World Summit. Register today!

A brief history of Native Code on the Web

Native Client (NaCl) is a sandbox for native x86 code, first published back in 2009, and later extended to support x86_64 and ARM. Portable Native Client (PNaCl) is built on top of NaCl and defines an intermediate architecture-independent format for distribution. PNaCl binaries are translated to NaCl binaries on first load by the browser. Chrome runs PNaCl binaries from the Web, NaCl binaries from the Chrome App store or if enabled in browser settings. Other browser vendors have showed little interest in this line of technology.

Emscripten compiles native code to JavaScript which can run on all browsers. Later versions of Emscripten improves performance (on cooperating browsers) by using the ASM JS subset of JavaScript.

WebAssembly is a joint effort between some of the larger browser vendors, which target “is to promote early-stage cross-browser collaboration on a new, portable, size- and load-time-efficient format suitable for compilation to the web.” Compatibility for non-WebAssembly browsers is provided in the form of a WebAssembly loader implemented in JavaScript.

The Native Client SDK

The Native Client SDK is versioned along with Chrome and follows the same 6-week release cycle. The SDK contains an update script which fetches new versions and updates ‘canary’.

$ ls nacl_sdk/
	pepper_40
	pepper_41
	pepper_canary

‘pepper_NN/toolchain’ then contains PNaCl and NaCl toolchains. The “mac” in the names is the host, produced binaries are OS independent. The Qt tech preview currently supports the ‘pnacl’ and ‘newlib’ toolchains, using static builds.

$ ls nacl_sdk/pepper_41/toolchain
	mac_arm_newlib
	mac_pnacl
	mac_x86_glibc
	mac_x86_newlib

Finally we find the compiler binaries and conclude we are dealing with a cross-compiler:

$ ./nacl_sdk/pepper_41/toolchain/mac_pnacl/bin/i686-nacl-clang++ hello.cpp -o hello.nexe
$ file hello.nexe
hello.nexe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
$ ./hello
-bash: ./hello.nexe: cannot execute binary file

Emscripten

Emscripten is typically distributed by your platforms package manager. On OS X:

	brew install emscripten

This gives you the ‘em++’ compiler and friends – there are no versions or toolchain variants. em++ can produce “executable” .js files:

$em++ hello.cpp -o hello.js
node hello.js
“Hello World”

API and Platform

Programs that want to do something more interesting than printing to standard out need an API to interface against. In Qt, this is the domain of the QPA platform plugin. Native Client provides PPAPI (’Pepper’) which provides a C and C++ API for the features covered by the HTML (5) specification. For example, Pepper gives access to mouse and keyboard events, and provides 2D or 3D graphics contexts.

Emscripten also has a similar API. Qt could have used it but instead uses pepper.js, which is a re-implementation of the Pepper API on top of Html, which allows us to re-use the exiting pepper platform plugin. (It could be said that adding this level of indirection is in the spirit of compiling C++ to JavaScript). Emscripten support is still very expermental: QtCore and QtGui runs with raster graphics, the OpenGL, QtWidgets and QtQuick modules are largely untested.

Setting up Qt

The workflow is similar to using Qt for any other platform:
1. Configure and build Qt.
2. Build the application.
3. Deploy. (nacldeployqt)

The following is a simplified overview, complete getting started instructions are available at qtbase/README.md.

1. Use the provided configure script, select a NaCl toolchain or emscripten (We treat emscripten as a nacl variant.)

./nacl-configure mac_pnacl release

Build Qt:

make qtmodule-qtbase (or qtmodule-qtdeclarative)

2. Build the application

/path/to/qmake && make

3. Run nacldeployqt

/path/to/nacldeployqt application.nexe

This creates supporting files for the application: a html file, the qtloader.js script, manifest files.

In addition, nacldeployqt provides some convenience:

   -—run: Start Chrome, run the application
   -—debug: Start Chrome and nacl-gdb, run the applicatjon with attached debugger

Finally it runs:
nacl-controls-gallery

Questions? Interested in contributing to the development of Qt for Native Client? Contact us here or on #qt-labs on irc (freenode).

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in Qt, Qt Quick

15 comments

Scorp1us says:

This seems like the opposite approach as what I think should be undertaken. The “Vaudeville” tech (that I do hope to get back onto one day) is a HTML5-Canvas painter QPA plug-in to use Qt apps to drive a browser from a Qt headless app running on a server. Think of it as a virtual frame buffer, but is web. It doesn’t require any browser plugins, just HTML5 Canvas. I think the Canvas approach is a more flexible approach.

Morten Johan Sørvig Morten Johan Sørvig says:

I don’t think these approaches are completely at odds, but rather can complement each other. For example, your approach uses an active server component while the NaCl solution runs on the client. Developers could then choose the solution that fits their use case.

Tim says:

Yes; in general the hard part of creating “web applications” is dealing with WAN latencies and the consequent lack of responsiveness… and the most effective way to deal with that is to be able to push at least some first line of response logic into the client. Solutions where everything is done serverside and nothing happens on the client display until there’s been a round trip to the server… not so good, and IMHO it makes little difference whether you use RDP or VNC or reinvent that sort of approach using an “HTML framebuffer”… as soon as latencies creep up, it becomes pretty unpleasant. So I certainly think this client-centric tech is a very interesting answer to the “what’s Qt’s story on the web?” question.

Pau Garcia i Quiles says:

I am not sure I have understood correctly:
– you are compiling Qt as “shared” PNaCl libraries
– you are compiling your application to JavaScript with EmScripten
– you are linking those two together by means of pepper.js

Why not compiling your application as a (P)NaCl binary directly?

(or maybe all this was just an exercise in what technology CAN do, even if it’s not that practical?)

Morten Johan Sørvig Morten Johan Sørvig says:

Yes, this was perhaps not completely clear in the post:
– We are compiling applications directly as PNaCl binaries.
– There is a separate “can do” exercise involving emscripten and pepper.js which re-uses parts of the Qt for NaCl implementation and allows targeting all browsers.

Andreykonn says:

So I can compile qml app into cross-browser javascript?

Morten Johan Sørvig Morten Johan Sørvig says:

That is what we are aiming for with the “emscripten” effort. We are not there yet, so today compiling for Native Client and the Chrome browser works best.

CSRedRat says:

NaCl = Salt

Firat says:

Finally! This is exacting news! I ‘m not much into NaCL but definitely will track progress of emscriptten. Looking forward to more here about this!

lu says:

whether qt fo nacl supports windows?

Morten Johan Sørvig Morten Johan Sørvig says:

Windows is unfortunately not supported as a host/development platform by Qt. Binaries compiled for NaCl runs on Chrome also on Windows. (but not on Chrome for iOS, which used the native UIWebView for rendering)

TTR says:

The true web app has been born! how about http://example.com/foo.qml ??

Alan says:

Wt already does that….http://www.webtoolkit.eu/wt

Morten Johan Sørvig Morten Johan Sørvig says:

It should be noted though that Wt requires an active server component where the application logic runs. So that’s a different type of solution again.

Alan says:

Thank you for pointing out the difference. I will give it a try !

Commenting closed.

Get started today with Qt Download now