yocto系列讲解 (实战篇) 55 - 编译Qt程序和添加Qt的recipe(bb文件)

By: fu linux
E-mail: fulinux@sina.com
Blog: https://blog.csdn.net/fulinus
喜欢的盆友欢迎点赞和订阅!
你的喜欢就是我写作的动力!

结果展示:
在这里插入图片描述
在这里插入图片描述
参考上一篇: yocto实战讲解系列之添加Qt5和生成带Qt5的SDK

返回总目录 Yocto开发讲解系列 - 总目录

概述

上一篇我们讲解了如何添加Qt5软件包和构建带有Qt5的toolchain SDK,并且在我们的qemux86虚拟机中已经安装了Qt5相关的软件包。本篇将继续完成如下工作:

  1. 如何使用编译出来的toolchain SDK来编译自己的Qt程序;
  2. 如何将我们的Qt程序整合到yocto中;

创建一个简单的Qt5程序

要完成上面的任务我们首先需要有一个Qt的daemon来做实验才行。
这里我就不在赘述如何安装Qt creator软件了,网络上面教大家如何安装Qt creator的教程也有很多,我自己安装的版本是v4.13.2。我要提一点,我记得我安装Qt creatror的时候,有的软件包很大,而有的很小。大家竟可能安装完整的,还有就是windows和ubuntu上安装都可以。
在这里插入图片描述
首先我们打开上面图片中的Qt creator 4.13.2。
在首页中搜索QML,我们找到一个下面图片中先是的一个例子,点击它
在这里插入图片描述
会弹出这个:
在这里插入图片描述
在点击 Configure Project 按键,项目如下:

在这里插入图片描述
我们点击左下角运行按键,看看能不能正常运行:
在这里插入图片描述
找到这个实例的代码:

C:\Qt\Examples\Qt-5.15.1\qml\qml-i18n
  • 1

将其放在ubuntu系统的某个目录中,例如我的:

/home/peeta/code/qml-i18n
  • 1

至此,我们的QML编程的Qt程序准备好了。

安装带Qt5 toolchain SDK

  1. 将前篇文章中编译出来的SDK复制到某个目录中,我的操作如下:
code]$ pwd
/home/peeta/code
code]$ cp ~/poky/build/tmp-qemux86-64/deploy/sdk/poky-glibc-x86_64-meta-toolchain-core2-64-qemux86-64-toolchain-3.2.2.sh .
  • 1
  • 2
  • 3
  1. 安装sdk:
code]$ ./poky-glibc-x86_64-meta-toolchain-core2-64-qemux86-64-toolchain-3.2.2.sh 
Poky (Yocto Project Reference Distro) SDK installer version 3.2.2
=================================================================
Enter target directory for SDK (default: /opt/poky/3.2.2): 
You are about to install the SDK to "/opt/poky/3.2.2". Proceed [Y/n]? 
[sudo] password for peeta: 
Extracting SDK......................................................................................................................................................................................................................................................................................................................done
Setting it up...done
SDK has been successfully set up and is ready to be used.
Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g.
 $ . /opt/poky/3.2.2/environment-setup-core2-64-poky-linux
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 使能SDK的环境:
code]$ . /opt/poky/3.2.2/environment-setup-core2-64-poky-linux
  • 1
  1. 确认下SDK的sysroot中是否有Qt相关的软件包:
code]$ ls /opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib
...
libQt5QuickControls2.so
...
code]$ ls /opt/poky/3.2.2/sysroots/x86_64-pokysdk-linux/usr/lib/
...
libQt5Qml.so.5
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. 编译Qt程序
code]$ cd qml-i18n/
qml-i18n]$ qmake
Info: creating stash file /home/peeta/code/qml-i18n/.qmake.stash
qml-i18n]$ ls
doc   main.cpp  qmake_qmake_qm_files.qrc  qml-i18n.pro.user  qml-i18n.qmlproject
i18n  Makefile  qml-i18n.pro              qml-i18n.qml       qml-i18n.qrc
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

