/**************************************************************************** ** ** Copyright (C) 2014 Digia Plc ** All rights reserved. ** For any questions to Digia, please use the contact form at ** http://www.qt.io ** ** This file is part of Qt Enterprise Embedded. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. ** ** If you have questions regarding the use of this file, please use ** the contact form at http://www.qt.io ** ****************************************************************************/ /*! \page qtee-static-linking.html \title Linking to Static Builds of Qt \previouspage qtee-custom-embedded-linux-image.html \nextpage qtee-changelog.html The device-specific sysroots in \B2Q come with a dynamically linked version of Qt libraries (\c *.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. \section1 Requirements In addition to installing \SDK, ensure that required packages are installed for all Qt modules that are included in the static build. For more information, see \l {Qt for X11 Requirements#OpenGL Dependencies}{Qt for Linux Requirements} and \l {Qt for Linux/X11#Requirements for Development Host}{Requirements for Development Host}. Note that dependencies for the \e xcb platform plugin need not be installed, as Qt will be configured without xcb support. Install Qt sources by running the \e MaintenanceTool, located in the root of \c INSTALL_DIR. Alternatively, \l {https://wiki.qt.io/Building_Qt_5_from_Git#Getting_the_source_code}{clone} the \e qt5 repository using git. \section1 Building Qt for Static Linking To use static linking, Qt must be built with the \c -static configuration option. The following configure command selects the correct options and \e 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: \badcode export SYSROOT_BASE=/5.6/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 \endcode 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 \SDK installation. Description of the used variables: \table \row \li \c SYSROOT_BASE \li Base directory for the sysroots (host and target) for the device \row \li \c TARGET_DEVICE \li Target device (mkspec) \row \li \c SYSROOT_TARGET \li Target sysroot directory under \c SYSROOT_BASE \row \li \c CROSSCOMPILE_PREFIX \li Cross-compilation toolchain path and tool prefix (ends with '-') \row \li \c HOST_PREFIX \li Location to install the host binaries (qmake, moc, rcc, etc.) \endtable Using the above variables, \e configure can be called as follows: \badcode cd ./configure -commercial -release -static \ -prefix /opt/qt5 -hostprefix $HOST_PREFIX \ -device $TARGET_DEVICE \ -device-option CROSS_COMPILE=$SYSROOT_BASE/$CROSSCOMPILE_PREFIX \ -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 \endcode Above, \c -prefix sets the intended destination of the Qt build on the device (sysroot). Running \c {make install} will, by default, install Qt under \c sysroot/prefix. Compiling in \e xcb support is disabled, OpenGL ES 2.0 support is selected, and \l [QtWebEngine] {Qt WebEngine} is excluded from the build, as it does not support static builds. More information about configure options is available in the \l [QtDoc] {Qt for Embedded Linux#Configuring a Specific Device}{Qt for Embedded Linux} documentation. If configuration is successful, proceed to build and install Qt: \badcode make -j6 && make install \endcode The host tools (in particular, qmake) are now installed in \c HOST_PREFIX, and the statically compiled Qt libraries are in \c $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 \e Kit for it: \list \li \l {https://doc.qt.io/qtcreator/creator-project-qmake.html}{Qt Creator: Adding Qt Versions} \li \l {https://doc.qt.io/qtcreator/creator-targets.html}{Qt Creator: Adding Kits} \endlist \section1 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 \l [QMake] {QTPLUGIN} variable. After running qmake, the project directory contains a \c _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: \badcode QTPLUGIN.imageformats = - \endcode Alternatively, the automatic generation of Q_IMPORT_PLUGIN() macros can be turned off: \badcode CONFIG -= import_plugins \endcode The relevant plugins then need to be explicitly imported in the application code. For more information, see \l {How to Create Qt Plugins#Static Plugins} {Static Plugins}. \section2 Adding QML Imports Similar to how Qt plugins are imported, qmake invokes the \e qmlimportscanner tool to scan the application's .qml files, and generates a \c _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 \c QtQuick and \c QtQuick.Window import statements, the following statements are generated: \code Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) \endcode 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 \e qmldir file needs to be accessible and located under the correct \l [QtQml] {QML Import Path} {QML import path}. For example, the following entries in a Qt resource collection file (.qrc) places the qmldir files under the \c qml/ prefix in resources: \badcode qml/QtQuick.2/qmldir qml/QtQuick/Window.2/qmldir \endcode Finally, the QML engine needs to be informed about the import path that's now located within the resources. The following implementation of \c main() sets the import path to \c qrc:/qml before loading \c main.qml: \code #include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.setImportPathList(QStringList(QStringLiteral("qrc:/qml"))); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } \endcode */