1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
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 <INSTALL_DIR>/5.6/Boot2Qt/raspberrypi2-eLinux/qt5/mkspecs/devices/linux-rasp-pi2-g++-b2qt \
<QT_SRC>/qtbase/mkspecs/devices
\endcode
Above, <QT_SRC> 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=<INSTALL_DIR>/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 <QT_SRC>
./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 <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:
\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 <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 \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
<file>qml/QtQuick.2/qmldir</file>
<file>qml/QtQuick/Window.2/qmldir</file>
\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 <QGuiApplication>
#include <QQmlApplicationEngine>
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
*/
|