可见上面生成Makefile文件了。

qml-i18n]$ make
x86_64-poky-linux-g++  -m64 -march=core2 -mtune=core2 -msse3 -mfpmath=sse -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.2.2/sysroots/core2-64-poky-linux -c -pipe  -O2 -pipe -g -feliminate-unused-debug-types  --sysroot=/opt/poky/3.2.2/sysroots/core2-64-poky-linux -O2 -Wall -Wextra -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQuick -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtGui -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQmlModels -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQml -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtNetwork -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtCore -I. -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/libdrm -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/mkspecs/linux-oe-g++ -o main.o main.cpp
/opt/poky/3.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/rcc -name qml-i18n qml-i18n.qrc -o qrc_qml-i18n.cpp
x86_64-poky-linux-g++  -m64 -march=core2 -mtune=core2 -msse3 -mfpmath=sse -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.2.2/sysroots/core2-64-poky-linux -c -pipe  -O2 -pipe -g -feliminate-unused-debug-types  --sysroot=/opt/poky/3.2.2/sysroots/core2-64-poky-linux -O2 -Wall -Wextra -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQuick -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtGui -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQmlModels -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQml -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtNetwork -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtCore -I. -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/libdrm -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/mkspecs/linux-oe-g++ -o qrc_qml-i18n.o qrc_qml-i18n.cpp
/opt/poky/3.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/lrelease i18n/base.ts -qm .qm/base.qm
Updating '.qm/base.qm'...
    Generated 0 translation(s) (0 finished and 0 unfinished)
    Ignored 1 untranslated source text(s)
/opt/poky/3.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/lrelease i18n/qml_en.ts -qm .qm/qml_en.qm
Updating '.qm/qml_en.qm'...
    Generated 0 translation(s) (0 finished and 0 unfinished)
/opt/poky/3.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/lrelease i18n/qml_en_AU.ts -qm .qm/qml_en_AU.qm
Updating '.qm/qml_en_AU.qm'...
    Generated 1 translation(s) (1 finished and 0 unfinished)
/opt/poky/3.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/lrelease i18n/qml_fr.ts -qm .qm/qml_fr.qm
Updating '.qm/qml_fr.qm'...
    Generated 1 translation(s) (1 finished and 0 unfinished)
/opt/poky/3.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/rcc -name qmake_qmake_qm_files qmake_qmake_qm_files.qrc -o qrc_qmake_qmake_qm_files.cpp
x86_64-poky-linux-g++  -m64 -march=core2 -mtune=core2 -msse3 -mfpmath=sse -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.2.2/sysroots/core2-64-poky-linux -c -pipe  -O2 -pipe -g -feliminate-unused-debug-types  --sysroot=/opt/poky/3.2.2/sysroots/core2-64-poky-linux -O2 -Wall -Wextra -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQuick -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtGui -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQmlModels -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtQml -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtNetwork -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/QtCore -I. -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/include/libdrm -I/opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/mkspecs/linux-oe-g++ -o qrc_qmake_qmake_qm_files.o qrc_qmake_qmake_qm_files.cpp
x86_64-poky-linux-g++  -m64 -march=core2 -mtune=core2 -msse3 -mfpmath=sse -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.2.2/sysroots/core2-64-poky-linux -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,-z,relro,-z,now --sysroot=/opt/poky/3.2.2/sysroots/core2-64-poky-linux -Wl,-O1 -o qml-i18n main.o qrc_qml-i18n.o qrc_qmake_qmake_qm_files.o   /opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/libQt5Quick.so /opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/libQt5Gui.so /opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/libQt5QmlModels.so /opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/libQt5Qml.so /opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/libQt5Network.so /opt/poky/3.2.2/sysroots/core2-64-poky-linux/usr/lib/libQt5Core.so -lGL -lpthread
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
qml-i18n]$ ls -l
-rwxrwxr-x 1 peeta peeta 501224 515 14:30 qml-i18n #这个就是最终的执行程序
  • 1
  • 2

