From f7b22de2ee53554448f27df20792ef593b081f8a Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 18 Nov 2015 13:32:24 +0100 Subject: Doc: Add documentation on static builds Add documentation on how to configure Qt for a static build using cross-compilation with B2Qt toolchain, and how to manage linking of static Qt plugins and QML imports. Task-number: QTEE-983 Change-Id: Ied0172fc92dbaa1290389ba321d4588c3df9e54c Reviewed-by: Kalle Viironen Reviewed-by: Laszlo Agocs --- src/doc/src/qtee-custom-embedded-linux.qdoc | 2 +- src/doc/src/qtee-index.qdoc | 3 + src/doc/src/qtee-static-linking.qdoc | 226 ++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 src/doc/src/qtee-static-linking.qdoc (limited to 'src/doc/src') diff --git a/src/doc/src/qtee-custom-embedded-linux.qdoc b/src/doc/src/qtee-custom-embedded-linux.qdoc index df156bd..ae65a6b 100644 --- a/src/doc/src/qtee-custom-embedded-linux.qdoc +++ b/src/doc/src/qtee-custom-embedded-linux.qdoc @@ -20,7 +20,7 @@ \page qtee-custom-embedded-linux-image.html \title Building Your Own Embedded Linux Image \previouspage qtee-customization.html - \nextpage qtee-changelog.html + \nextpage qtee-static-linking.html \B2QL is built using the tools and resources from the \l {Yocto Project}, and is based on Yocto's reference distribution (\e Poky). You can diff --git a/src/doc/src/qtee-index.qdoc b/src/doc/src/qtee-index.qdoc index 3ea844a..5fb4556 100644 --- a/src/doc/src/qtee-index.qdoc +++ b/src/doc/src/qtee-index.qdoc @@ -59,6 +59,9 @@ \endlist \li \l{Customization} \li \l{Building Your Own Embedded Linux Image} + \list + \li \l{Linking to Static Builds of Qt} + \endlist \li \l{ChangeLog} \li \l{Troubleshooting} \li \l{Known Issues} diff --git a/src/doc/src/qtee-static-linking.qdoc b/src/doc/src/qtee-static-linking.qdoc new file mode 100644 index 0000000..33ebd6b --- /dev/null +++ b/src/doc/src/qtee-static-linking.qdoc @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** 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 + + As the first step before configuring Qt, the \e mkspec for the target device + needs to be copied over to Qt sources, so that \e qmake will reference the + correct toolchains when creating the makefiles. + + Using Raspberry Pi 2 as an example: + + \badcode + cp -a /5.6/Boot2Qt/raspberrypi2-eLinux/qt5/mkspecs/devices/linux-rasp-pi2-g++-b2qt \ + /qtbase/mkspecs/devices + \endcode + + Above, is the location of Qt sources (top-level directory containing + the \e configure script). + + 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-eLinux/toolchain/sysroots + export TARGET_DEVICE=linux-rasp-pi2-g++-b2qt + 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 + + 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. + + 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 +*/ -- cgit v1.2.3