Yocto/Qt5: hello-qt part1 - Community/Wrapper/Image Size
Introduction
This work is sponsored by Reliable Embedded Systems. You can find more information about our training/consulting services here.
Objectives
The
goal of this blog post is to show my journey trying to build a hello-qt
application and reasons why I don't like Qt. As far as I can tell this is going to be a multi part blog post.
Community not valued by the Qt Company
Qt 5 was officially released on 19 December 2012 and on 31 August 2020 was the Qt 6 feature freeze so one would think the community prepares meta-qt6.
But the Qt Company sufficiently pissed off well known and respected community members and contributors to meta-qt5[1] so that it does not look like there will be community support for Qt 6 any time soon.
[1] meta-qt5 is a community project outside of The Qt Company and it's a lot more stable and easier to maintain then the Qt 5 layer from Qt.
The Qt Company decided to make their own meta-qt6 layer, but there are some concerns from the community: "The Qt policy for the layer changes is not well aligned with the way we usually maintain Yocto Project layers. We denied some of the changes they tried to do in the past and I always prefer when this kind of key component is maintained in a more neutral way.
Maintaining Qt is time-consuming and Martin has done a great job. If Qt is willing to do it, it is good but it'd be nice if it respects the good practices. I am a little concerned since Qt last tentative of closing source."
Let me add to this that the Qt Company has quite interesting ideas about licensing fees of their stuff as well as source code licensing, but this will be discussed in another blog post.
One wrapper to rule them all
"One framework. One codebase. Any platform."
This is the first thing you read on the Qt website. In my humble opinion every operating system has it's own philosophy and patterns and Qt (plus some others) try to sell us that it's possible to have "one for all". "
hello-qt
Let's say we wanted to run a minimal hello-qt application. No GUI just "Hello, Qt!". Something like that:
#include <QTextStream> int main() { QTextStream(stdout) << "Hello, Qt!" << Qt::endl; return 0; }
You can find more about it here.
core-image-minimal-qt5.bb
The image recipe looks like this:
# Copyright (C) 2020 Robert Berger <robert.berger@ReliableEmbeddedSystems.com> # Released under the MIT license (see COPYING.MIT for the terms) require recipes-core/images/common-img.inc require recipes-core/images/core-image-minimal.bb # qt support in SDK inherit populate_sdk_qt5 IMAGE_INSTALL += "\ dropbear \ udev-extraconf \ " # let's include a few qt components IMAGE_INSTALL += "\ qtbase \ qtserialport \ hello-qt \ " # this is a pure qt5 embedded demo image without X CONFLICT_DISTRO_FEATURES = "x11 wayland"
site.conf
I typically turn on buildhistory
. You will see later why.
An excerpt of my site.conf
looks like this:
PRSERV_HOST = "localhost:0" # It is recommended to activate "buildhistory" for testing the PR service # it also looks like with PR service + buildhistory packages are versioned # automatically if we change meta data INHERIT += "buildhistory" BUILDHISTORY_COMMIT = "1"
buildhistory.bbclass
buildhistory
class records a
history of build output metadata, which can be used to detect possible
regressions as well as used for analysis of the build output.
For more information on using Build History, see the
"Maintaining Build Output Quality"
section in the Yocto Project Development Tasks Manual.
local.conf
Recent Yocto versions enable ptests
in the poky
distro by default, which pulls in GPL-3.0 components and increases the image size. Let's remove those.
An excerpt of my local.conf
looks like this:
### --> remove ptest # remove some test cases and GPL-3.0 dependencies # Impact of ptest feature is now more significant # The Poky distribution configuration (DISTRO = "poky") enables ptests by default # to enable runtime testing of various components. In this release, a dependency # needed to be added that has resulted in a significant increase in the number of # components that will be built just when building a simple image such as core-image-minimal. # If you do not need runtime tests enabled for core components, then it is recommended that # you remove "ptest" from DISTRO_FEATURES to save a significant amount of build time # e.g. by adding the following in your configuration: DISTRO_FEATURES_remove = "ptest"
# <-- remove ptest
Another excerpt, which adds license compliance stuff to the image is here:
# include license text in image COPY_LIC_MANIFEST = "1" COPY_LIC_DIRS = "1"
Image size
core-image-minimal
Let's BitBake a core-image-minimal
:
$ bitbake core-image-minimal NOTE: Started PRServer with DBfile: /workdir/build/multi-v7-ml-qt5/cache/prserv.sqlite3, IP: 127.0.0.1, PORT: 46873, PID: 981784 Loading cache: 100% |#########################################################################################################################################| Time: 0:00:00 Loaded 3375 entries from dependency cache. Parsing recipes: 100% |#######################################################################################################################################| Time: 0:00:01 Parsing of 2266 .bb files complete (2264 cached, 2 parsed). 3377 targets, 141 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies Build Configuration: BB_VERSION = "1.46.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "universal" TARGET_SYS = "arm-resy-linux-gnueabi" MACHINE = "multi-v7-ml" DISTRO = "resy" DISTRO_VERSION = "3.1.2" TUNE_FEATURES = "arm armv7a vfp thumb callconvention-hard" TARGET_FPU = "hard" meta meta-poky meta-yocto-bsp = "2020-08-28-dunfell-3.1.2+:d3d80fa6fbf15189f6183a33c95fa90053535ae2" meta-multi-v7-ml-bsp = "dunfell:30a525012dcc6017beb3bdb735b53b6b07908303" meta-u-boot-wic-bsp = "dunfell:4dbfc93ee3fe797cee5a25ef7a389eeaec70f418" meta-resy = "dunfell:2968f06c1e400131e15bd726808a43195eec8c16" meta-oe meta-networking meta-filesystems meta-python = "2020-04-30-dunfell-3.1:17fd382f3467e20308924499b7531ae8b789f056" meta-qt5 = "2020-09-08-dunfell:0e7015f7a86dda995a39662edbb5c26da647c496" meta-qt5-examples = "<unknown>:<unknown>" Initialising tasks: 100% |####################################################################################################################################| Time: 0:00:01 Sstate summary: Wanted 2 Found 0 Missed 2 Current 716 (0% match, 99% complete) NOTE: Executing Tasks NOTE: Tasks Summary: Attempted 1920 tasks of which 1913 didn't need to be rerun and all succeeded. NOTE: Writing buildhistory NOTE: Writing buildhistory took: 1 seconds
Let's see the image size:
$ cat buildhistory/images/multi_v7_ml/glibc/core-image-minimal/image-info.txt DISTRO = resy DISTRO_VERSION = 3.1.2 USER_CLASSES = buildstats image-mklibs image-prelink IMAGE_CLASSES = license_image IMAGE_FEATURES = debug-tweaks IMAGE_LINGUAS = IMAGE_INSTALL = packagegroup-core-boot BAD_RECOMMENDATIONS = NO_RECOMMENDATIONS = PACKAGE_EXCLUDE = ROOTFS_POSTPROCESS_COMMAND = write_package_manifest; license_create_manifest; ssh_allow_empty_password; ssh_allow_root_login; postinst_enable_logging; rootfs_update_timestamp ; write_image_test_data ; empty_var_volatile; sort_passwd; rootfs_reproducible; IMAGE_POSTPROCESS_COMMAND = buildhistory_get_imageinfo ; IMAGESIZE = 66216
core-image-minimal-qt5
Let's BitBake a core-image-minimal-qt5
:
$ bitbake core-image-minimal-qt5 NOTE: Started PRServer with DBfile: /workdir/build/multi-v7-ml-qt5/cache/prserv.sqlite3, IP: 127.0.0.1, PORT: 45129, PID: 992954 Loading cache: 100% |#########################################################################################################################################| Time: 0:00:00 Loaded 3375 entries from dependency cache. Parsing recipes: 100% |#######################################################################################################################################| Time: 0:00:01 Parsing of 2266 .bb files complete (2264 cached, 2 parsed). 3377 targets, 141 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies Build Configuration: BB_VERSION = "1.46.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "universal" TARGET_SYS = "arm-resy-linux-gnueabi" MACHINE = "multi-v7-ml" DISTRO = "resy" DISTRO_VERSION = "3.1.2" TUNE_FEATURES = "arm armv7a vfp thumb callconvention-hard" TARGET_FPU = "hard" meta meta-poky meta-yocto-bsp = "2020-08-28-dunfell-3.1.2+:d3d80fa6fbf15189f6183a33c95fa90053535ae2" meta-multi-v7-ml-bsp = "dunfell:30a525012dcc6017beb3bdb735b53b6b07908303" meta-u-boot-wic-bsp = "dunfell:4dbfc93ee3fe797cee5a25ef7a389eeaec70f418" meta-resy = "dunfell:2968f06c1e400131e15bd726808a43195eec8c16" meta-oe meta-networking meta-filesystems meta-python = "2020-04-30-dunfell-3.1:17fd382f3467e20308924499b7531ae8b789f056" meta-qt5 = "2020-09-08-dunfell:0e7015f7a86dda995a39662edbb5c26da647c496" meta-qt5-examples = "<unknown>:<unknown>" Initialising tasks: 100% |####################################################################################################################################| Time: 0:00:02 Sstate summary: Wanted 0 Found 0 Missed 0 Current 1142 (0% match, 100% complete) NOTE: Executing Tasks NOTE: Tasks Summary: Attempted 2842 tasks of which 2842 didn't need to be rerun and all succeeded. NOTE: Writing buildhistory NOTE: Writing buildhistory took: 1 seconds
Let's see the image size:
$ cat buildhistory/images/multi_v7_ml/glibc/core-image-minimal-qt5/image-info.txt DISTRO = resy DISTRO_VERSION = 3.1.2 USER_CLASSES = buildstats image-mklibs image-prelink IMAGE_CLASSES = license_image IMAGE_FEATURES = debug-tweaks IMAGE_LINGUAS = IMAGE_INSTALL = packagegroup-core-boot dropbear udev-extraconf qtbase qtserialport hello-qt BAD_RECOMMENDATIONS = NO_RECOMMENDATIONS = PACKAGE_EXCLUDE = ROOTFS_POSTPROCESS_COMMAND = write_package_manifest; license_create_manifest; ssh_allow_empty_password; ssh_allow_root_login; postinst_enable_logging; rootfs_update_timestamp ; write_image_test_data ; empty_var_volatile; sort_passwd; rootfs_reproducible; IMAGE_POSTPROCESS_COMMAND = buildhistory_get_imageinfo ; IMAGESIZE = 115496
This means the image size grew from 66216 to 115496 which is a 74% increase.
Some guilty Qt libraries:
$ cat buildhistory/images/multi_v7_ml/glibc/core-image-minimal-qt5/files-in-image.txt | grep libQt | sort -r -n -k4 -rwxr-xr-x root root 4672392 ./usr/lib/libQt5Core.so.5.14.2 -rwxr-xr-x root root 4523576 ./usr/lib/libQt5Widgets.so.5.14.2 -rwxr-xr-x root root 4489300 ./usr/lib/libQt5Gui.so.5.14.2 -rwxr-xr-x root root 1267084 ./usr/lib/libQt5Network.so.5.14.2 -rwxr-xr-x root root 841944 ./usr/lib/libQt5XcbQpa.so.5.14.2 -rwxr-xr-x root root 435568 ./usr/lib/libQt5DBus.so.5.14.2 -rwxr-xr-x root root 288100 ./usr/lib/libQt5PrintSupport.so.5.14.2 -rwxr-xr-x root root 243188 ./usr/lib/libQt5Test.so.5.14.2 -rwxr-xr-x root root 238952 ./usr/lib/libQt5OpenGL.so.5.14.2 -rwxr-xr-x root root 214364 ./usr/lib/libQt5Sql.so.5.14.2 -rwxr-xr-x root root 169304 ./usr/lib/libQt5Xml.so.5.14.2 -rwxr-xr-x root root 71008 ./usr/lib/libQt5SerialPort.so.5.14.2 -rwxr-xr-x root root 17860 ./usr/lib/libQt5Concurrent.so.5.14.2 lrwxrwxrwx root root 28 ./usr/lib/libQt5PrintSupport.so.5 -> libQt5PrintSupport.so.5.14.2 lrwxrwxrwx root root 28 ./usr/lib/libQt5PrintSupport.so.5.14 -> libQt5PrintSupport.so.5.14.2 lrwxrwxrwx root root 26 ./usr/lib/libQt5SerialPort.so.5 -> libQt5SerialPort.so.5.14.2 lrwxrwxrwx root root 26 ./usr/lib/libQt5SerialPort.so.5.14 -> libQt5SerialPort.so.5.14.2 lrwxrwxrwx root root 26 ./usr/lib/libQt# include license text in image COPY_LIC_MANIFEST = "1" COPY_LIC_DIRS = "1" 5Concurrent.so.5 -> libQt5Concurrent.so.5.14.2 lrwxrwxrwx root root 26 ./usr/lib/libQt5Concurrent.so.5.14 -> libQt5Concurrent.so.5.14.2 lrwxrwxrwx root root 23 ./usr/lib/libQt5Widgets.so.5 -> libQt5Widgets.so.5.14.2 lrwxrwxrwx root root 23 ./usr/lib/libQt5Widgets.so.5.14 -> libQt5Widgets.so.5.14.2 lrwxrwxrwx root root 23 ./usr/lib/libQt5Network.so.5 -> libQt5Network.so.5.14.2 lrwxrwxrwx root root 23 ./usr/lib/libQt5Network.so.5.14 -> libQt5Network.so.5.14.2 lrwxrwxrwx root root 22 ./usr/lib/libQt5XcbQpa.so.5 -> libQt5XcbQpa.so.5.14.2 lrwxrwxrwx root root 22 ./usr/lib/libQt5XcbQpa.so.5.14 -> libQt5XcbQpa.so.5.14.2 lrwxrwxrwx root root 22 ./usr/lib/libQt5OpenGL.so.5 -> libQt5OpenGL.so.5.14.2 lrwxrwxrwx root root 22 ./usr/lib/libQt5OpenGL.so.5.14 -> libQt5OpenGL.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5Test.so.5 -> libQt5Test.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5Test.so.5.14 -> libQt5Test.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5DBus.so.5 -> libQt5DBus.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5DBus.so.5.14 -> libQt5DBus.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5Core.so.5 -> libQt5Core.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5Core.so.5.14 -> libQt5Core.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Xml.so.5 -> libQt5Xml.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Xml.so.5.14 -> libQt5Xml.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Sql.so.5 -> libQt5Sql.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Sql.so.5.14 -> libQt5Sql.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Gui.so.5 -> libQt5Gui.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Gui.so.5.14 -> libQt5Gui.so.5.14.2
License Compliance artifacts plus a few libs and executables coming from Qt:
$ cat buildhistory/images/multi_v7_ml/glibc/core-image-minimal-qt5/files-in-image.txt | grep qt | sort -r -n -k4 | more -rw-r--r-- root root 79543 ./usr/share/common-licenses/qtbase-qmlplugins/LICENSE.QT-LICENSE-AGREEMENT -rw-r--r-- root root 79543 ./usr/share/common-licenses/qtbase-plugins/LICENSE.QT-LICENSE-AGREEMENT -rw-r--r-- root root 79543 ./usr/share/common-licenses/qtbase/LICENSE.QT-LICENSE-AGREEMENT -rwxr-xr-x root root 42328 ./usr/lib/plugins/generic/libqtuiotouchplugin.so -rw-r--r-- root root 36363 ./usr/share/common-licenses/qtserialport-qmlplugins/LICENSE.GPL3-EXCEPT -rw-r--r-- root root 36363 ./usr/share/common-licenses/qtserialport-plugins/LICENSE.GPL3-EXCEPT -rw-r--r-- root root 36363 ./usr/share/common-licenses/qtserialport/LICENSE.GPL3-EXCEPT -rw-r--r-- root root 36363 ./usr/share/common-licenses/qtbase-qmlplugins/LICENSE.GPL3-EXCEPT -rw-r--r-- root root 36363 ./usr/share/common-licenses/qtbase-plugins/LICENSE.GPL3-EXCEPT -rw-r--r-- root root 36363 ./usr/share/common-licenses/qtbase/LICENSE.GPL3-EXCEPT -rw-r--r-- root root 35147 ./usr/share/common-licenses/qtserialport-qmlplugins/LICENSE.GPL3 -rw-r--r-- root root 35147 ./usr/share/common-licenses/qtserialport-plugins/LICENSE.GPL3 -rw-r--r-- root root 35147 ./usr/share/common-licenses/qtserialport/LICENSE.GPL3 -rw-r--r-- root root 35147 ./usr/share/common-licenses/qtbase-qmlplugins/LICENSE.GPL3 -rw-r--r-- root root 35147 ./usr/share/common-licenses/qtbase-plugins/LICENSE.GPL3 -rw-r--r-- root root 35147 ./usr/share/common-licenses/qtbase/LICENSE.GPL3 -rw-r--r-- root root 22961 ./usr/share/common-licenses/qtserialport-qmlplugins/LICENSE.FDL -rw-r--r-- root root 22961 ./usr/share/common-licenses/qtserialport-plugins/LICENSE.FDL -rw-r--r-- root root 22961 ./usr/share/common-licenses/qtserialport/LICENSE.FDL -rw-r--r-- root root 22961 ./usr/share/common-licenses/qtbase-qmlplugins/LICENSE.FDL -rw-r--r-- root root 22961 ./usr/share/common-licenses/qtbase-plugins/LICENSE.FDL -rw-r--r-- root root 22961 ./usr/share/common-licenses/qtbase/LICENSE.FDL -rw-r--r-- root root 18092 ./usr/share/common-licenses/qtserialport-qmlplugins/LICENSE.GPL2 -rw-r--r-- root root 18092 ./usr/share/common-licenses/qtserialport-plugins/LICENSE.GPL2 -rw-r--r-- root root 18092 ./usr/share/common-licenses/qtserialport/LICENSE.GPL2 -rw-r--r-- root root 18092 ./usr/share/common-licenses/qtbase-qmlplugins/LICENSE.GPL2 -rw-r--r-- root root 18092 ./usr/share/common-licenses/qtbase-plugins/LICENSE.GPL2 -rw-r--r-- root root 18092 ./usr/share/common-licenses/qtbase/LICENSE.GPL2 -rw-r--r-- root root 18032 ./usr/share/common-licenses/hello-qt/LICENSE -rw-r--r-- root root 7651 ./usr/share/common-licenses/qtserialport-qmlplugins/LICENSE.LGPL3 -rw-r--r-- root root 7651 ./usr/share/common-licenses/qtserialport-plugins/LICENSE.LGPL3 -rw-r--r-- root root 7651 ./usr/share/common-licenses/qtserialport/LICENSE.LGPL3 -rw-r--r-- root root 7651 ./usr/share/common-licenses/qtbase-qmlplugins/LICENSE.LGPL3 -rw-r--r-- root root 7651 ./usr/share/common-licenses/qtbase-plugins/LICENSE.LGPL3 -rw-r--r-- root root 7651 ./usr/share/common-licenses/qtbase/LICENSE.LGPL3 -rwxr-xr-x root root 5556 ./usr/bin/hello-qt drwxr-xr-x root root 4096 ./usr/share/common-licenses/qtserialport-qmlplugins drwxr-xr-x root root 4096 ./usr/share/common-licenses/qtserialport-plugins drwxr-xr-x root root 4096 ./usr/share/common-licenses/qtserialport drwxr-xr-x root root 4096 ./usr/share/common-licenses/qtbase-qmlplugins drwxr-xr-x root root 4096 ./usr/share/common-licenses/qtbase-plugins drwxr-xr-x root root 4096 ./usr/share/common-licenses/qtbase drwxr-xr-x root root 4096 ./usr/share/common-licenses/hello-qt -rw-r--r-- root root 3253 ./usr/share/mime/text/vnd.qt.linguist.xml -rw-r--r-- root root 2458 ./usr/share/mime/application/x-qtiplot.xml -rw-r--r-- root root 195 ./usr/share/common-licenses/qtserialport/recipeinfo -rw-r--r-- root root 195 ./usr/share/common-licenses/qtserialport-qmlplugins/recipeinfo -rw-r--r-- root root 195 ./usr/share/common-licenses/qtserialport-plugins/recipeinfo -rw-r--r-- root root 195 ./usr/share/common-licenses/qtbase/recipeinfo -rw-r--r-- root root 195 ./usr/share/common-licenses/qtbase-qmlplugins/recipeinfo -rw-r--r-- root root 195 ./usr/share/common-licenses/qtbase-plugins/recipeinfo -rw-r--r-- root root 54 ./usr/share/common-licenses/hello-qt/recipeinfo lrwxrwxrwx root root 43 ./usr/share/common-licenses/qtserialport-qmlplugins/generic_The-Qt-Company-GPL-Exception-1.0 -> ../generic_The-Qt-Company-GPL-Exc eption-1.0 lrwxrwxrwx root root 43 ./usr/share/common-licenses/qtserialport-plugins/generic_The-Qt-Company-GPL-Exception-1.0 -> ../generic_The-Qt-Company-GPL-Except ion-1.0 lrwxrwxrwx root root 43 ./usr/share/common-licenses/qtserialport/generic_The-Qt-Company-GPL-Exception-1.0 -> ../generic_The-Qt-Company-GPL-Exception-1.0 lrwxrwxrwx root root 43 ./usr/share/common-licenses/qtbase-qmlplugins/generic_The-Qt-Company-GPL-Exception-1.0 -> ../generic_The-Qt-Company-GPL-Exception -1.0 lrwxrwxrwx root root 43 ./usr/share/common-licenses/qtbase-plugins/generic_The-Qt-Company-GPL-Exception-1.0 -> ../generic_The-Qt-Company-GPL-Exception-1. 0 lrwxrwxrwx root root 43 ./usr/share/common-licenses/qtbase/generic_The-Qt-Company-GPL-Exception-1.0 -> ../generic_The-Qt-Company-GPL-Exception-1.0 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtserialport-qmlplugins/generic_LGPL-3.0 -> ../generic_LGPL-3.0 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtserialport-qmlplugins/generic_GFDL-1.3 -> ../generic_GFDL-1.3 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtserialport-plugins/generic_LGPL-3.0 -> ../generic_LGPL-3.0 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtserialport-plugins/generic_GFDL-1.3 -> ../generic_GFDL-1.3 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtserialport/generic_LGPL-3.0 -> ../generic_LGPL-3.0 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtserialport/generic_GFDL-1.3 -> ../generic_GFDL-1.3 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtbase-qmlplugins/generic_LGPL-3.0 -> ../generic_LGPL-3.0 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtbase-qmlplugins/generic_GFDL-1.3 -> ../generic_GFDL-1.3 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtbase-plugins/generic_LGPL-3.0 -> ../generic_LGPL-3.0 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtbase-plugins/generic_GFDL-1.3 -> ../generic_GFDL-1.3 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtbase/generic_LGPL-3.0 -> ../generic_LGPL-3.0 lrwxrwxrwx root root 19 ./usr/share/common-licenses/qtbase/generic_GFDL-1.3 -> ../generic_GFDL-1.3 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtserialport-qmlplugins/generic_GPL-3.0 -> ../generic_GPL-3.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtserialport-qmlplugins/generic_GPL-2.0 -> ../generic_GPL-2.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtserialport-plugins/generic_GPL-3.0 -> ../generic_GPL-3.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtserialport-plugins/generic_GPL-2.0 -> ../generic_GPL-2.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtserialport/generic_GPL-3.0 -> ../generic_GPL-3.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtserialport/generic_GPL-2.0 -> ../generic_GPL-2.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtbase-qmlplugins/generic_GPL-3.0 -> ../generic_GPL-3.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtbase-qmlplugins/generic_GPL-2.0 -> ../generic_GPL-2.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtbase-plugins/generic_GPL-3.0 -> ../generic_GPL-3.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtbase-plugins/generic_GPL-2.0 -> ../generic_GPL-2.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtbase/generic_GPL-3.0 -> ../generic_GPL-3.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/qtbase/generic_GPL-2.0 -> ../generic_GPL-2.0 lrwxrwxrwx root root 18 ./usr/share/common-licenses/hello-qt/generic_GPL-2.0 -> ../generic_GPL-2.0 lrwxrwxrwx root root 14 ./usr/share/common-licenses/qtserialport-qmlplugins/generic_BSD -> ../generic_BSD lrwxrwxrwx root root 14 ./usr/share/common-licenses/qtserialport-plugins/generic_BSD -> ../generic_BSD lrwxrwxrwx root root 14 ./usr/share/common-licenses/qtserialport/generic_BSD -> ../generic_BSD lrwxrwxrwx root root 14 ./usr/share/common-licenses/qtbase-qmlplugins/generic_BSD -> ../generic_BSD lrwxrwxrwx root root 14 ./usr/share/common-licenses/qtbase-plugins/generic_BSD -> ../generic_BSD lrwxrwxrwx root root 14 ./usr/share/common-licenses/qtbase/generic_BSD -> ../generic_BSD
Attempt to decrease image size
PACKAGECONFIG
This variable provides a means of enabling or disabling
features of a recipe on a per-recipe basis.
PACKAGECONFIG
blocks are defined
in recipes when you specify features and then arguments
that define feature behaviors.
Here is the basic block structure (broken over multiple
lines for readability):
PACKAGECONFIG ??= "f1 f2 f3 ..." PACKAGECONFIG[f1] = "\ --with-f1, \ --without-f1, \ build-deps-for-f1, \ runtime-deps-for-f1, \ runtime-recommends-for-f1, \ packageconfig-conflicts-for-f1 \ " PACKAGECONFIG[f2] = "\ ... and so on and so on ...
The PACKAGECONFIG
variable itself specifies a space-separated list of the
features to enable.
Following the features, you can determine the behavior of
each feature by providing up to six order-dependent
arguments, which are separated by commas.
You can omit any argument you like but must retain the
separating commas.
The order is important and specifies the following:
Extra arguments that should be added to the configure script argument list (
EXTRA_OECONF
orPACKAGECONFIG_CONFARGS
) if the feature is enabled.Extra arguments that should be added to
EXTRA_OECONF
orPACKAGECONFIG_CONFARGS
if the feature is disabled.Additional build dependencies (
DEPENDS
) that should be added if the feature is enabled.Additional runtime dependencies (
RDEPENDS
) that should be added if the feature is enabled.Additional runtime recommendations (
RRECOMMENDS
) that should be added if the feature is enabled.Any conflicting (that is, mutually exclusive)
PACKAGECONFIG
settings for this feature.
Consider the following
PACKAGECONFIG
block taken from the
librsvg
recipe.
In this example the feature is gtk
,
which has three arguments that determine the feature's
behavior.
PACKAGECONFIG[gtk] = "--with-gtk3,--without-gtk3,gtk+3"
The --with-gtk3
and
gtk+3
arguments apply only if
the feature is enabled.
In this case, --with-gtk3
is
added to the configure script argument list and
gtk+3
is added to
DEPENDS
.
On the other hand, if the feature is disabled say through
a .bbappend
file in another layer, then
the second argument --without-gtk3
is
added to the configure script instead.
The basic PACKAGECONFIG
structure
previously described holds true regardless of whether you
are creating a block or changing a block.
When creating a block, use the structure inside your
recipe.
If you want to change an existing
PACKAGECONFIG
block, you can do so
one of two ways:
Append file: Create an append file named
recipename
.bbappend
in your layer and override the value ofPACKAGECONFIG
. You can either completely override the variable:PACKAGECONFIG = "f4 f5"
Or, you can just append the variable:
PACKAGECONFIG_append = " f4"
Configuration file: This method is identical to changing the block through an append file except you edit your
local.conf
or
file. As with append files previously described, you can either completely override the variable:mydistro
.confPACKAGECONFIG_pn-
recipename
= "f4 f5"Or, you can just amend the variable:
PACKAGECONFIG_append_pn-
recipename
= " f4"
local.conf
Qt tends to pull in lots of stuff via PACKAGECONFIG, so let's try to remove a couple of things globally.
An excerpt of my local.conf looks like this:
### --> qt-5 remove stuff DISTRO_FEATURES_remove = "wayland" DISTRO_FEATURES_remove = "vulkan" DISTRO_FEATURES_remove = "x11" DISTRO_FEATURES_remove = "opengl" DISTRO_FEATURES_remove = "alsa" DISTRO_FEATURES_remove = "pulseaudio" DISTRO_FEATURES_remove = "gobject-introspection-data" DISTRO_FEATURES_remove = "3g" DISTRO_FEATURES_remove = "nfc" ### <-- qt-5 remove stuff
qtbase_git.bbappend
I created a meta-qt5-examples layer, which contains, among other things, a qtbase_git.bbappend file where I'll try to remove more things via PACKAGECONFIG
.
An excerpt of my meta-qt5-examples/recipes-qt/qt5/qtbase_git.bbappend
looks like this:
# Things we don't use: # PACKAGECONFIG_DEFAULT="accessibility udev evdev widgets tools libs freetype tests pcre"
PACKAGECONFIG_DEFAULT_remove = "accessibility"
PACKAGECONFIG_DEFAULT_remove = "dbus"
PACKAGECONFIG_DEFAULT_remove = "tests"
PACKAGECONFIG_DEFAULT_remove = "widgets"
# PACKAGECONFIG="release accessibility udev evdev tools libs freetype pcre openssl no-opengl jpeg libpng zlib"
# we could remove a few more here
PACKAGECONFIG_DEFAULT
and PACKAGECONFIG
for qtbase
. That's how it looks like after the changes from above:pokyuser@200239fdab09:/workdir/build/multi-v7-ml-qt5$ bitbake qtbase -e | grep ^PACKAGECONFIG_DEFAULT= PACKAGECONFIG_DEFAULT=" udev evdev tools libs freetype pcre " pokyuser@200239fdab09:/workdir/build/multi-v7-ml-qt5$ bitbake qtbase -e | grep ^PACKAGECONFIG= PACKAGECONFIG=" release udev evdev tools libs freetype pcre openssl no-opengl jpeg libpng zlib "
core-image-minimal-qt5 - Second attempt
Let's BitBake a core-image-minimal-qt5
:
$ bitbake core-image-minimal-qt5 NOTE: Started PRServer with DBfile: /workdir/build/multi-v7-ml-qt5/cache/prserv.sqlite3, IP: 127.0.0.1, PORT: 44461, PID: 1007916 Loading cache: 100% |#########################################################################################################################################| Time: 0:00:00 Loaded 3375 entries from dependency cache. Parsing recipes: 100% |#######################################################################################################################################| Time: 0:00:01 Parsing of 2266 .bb files complete (2264 cached, 2 parsed). 3377 targets, 372 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies Build Configuration: BB_VERSION = "1.46.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "universal" TARGET_SYS = "arm-resy-linux-gnueabi" MACHINE = "multi-v7-ml" DISTRO = "resy" DISTRO_VERSION = "3.1.2" TUNE_FEATURES = "arm armv7a vfp thumb callconvention-hard" TARGET_FPU = "hard" meta meta-poky meta-yocto-bsp = "2020-08-28-dunfell-3.1.2+:d3d80fa6fbf15189f6183a33c95fa90053535ae2" meta-multi-v7-ml-bsp = "dunfell:30a525012dcc6017beb3bdb735b53b6b07908303" meta-u-boot-wic-bsp = "dunfell:4dbfc93ee3fe797cee5a25ef7a389eeaec70f418" meta-resy = "dunfell:2968f06c1e400131e15bd726808a43195eec8c16" meta-oe meta-networking meta-filesystems meta-python = "2020-04-30-dunfell-3.1:17fd382f3467e20308924499b7531ae8b789f056" meta-qt5 = "2020-09-08-dunfell:0e7015f7a86dda995a39662edbb5c26da647c496" meta-qt5-examples = "<unknown>:<unknown>" Initialising tasks: 100% |####################################################################################################################################| Time: 0:00:01 Sstate summary: Wanted 5 Found 5 Missed 0 Current 805 (100% match, 100% complete) NOTE: Executing Tasks NOTE: Tasks Summary: Attempted 2131 tasks of which 2131 didn't need to be rerun and all succeeded. NOTE: Writing buildhistory NOTE: Writing buildhistory took: 1 seconds
Let's see the image size:
$ cat buildhistory/images/multi_v7_ml/glibc/core-image-minimal-qt5/image-info.txt DISTRO = resy DISTRO_VERSION = 3.1.2 USER_CLASSES = buildstats image-mklibs image-prelink IMAGE_CLASSES = license_image IMAGE_FEATURES = debug-tweaks IMAGE_LINGUAS = IMAGE_INSTALL = packagegroup-core-boot dropbear udev-extraconf qtbase qtserialport hello-qt BAD_RECOMMENDATIONS = NO_RECOMMENDATIONS = PACKAGE_EXCLUDE = ROOTFS_POSTPROCESS_COMMAND = write_package_manifest; license_create_manifest; ssh_allow_empty_password; ssh_allow_root_login; postinst_enable_logging; rootfs_update_timestamp ; write_image_test_data ; empty_var_volatile; sort_passwd; rootfs_reproducible; IMAGE_POSTPROCESS_COMMAND = buildhistory_get_imageinfo ; IMAGESIZE = 82752
This means the image size grew from 66216 to 82752 which is a 25% increase and a decrease of 28% compared to 115496 which we had before.
Some guilty Qt libraries (less then before):
$ cat buildhistory/images/multi_v7_ml/glibc/core-image-minimal-qt5/files-in-image.txt | grep libQt | sort -r -n -k4 -rwxr-xr-x root root 4664104 ./usr/lib/libQt5Core.so.5.14.2 -rwxr-xr-x root root 3895380 ./usr/lib/libQt5Gui.so.5.14.2 -rwxr-xr-x root root 1267084 ./usr/lib/libQt5Network.so.5.14.2 -rwxr-xr-x root root 243188 ./usr/lib/libQt5Test.so.5.14.2 -rwxr-xr-x root root 214364 ./usr/lib/libQt5Sql.so.5.14.2 -rwxr-xr-x root root 169304 ./usr/lib/libQt5Xml.so.5.14.2 -rwxr-xr-x root root 71008 ./usr/lib/libQt5SerialPort.so.5.14.2 -rwxr-xr-x root root 17860 ./usr/lib/libQt5Concurrent.so.5.14.2 lrwxrwxrwx root root 26 ./usr/lib/libQt5SerialPort.so.5 -> libQt5SerialPort.so.5.14.2 lrwxrwxrwx root root 26 ./usr/lib/libQt5SerialPort.so.5.14 -> libQt5SerialPort.so.5.14.2 lrwxrwxrwx root root 26 ./usr/lib/libQt5Concurrent.so.5 -> libQt5Concurrent.so.5.14.2 lrwxrwxrwx root root 26 ./usr/lib/libQt5Concurrent.so.5.14 -> libQt5Concurrent.so.5.14.2 lrwxrwxrwx root root 23 ./usr/lib/libQt5Network.so.5 -> libQt5Network.so.5.14.2 lrwxrwxrwx root root 23 ./usr/lib/libQt5Network.so.5.14 -> libQt5Network.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5Test.so.5 -> libQt5Test.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5Test.so.5.14 -> libQt5Test.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5Core.so.5 -> libQt5Core.so.5.14.2 lrwxrwxrwx root root 20 ./usr/lib/libQt5Core.so.5.14 -> libQt5Core.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Xml.so.5 -> libQt5Xml.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Xml.so.5.14 -> libQt5Xml.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Sql.so.5 -> libQt5Sql.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Sql.so.5.14 -> libQt5Sql.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Gui.so.5 -> libQt5Gui.so.5.14.2 lrwxrwxrwx root root 19 ./usr/lib/libQt5Gui.so.5.14 -> libQt5Gui.so.5.14.2
Conclusion
If you really want to use Qt and keep your image small you should definitly have a look at PACKAGECONFIG
and how it works. And even if you don't use Qt it's a good idea to learn how to use PACKAGECONFIG
.
Part two is here.
Comments
Post a Comment