OK~ 编译一次成功!

  1. 将其复制到qemu虚拟机
    首先在ubuntu的终端中运行qemu虚拟机:
build]$ runqemu qemux86-64
  • 1

在另外一个终端上去除ssh的密钥:

$ ssh-keygen -f "/home/peeta/.ssh/known_hosts" -R 192.168.7.2
  • 1

使用scp命令复制:

qml-i18n]$ scp qml-i18n root@192.168.7.2:~/
qml-i18n                                                                           100%  489KB 489.5KB/s   00:00
  • 1
  • 2
  1. 在虚拟机中运行
    首先我们前面已经将qml-i18n复制到了qemu虚拟机的root用户根目录下,需要添加执行权限:
qml-i18n]$ ssh root@192.168.7.2
root@qemux86-64:~# chmod +x qml-i18n
  • 1
  • 2

执行我们的Qt程序:

root@qemux86-64:~# ./qml-i18n 
qt.qpa.xcb: could not connect to display 
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: minimal, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, xcb.

Aborted
root@qemux86-64:~#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

出错了!看这个提示“qt.qpa.xcb: could not connect to display ”,无法连接显示设备?
具体不是很清楚,但是我在网上找到 方法 ,设置如下命令:

root@qemux86-64:~# export DISPLAY=:0.0
root@qemux86-64:~# ./qml-i18n
  • 1
  • 2

这次在我们的QEMU虚拟机上面有显示了,但是不同于ubuntu上面,没有文字显示,应该是字体库的问题:

在这里插入图片描述

添加现成的字体库

我们先添加字体库看看。
我这里有一个现成的字体库 DroidSansFallback.ttf (链接: https://pan.baidu.com/s/1ajjdPB97VEkpJYOjJ_P5FQ 提取码:uatu ),并将其复制到qemu上面,如下:

code]$ scp DroidSansFallback.ttf root@192.168.7.2:~/
DroidSansFallback.ttf                                                              100% 4423KB   4.3MB/s   00:01
  • 1
  • 2

设置字体库路径:

root@qemux86-64:~# ls
DroidSansFallback.ttf  qml-i18n
root@qemux86-64:~# export QT_QPA_FONTDIR='/home/root/'
  • 1
  • 2
  • 3

再次运行:

root@qemux86-64:~# export DISPLAY=:0.0
root@qemux86-64:~# ./qml-i18n
  • 1
  • 2

可以正常显示了:

在这里插入图片描述

yocto中添加字体库

上面我们是手动添加字体库的,那再yocto中如何添加字体库呢?
我不认为yocto或者Qt不考虑字体库的问题,那么我们Qt为啥没有字体显示或者存在字体库问题呢?
首先我们进入文件系统,通过搜索发现:

poky]$ cd build/tmp-qemux86-64/work/qemux86_64-poky-linux/core-image-sato/1.0-r0/rootfs/
[peeta@peeta-OptiPlex-7050 rootfs]$ find -iname *.ttf
./usr/share/fonts/ttf/LiberationSerif-Bold.ttf
./usr/share/fonts/ttf/LiberationSans-Regular.ttf
./usr/share/fonts/ttf/LiberationSans-BoldItalic.ttf
./usr/share/fonts/ttf/LiberationSans-Italic.ttf
./usr/share/fonts/ttf/LiberationMono-Italic.ttf
./usr/share/fonts/ttf/LiberationSerif-BoldItalic.ttf
./usr/share/fonts/ttf/LiberationSerif-Regular.ttf
./usr/share/fonts/ttf/LiberationSerif-Italic.ttf
./usr/share/fonts/ttf/LiberationMono-Bold.ttf
./usr/share/fonts/ttf/LiberationMono-Regular.ttf
./usr/share/fonts/ttf/LiberationSans-Bold.ttf
./usr/share/fonts/ttf/LiberationMono-BoldItalic.ttf
./usr/lib/qml/QtQuick/Dialogs/qml/icons.ttf
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

