Linking to Static Builds of Qt

The device-specific sysroots in Boot to Qt come with a dynamically linked version of Qt libraries (*.so files). In some cases, using static linking may be preferable; it avoids the dependencies to external libraries, produces single, self-contained application binaries making deployment easier, and may lead to smaller binary size as unused code can be stripped away.

Internally, Qt uses dynamic linking with plugins for a lot of its functionality. In order to have a fully functioning application, extra attention is needed on which plugins to include in a static build. A downside of static linking is that adding or updating a plugin requires a complete rebuild and redeployment of the application.


In addition to installing Qt for Device Creation, ensure that required packages are installed for all Qt modules that are included in the static build. For more information, see Qt for Linux Requirements and Requirements for Development Host. Note that dependencies for the xcb platform plugin need not be installed, as Qt will be configured without xcb support.

Install Qt sources by running the MaintenanceTool, located in the root of INSTALL_DIR. Alternatively, clone the qt5 repository using git.

Building Qt for Static Linking

To use static linking, Qt must be built with the -static configuration option. The following configure command selects the correct options and sysroot for the Raspberry Pi 2.

To make the set of configure options reusable and more readable, the device-specific paths are defined as environment variables:

export SYSROOT_BASE=<INSTALL_DIR>/5.9/Boot2Qt/raspberrypi2/toolchain/sysroots
export TARGET_DEVICE=linux-rasp-pi2-g++
export SYSROOT_TARGET=cortexa7hf-vfp-vfpv4-neon-poky-linux-gnueabi
export CROSSCOMPILE_PREFIX=x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-
export HOST_PREFIX=~/build/qt5-rasp-pi2

To configure and build Qt for some other device, modify the variables to contain the correct sysroot paths and device target strings as they appear in your Qt for Device Creation installation.

Description of the used variables:

SYSROOT_BASEBase directory for the sysroots (host and target) for the device
TARGET_DEVICETarget device (mkspec)
SYSROOT_TARGETTarget sysroot directory under SYSROOT_BASE
CROSSCOMPILE_PREFIXCross-compilation toolchain path and tool prefix (ends with '-')
HOST_PREFIXLocation to install the host binaries (qmake, moc, rcc, etc.)

Using the above variables, configure can be called as follows:

cd <QT_SRC>
./configure -commercial -release -static \
            -prefix /opt/qt5 -hostprefix $HOST_PREFIX \
            -device $TARGET_DEVICE \
            -sysroot $SYSROOT_BASE/$SYSROOT_TARGET \
            -mysql_config $SYSROOT_BASE/$SYSROOT_TARGET/usr/bin/mysql_config \
            -psql_config /dev/null \
            -no-xcb -opengl es2 \
            -nomake tests -nomake examples \
            -skip qtwebengine

Above, -prefix sets the intended destination of the Qt build on the device (sysroot). Running make install will, by default, install Qt under sysroot/prefix.

Compiling in xcb support is disabled, OpenGL ES 2.0 support is selected, and Qt WebEngine is excluded from the build, as it does not support static builds.

More information about configure options is available in the Qt for Embedded Linux documentation.

If configuration is successful, proceed to build and install Qt:

make -j6 && make install

The host tools (in particular, qmake) are now installed in HOST_PREFIX, and the statically compiled Qt libraries are in $SYSROOT_BASE/$SYSROOT_TARGET/opt/qt5. At this point, it's also possible to add the new Qt version into Qt Creator and set up a Kit for it:

Building a Static Application

Building a stand-alone, static application requires all the necessary plugins to be also statically linked. By default, qmake compiles a set of plugins based on which Qt modules are used, and adds them to the QTPLUGIN variable.

After running qmake, the project directory contains a <target_name>_plugin_import.cpp file that imports the plugins using Q_IMPORT_PLUGIN() macros. The default set often contains more plugins than are actually needed; to prevent unnecessary bloat, it's possible to exclude certain plugin classes from the build.

For example, to exclude additional image format plugins, use:

QTPLUGIN.imageformats = -

Alternatively, the automatic generation of Q_IMPORT_PLUGIN() macros can be turned off:

CONFIG -= import_plugins

The relevant plugins then need to be explicitly imported in the application code.

For more information, see Static Plugins.

Adding QML Imports

Similar to how Qt plugins are imported, qmake invokes the qmlimportscanner tool to scan the application's .qml files, and generates a <target_name>_qml_plugin_import.cpp file containing a Q_IMPORT_PLUGIN() call for each static plugin associated with a QML import.

For example, for a simple QML application using the QtQuick and QtQuick.Window import statements, the following statements are generated:


In addition, the resources used by the QML imports need to be made available to the QML engine. The best approach is to copy the files from the source location into the application's project directory and add them to the Qt resource system, together with the application's own resources.

At minimum, even though an import plugin uses no extra resources (.qml, .js, or image files), its qmldir file needs to be accessible and located under the correct QML import path.

For example, the following entries in a Qt resource collection file (.qrc) places the qmldir files under the qml/ prefix in resources:


Finally, the QML engine needs to be informed about the import path that's now located within the resources. The following implementation of main() sets the import path to qrc:/qml before loading main.qml:

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    return app.exec();

Available under certain Qt licenses.
Find out more.