Deploying apps with QtWebEngine for Ubuntu
QtWebEngine is a very handy C++/Qt module for creating applications with embedded web content. It carries a complete Chromium browser and allows you to embed HTML/JS content in your application or to modify such content as you wish.
If you however want to deploy this application to Ubuntu, you will be faced with two problems:
QtWebEngine is not available in the official repository (yet). This means that you can't just create a .deb package, since the necessary dependencies won't be available. There are PPA's, but at least at the time of this writing, none of them worked.
You can't compile Qt statically with QtWebEngine included, since the codebase doesn't support it. Also you would have to make the source code of your application available under the terms of the LGPL, which could be unwanted if you chose a different license or if your application is proprietary.
Using a snap package
Note: As for now, this only works under 16.04. Under Ubuntu 16.10 you need to add
to the linker flags, but I couldn't figure out how.
Luckily, we can overcome this problem by utilizing the new snap package format which has been introduced into ubuntu 16.04. A snap package will allow you to distribute your application shipped with a Qt version of your choice, allowing to include QtWebEngine and to comply with the terms of the LGPL (Note: I'm not a lawyer. Check with your legal experts if your application is proprietary and if you don't want to make your source code publicly available).
Creating the snap package
If you are new to snap packages, I'd advise you to read the official tutorial, called "Build your first snap". It takes about 5 minutes to complete and will tell you everything you will need to know to distribute your application.
The remainder of this article will assume that you have basic knowledge of snap packaging.
Adding your source code
We start first by adding your source code to the
snapcraft.yml file. For the sake of this tutorial,
I will use the QtWebEngine minimal example, which is included in the Qt sourcecode:
name: qtwebengine-snap-tutorial version: "2017-18-02" summary: A short demo on howto package Qt using snap grade: devel confinement: devmode apps: qtwebengine-example: command: deploy/qtwebengine.sh parts: example: # Replace this with the path to your sourcecode source: https://download.qt.io/archive/qt/5.8/5.8.0/submodules/qtwebengine-opensource-src-5.8.0.tar.xz source-subdir: qtwebengine-opensource-src-5.8.0/examples/webengine/minimal/
For adding Qt to our build, we will need to complete several steps:
- Download the Qt sourcecode from
- Extract it
- Install all necessary dependencies inside the snap environment
- run the
configurescript will the right parameters. Important: Depending on what parts of Qt your application uses, you will maybe need to adjust this step.
- Compile & install it.
- Copy everything needed for the application into a special
The last step is needed since the
QtWebEngineProcess looks for it's resource files at some
hard-coded paths and in the path where the executable lies. Of course it would be nicer if we could omit
this step and put everything into
/usr in the snap environment, but as far as I know, this is not possible.
Anyway, here is the qt part for the
parts: qt: source: http://download.qt.io/archive/qt/5.8/5.8.0/single/qt-everywhere-opensource-src-5.8.0.tar.gz stage-packages: - libdbus-1-dev - libpci-dev - libxss-dev - gperf - bison - libegl1-mesa-dev - libfontconfig1-dev - libudev-dev - libudev1 - re2c - libvpx-dev - libsnappy-dev - libsrtp0-dev - zlib1g-dev - libwebp-dev - libxslt1-dev - libevent-dev - libjsoncpp-dev - libopus-dev - libprotobuf-dev - libfreetype6-dev - libx11-dev - libxext-dev - libxfixes-dev - libxi-dev - libxrender-dev - libxcb1-dev - libx11-xcb-dev - libxcb-glx0-dev - libxcb-keysyms1-dev - libxcb-image0-dev - libxcb-shm0-dev - libxcb-icccm4-dev - libxcb-sync-dev - libxcb-xfixes0-dev - libxcb-shape0-dev - libxcb-randr0-dev - libxcb-render-util0-dev - libxcb-xinerama0-dev - libxcomposite-dev - libxcursor-dev - libxrandr-dev - libxtst-dev - libpng12-dev - yasm - bc - python - libbluetooth-dev - libopenal-dev - libgstreamer1.0-dev - libgles2-mesa-dev - libgl1-mesa-dev - mesa-common-dev - libglu1-mesa-dev - libgstreamer-plugins-base1.0-dev plugin: make prepare: | bash -c '$SNAPCRAFT_STAGE/../patch.sh' build: | ./configure -opensource -release -confirm-license -nomake tests -no-compile-examples -system-zlib -skip virtualkeyboard -skip wayland -skip charts -prefix $SNAPCRAFT_PART_INSTALL -I $SNAPCRAFT_PART_INSTALL/usr/include/freetype2 -I $SNAPCRAFT_PART_INSTALL/usr/include -L $SNAPCRAFT_PART_INSTALL/usr/lib/x86_64-linux-gnu/ -nomake examples -nomake tools -opengl desktop -qt-libpng -qt-xcb -v 2>&1 | tee qt-configure.log make -s -j $(echo $(nproc) +1 | bc) rm -v $SNAPCRAFT_PART_INSTALL/usr/include/x86_64-linux-gnu/bits/string3.h make -s install mkdir $SNAPCRAFT_PART_INSTALL/deploy cp -r $SNAPCRAFT_PART_INSTALL/plugins $SNAPCRAFT_PART_INSTALL/deploy/ cp -r $SNAPCRAFT_PART_INSTALL/libexec/* $SNAPCRAFT_PART_INSTALL/deploy/ cp -r $SNAPCRAFT_PART_INSTALL/resources/icudtl.dat $SNAPCRAFT_PART_INSTALL/deploy/ cp -r $SNAPCRAFT_PART_INSTALL/resources/qtwebengine_resources_100p.pak $SNAPCRAFT_PART_INSTALL/deploy/ cp -r $SNAPCRAFT_PART_INSTALL/resources/qtwebengine_resources_200p.pak $SNAPCRAFT_PART_INSTALL/deploy/ cp -r $SNAPCRAFT_PART_INSTALL/resources/qtwebengine_resources.pak $SNAPCRAFT_PART_INSTALL/deploy/ cp -r $SNAPCRAFT_PART_INSTALL/translations/qtwebengine_locales $SNAPCRAFT_PART_INSTALL/deploy/ cp $SNAPCRAFT_STAGE/../example.sh $SNAPCRAFT_PART_INSTALL/deploy/ stage: - bin/* - usr/* - deploy/* - lib/* - translations/* - resources/*
OK, this is a lot. Here is what's going on:
We are installing several dependencies. These are needed for compiling Qt and QtWebEngine and my be needed to be adjusted by you, regarding which modules your application needs.
preparestep calls a custom bash script, which works around a bug in the C header files supplied by Ubuntu 16.04. The script & patch is listed below.
Since we need to do several custom steps during the build process, we can't use snapcraft's
autotoolsplugin. Instead, we utilize the more general
makeplugin and provide a custom build script.
During the stage phase, we make sure that all files needed by QtWebEngine are carried over to the final package.
Patching the ubuntu C header files
One of the ubuntu header files uses the notation
// for commenting at one point instead of
QtWebEngine uses the flags
-pedantic -Werror internally, this causes the build process to fail. Therefore we
need to patch this file:
--- ./usr/include/x86_64-linux-gnu/bits/string3.h 2016-11-16 21:53:50.000000000 +0100 +++ ./usr/include/x86_64-linux-gnu/bits/string3.h 2017-02-10 08:12:21.786385589 +0100 @@ -126,7 +126,7 @@ return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); } -// XXX We have no corresponding builtin yet. +/* XXX We have no corresponding builtin yet. */ extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n, size_t __destlen) __THROW; extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src,
This patch file called
c-comment.patch is applied during the build stage by a helper script called
#!/bin/bash pushd $SNAPCRAFT_PART_INSTALL patch -p1 < ../../../c-comment.patch popd
That's it; our snapcraft package is complete.
To be honest, this is a lot of stuff to deploy an application and the resulting package is rather big; furthermore, this doesn't seem to work with Ubuntu 16.10/17.04 due to changes in some libraries (if you know a solution, write me a e-mail).
Nevertheless, it shows that all kinds of programs can be packaged and deployed using snap.
- If Qt doesn't build for you, change the
-qt-xcbparameter of call to
-system-xcb(or the other way around).
- The message
Note: No relevant classes found. No output generated.is normal during to the compilation of Qt and does not indicate an error.