说明我们的文件系统镜像在/usr/share/fonts中是有很多字体库的,那么,我们前面设置字体库的参数改下看看:

root@qemux86-64:~# export QT_QPA_FONTDIR='/usr/share/fonts/ttf'
root@qemux86-64:~# ./qml-i18n 
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/var/volatile/tmp/runtime-root'
libGL error: pci id for fd 8: 1234:1111, driver (null)
libGL error: MESA-LOADER: failed to open bochs-drm (search paths /usr/lib/dri)
libGL error: failed to load driver: bochs-drm
libGL error: pci id for fd 8: 1234:1111, driver (null)
libGL error: MESA-LOADER: failed to open bochs-drm (search paths /usr/lib/dri)
libGL error: failed to load driver: bochs-drm
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

也是可以正常显示的。
但是Qt程序需要设置这些字体库的环境变量吗?这个很奇怪,太不智能了哈~
通过观察发现:

rootfs]$ ls usr/share/
fontconfig/ fonts/ ...
  • 1
  • 2

是存在fontconfig的(Fontconfig是一个用于配置和自定义字体访问的库),而这个fontconfig是负责管理字体库的工具,Qt这么专业的软件不可能没有使用fontconfig工具吧,那么他对于Qt怎么没有生效呢?我们看下meta-qt5:

meta-qt5]$ grep -in fontconfig -r .
./recipes-qt/qt5/qtwebkit_git.bb:79:    fontconfig \
./recipes-qt/qt5/qtwebkit_git.bb:90:PACKAGECONFIG[fontconfig] = "-DENABLE_TEST_SUPPORT=ON,-DENABLE_TEST_SUPPORT=OFF,fontconfig"
./recipes-qt/qt5/qtwebengine/0004-mkspecs-Allow-builds-with-libc-glibc.patch:40:                         "webengine-system-fontconfig",
./recipes-qt/qt5/qtwebengine_git.bb:24:    libdrm libxkbcommon fontconfig pixman openssl pango cairo pciutils nss \
./recipes-qt/qt5/qtbase_git.bb:51:PACKAGECONFIG_KDE ?= "${@bb.utils.contains('DISTRO_FEATURES', 'kde', 'sm cups fontconfig kms gbm libinput sql-sqlite openssl', '', d)}"
./recipes-qt/qt5/qtbase_git.bb:99:# works only together with fontconfig
./recipes-qt/qt5/qtbase_git.bb:131:PACKAGECONFIG[fontconfig] = "-fontconfig,-no-fontconfig,fontconfig"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

通过搜索我们发现qtwebkit、qtwebengine和qtbase是有这个fontconfig配置项的,但是不一定使能了。我们进一步分析一下:
meta-qt5/recipes-qt/packagegroups/packagegroup-qt5-toolchain-target.bb 文件中我们可以没有看到有安装 qtwebkit qtwebengine (这两个和浏览器有关),在rootfs/usr/{bin/ lib/}下面也没有看到相关的,只剩下 qtbase 。我们看下 recipes-qt/qt5/qtbase_git.bb ,如下:

meta-qt5]$ vim ./recipes-qt/qt5/qtbase_git.bb
#只罗列有fontconfig字眼的行:
PACKAGECONFIG_KDE ?= "${@bb.utils.contains('DISTRO_FEATURES', 'kde', 'sm cups fontconfig kms gbm libinput sql-sqlite openssl', '', d)}"
PACKAGECONFIG ?= " ... ${PACKAGECONFIG_KDE} ..."
...
PACKAGECONFIG[fontconfig] = "-fontconfig,-no-fontconfig,fontconfig"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

小知识点:PACKAGECONFIG变量提供了一种按需启用或禁用recipe的某个特性或功能的方法。

经过观察和分析:如果要使我们的 qtbase 在编译的时候带上 -fontconfig,-no-fontconfig,fontconfig 选项,需要在 DISTRO_FEATURES (发版本特性)中具有 kde 特性,但是有吗?我们看下:

build]$ bitbake -e core-image-sato | grep DISTRO_FEATURES=
DISTRO_FEATURES="acl alsa argp bluetooth ext2 ipv4 ipv6 largefile pcmcia usbgadget usbhost wifi xattr nfs zeroconf pci 3g nfc x11 vfat largefile opengl ptest multiarch wayland vulkan pulseaudio sysvinit gobject-introspection-data ldconfig"
  • 1
  • 2

很显然我们的 DISTRO_FEATURES 中没有 kde 特性,进一步看 qtbase 中的 PACKAGECONFIG 也没有看到fontconfig:

build]$ bitbake -e qtbase | grep PACKAGECONFIG= 
PACKAGECONFIG="release accessibility dbus udev evdev widgets tools libs freetype pcre tests vulkan openssl gl xcb glib xkbcommon jpeg libpng zlib"
  • 1
  • 2

综上,我们的Qt程序之所以不能显示文本主要就是因为 qtbase 没有使能 fontconfig 功能。
我们应该如何使能该功能呢?

Qt5中使能字体库配置

我准备继续为 qtbase 创建一个 bbappend 文件。参考我下面的操作:

meta-mylayer]$ mkdir -p recipes-qt/qt5/  
meta-mylayer]$ vim recipes-qt/qt5/qtbase_git.bbappend
#添加:
PACKAGECONFIG_append_pn = " fontconfig"
  • 1
  • 2
  • 3
  • 4

编译:

poky]$ source oe-init-build-env 
build]$ bitbake -e qtbase | grep PACKAGECONFIG= 
PACKAGECONFIG="release accessibility dbus udev evdev widgets tools libs freetype pcre tests vulkan openssl gl xcb glib xkbcommon jpeg libpng zlib fontconfig" #这里就比上面多了fontconfig了
build]$ bitbake qtbase -c cleansstate
build]$ bitbake core-image-sato
  • 1
  • 2
  • 3
  • 4
  • 5

编译完成后开始测试:

qml-i18n]$ ssh-keygen -f "/home/peeta/.ssh/known_hosts" -R 192.168.7.2
qml-i18n]$ scp qml-i18n root@192.168.7.2:~/
qml-i18n]$ ssh root@192.168.7.2
root@qemux86-64:~# export DISPLAY=:0.0
root@qemux86-64:~# ./qml-i18n
  • 1
  • 2
  • 3
  • 4
  • 5

显示结果能够正常显示字体,说明我们的添加fontconfig成功。
在这里插入图片描述

如何编译qtbase自带的Example

Qt软件包中自身带有很多的Example实例程序,主要是为了方便开发人员编程参考,那么我们如何使能这些example编译呢?
我们以qtbase为例,在 meta-qt5/recipes-qt/qt5/qtbase_git.bb 文件中看到这一行:

PACKAGECONFIG[examples] = "-make examples -compile-examples,-nomake examples"
#如果PACKAGECONFIG中带有examples参数,那么会使能:"-make examples -compile-examples", 否则使能的是"-nomake examples",
#这里的逗号就起到了选项的功能
  • 1
  • 2
  • 3

那我们参考前面的使能fontconfig的做法使能这个example看看:

poky]$ vim meta-mylayer/recipes-qt/qt5/qtbase_git.bbappend
PACKAGECONFIG_append = " fontconfig"
PACKAGECONFIG_append = " examples" #新添加
  • 1
  • 2
  • 3

然后呢我们就开始编译过程。

build]$ bitbake qtbase -c cleansstate
build]$ bitbake core-image-sato -c cleansstate
build]$ bitbake core-image-sato
  • 1
  • 2
  • 3

编译完成后我们查看下qtbase中的image, 由此可见是编译了的。

build]$ ls tmp-qemux86-64/work/core2-64-poky-linux/qtbase/5.15.2+gitAUTOINC+40143c189b-r0/image/usr/share/examples/
corelib  examples.pro  network  qpa           qtestlib  sql     widgets
dbus     gui           opengl   qtconcurrent  README    vulkan  xml
  • 1
  • 2
  • 3

其他的Qt组件操作也类似。

如何添加自己的Qt应用程序

这里我们假设通过Qt creator开发了一个自己的应用,那我如何添加到yocto中去呢?
前面我们讲到如何使用构建出来的toolchain SDK来手动编译一个Qt应用,常规的流程就是:

$ qmake .
$ make
$ scp xxx yyyy:/usr/bin/
  • 1
  • 2
  • 3

但是我们的yocto是高度集成化的东西,我们如果这么笨拙的去编译一个qt应用显然是不合适的。

这里我们大家可以使用Qt creator工具开发一个程序,或者我这里直接选取一个qt的example来模拟自己开发的应用,比如这个应用:

C:\Qt\Examples\Qt-5.15.1\quick\mousearea
  • 1

首先我们在自己的meta-mylayer中创建recipe和bb文件等,过程参考如下:

  1. 准备recipe目录和源码
meta-mylayer]$ mkdir -p recipes-qt/qtapps #以后这个qtapps用来放qt的应用程序
meta-mylayer]$ cp ../build/tmp-qemux86-64/work/core2-64-poky-linux/qtdeclarative/5.15.2+gitAUTOINC+104eae5b17-r0/git/examples/quick/mousearea/ recipes-qt/qtapps/ -rf
  • 1
  • 2
  1. 创建bb文件
meta-mylayer]$ vim recipes-qt/qtapps/mousearea_git.bb
# My application of Qt5 for example

SUMMARY = "My application of Qt5 for example"
LICENSE = "CLOSED"

FILESEXTRAPATHS_prepend := "${THISDIR}/:"
SRC_DIR = "mousearea"
SRC_URI = "file://mousearea/"

S = "${WORKDIR}/mousearea"

DEPENDS = "qtdeclarative"

inherit qmake5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

上面基本上完成了我们的bb文件内容。
开始编译看看:

poky]$ source oe-init-build-env
build]$ bitbake mousearea
  • 1
  • 2

不过报错了:

| ../mousearea/main.cpp:50:10: fatal error: ../shared/shared.h: No such file or directory
|    50 | #include "../shared/shared.h"
  • 1
  • 2

说明我们的源码还少了东西。我们将少的目录复制到 recipes-qt/qtapps/ 中去,然后修改bb文件

meta-mylayer]$ cp ../build/tmp-qemux86-64/work/core2-64-poky-linux/qtdeclarative/5.15.2+gitAUTOINC+104eae5b17-r0/git/examples/quick/shared/ recipes-qt/qtapps/ -rf

meta-mylayer]$ vim recipes-qt/qtapps/mousearea_git.bb
SRC_URI = "file://mousearea/"
SRC_URI += "file://shared/" #加上这一行
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

出现了新的问题:

[peeta@peeta-OptiPlex-7050 build]$ bitbake mousearea
...
ERROR: mousearea-git-r0 do_package: QA Issue: mousearea: Files/directories were installed but not shipped in any package:
  /usr/share/examples/quick/mousearea/mousearea
Please set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.
mousearea: 1 installed and not shipped files. [installed-vs-shipped]
ERROR: mousearea-git-r0 do_package: Fatal QA errors found, failing task.
ERROR: Logfile of failure stored in: /home/peeta/poky/build/tmp-qemux86-64/work/core2-64-poky-linux/mousearea/git-r0/temp/log.do_package.15485
ERROR: Task (/home/peeta/poky/meta-mylayer/recipes-qt/qtapps/mousearea_git.bb:do_package) failed with exit code '1'
NOTE: Tasks Summary: Attempted 2331 tasks of which 2319 didn't need to be rerun and 1 failed.

Summary: 1 task failed:
  /home/peeta/poky/meta-mylayer/recipes-qt/qtapps/mousearea_git.bb:do_package
Summary: There was 1 WARNING message shown.
Summary: There were 2 ERROR messages shown, returning a non-zero exit code.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

不过这个问题还是比较好解决的,修改bb文件:

meta-mylayer]$ vim recipes-qt/qtapps/mousearea_git.bb
...
INSANE_SKIP_${PN} := "installed-vs-shipped" #添加这个
  • 1
  • 2
  • 3

但是,此时我们的moursearea还没有安装到目标镜像中,需要调用IMAGE_INSTALL变量镜像安装。我们在前面创建的 recipes-sato/images/core-image-sato.bbappend 文件中添加这个语句,如下:

meta-mylayer]$ vim recipes-sato/images/core-image-sato.bbappend
...
FEATURE_PACKAGES_qt5 = "packagegroup-qt5-toolchain-target"

IMAGE_INSTALL += "mousearea"
  • 1
  • 2
  • 3
  • 4
  • 5
poky]$ source oe-init-build-env
build]$ bitbake core-image-sato
  • 1
  • 2

但是实际结果是我们并没有在下面的目录中看到安装的mousearea:

build]$ ls tmp-qemux86-64/work/qemux86_64-poky-linux/core-image-sato/1.0-r0/rootfs/usr/share/
#没有examples目录
  • 1
  • 2

此时,需要继续修改bb文件,使用FILES变量指定安装文件或者目录:

meta-mylayer]$ vim recipes-qt/qtapps/mousearea_git.bb
...
INSANE_SKIP_${PN} := "installed-vs-shipped" #添加这个
FILES_${PN} = "${datadir}/*" #datadir指向的就是/usr/share/
  • 1
  • 2
  • 3
  • 4

再次编译验证:

build]$ bitbake mousearea 
build]$ bitbake core-image-sato
build]$ ls tmp-qemux86-64/work/qemux86_64-poky-linux/core-image-sato/1.0-r0/rootfs/usr/share/examples/quick/mousearea/mousearea 
tmp-qemux86-64/work/qemux86_64-poky-linux/core-image-sato/1.0-r0/rootfs/usr/share/examples/quick/mousearea/mousearea
  • 1
  • 2
  • 3
  • 4

我们需要的文件就出来了:

或者,我们可以修改源码,将其编译的文件正常放到/usr/bin目录下:

meta-mylayer]$ vim recipes-qt/qtapps/mousearea/mousearea.pro
#将
#target.path = $$[QT_INSTALL_EXAMPLES]/quick/mousearea
#改为:
target.path = /usr/bin
  • 1
  • 2
  • 3
  • 4
  • 5

再次编译就可以看到了:

build]$ bitbake mousearea 
build]$ bitbake core-image-sato
build]$ ls -l tmp-qemux86-64/work/qemux86_64-poky-linux/core-image-sato/1.0-r0/rootfs/usr/bin/moursearea
-rwxr-xr-x 1 peeta peeta 26752 39  2018 tmp-qemux86-64/work/qemux86_64-poky-linux/core-image-sato/1.0-r0/rootfs/usr/bin/mousearea
  • 1
  • 2
  • 3
  • 4

运行验证:

root@qemux86-64:~# export DISPLAY=:0.0
root@qemux86-64:~# /usr/share/examples/quick/mousearea/mousearea
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/var/volatile/tmp/runtime-root'
libGL error: pci id for fd 7: 1234:1111, driver (null)
libGL error: MESA-LOADER: failed to open bochs-drm (search paths /usr/lib/dri)
libGL error: failed to load driver: bochs-drm
libGL error: pci id for fd 7: 1234:1111, driver (null)
libGL error: MESA-LOADER: failed to open bochs-drm (search paths /usr/lib/dri)
libGL error: failed to load driver: bochs-drm
qml: Entered
qml: Pressed (LeftButton shift=false)
qml: Exited (pressed=false)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述
其中红色的用于测试鼠标点击有文本提示,蓝色框框可以拖动

Qt的任务目前就到这里了,如果有什么疑问可以在评论区讨论提出来!

End ~

您的点赞和留言是我持续更新的动力!欢迎关注!
在这里插入图片描述