编辑
2025-01-22
工作知识
0
请注意,本文编写于 135 天前,最后修改于 135 天前,其中某些信息可能已经过时。

目录

一、关于qt的交叉编译
二、实现思路
2.1 下载交叉编译工具链
2.2 下载sysroot环境
2.3 配置qmake
2.4 配置qt.conf
三、演示

我们开发工作中,如果是面向嵌入式的场景,很多客户其实倾向于使用交叉编译工具链,我们作为操作系统可以提供与系统本身gcc版本一致的交叉编译工具,这样构建的时候就不用担心libc/binutils等版本不匹配导致的符号问题从而构建的二进制无法运行的问题,关于交叉编译工具链的文章和工具获取,可以参考交叉编译环境搭建,本文主要谈一谈关于qt工程中,如果直接使用qmake来进行交叉编译过程中,我们需要修改qt.conf和qmake.conf的一些细节性问题

一、关于qt的交叉编译

我们可以通过qt官方的wiki找到支持qt的交叉编译的办法,根据此办法,我相信大家能够很轻易的支持到qt环境的交叉编译,关于qt环境的交叉编译的细节就不再赘述,有兴趣可以仔细看看文档,文章链接如下:

https://wiki.qt.io/Cross-Compile_Qt_6_for_Raspberry_Pi

如果wiki.qt.io无法正常访问,那么github上关于qt的cross compiling的文章也是一样的意思,如下

https://github.com/UvinduW/Cross-Compiling-Qt-for-Raspberry-Pi-4

还有一篇文章可以辅助了解

https://www.stefanocottafavi.com/crosscompile-qt-for-rpi/

根据上面的信息,我简单描述如下:

  1. 获取sysroot,sysroot就是我们的系统环境
  2. 获取交叉编译工具链
  3. 下载qt的源码
  4. 在构建源码时指定CROSS_COMPILE和–sysroot
  5. 构建完成之后,此时我们的qt工程可以通过qt源码的qmake直接生成Makefile完成构建

根据上面的简述,可以知道,我们在讨论qt的交叉编译的时候,往往是通过构建了qt的源码库。从而生成了对应的qmake和相关配置,我们直接使用qmake和相关配置即可完成交叉构建。这也是qt官方推荐的做法。

但是,本文需要的是直接基于sysroot中已安装的qt版本,来手动配置qmake和qtconf来实现交叉编译,那么这可以省略编译qt源码安插–sysroot这一个步骤。与上面官方的方法不同的点我列表如下:

qt官方:需要构建qt源码工程

本文讨论的:无需构建qt源码工程,程序链接sysroot下的qt库文件

二、实现思路

我们知道如果不想通过重新构建qt源码来实现交叉编译的话,我们就需要在host上强行指定好sysroot,头文件位置,库文件位置,数据文件位置等。这需要对qmake和qt.conf有详细的了解。这也是本文讨论的重点。主要步骤如下:

2.1 下载交叉编译工具链

我们可以通过linaro官网上下载工具链,也可以使用我们提供的工具链,交叉编译环境搭建有提到工具链地址是

gcc-kylin-9.3.0-2024.10-x86_64_aarch64-linux-gnu.tar.gz 文件获取位置(110服务器):/home/yangquan/develop/嵌入式相关/01_嵌入式定制部门/嵌入式版本项目&产品版本问题解决集/KylinSdk

2.2 下载sysroot环境

我们需要一个编译的sysroot环境,这个环境可以在已有的机器环境上打包其rootfs,也可以在麒麟平台上根据系统iso的filesystem.squashfs来进行解压获取,里面是一个标准的操作系统环境,我们还需要在这个环境中根据deb包来下载安装必要的头文件和动态库

2.3 配置qmake

qt默认提供了基于aarch64的交叉编译配置,地址如下:

/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-aarch64-gnu-g++/qmake.conf

我们可以发现其会设置相应的环境变量,例如

QMAKE_CC = aarch64-linux-gnu-gcc QMAKE_CXX = aarch64-linux-gnu-g++ QMAKE_LINK = aarch64-linux-gnu-g++ QMAKE_LINK_SHLIB = aarch64-linux-gnu-g++ # modifications to linux.conf QMAKE_AR = aarch64-linux-gnu-ar cqs QMAKE_OBJCOPY = aarch64-linux-gnu-objcopy QMAKE_NM = aarch64-linux-gnu-nm -P QMAKE_STRIP = aarch64-linux-gnu-strip

可以发现,这里指向的是交叉编译工具链中的编译工具

2.4 配置qt.conf

我们配置了qmake默认使用交叉编译工具之后,还需要配置qt.conf,如下:

[Paths] Prefix=/usr ArchData=lib/aarch64-linux-gnu/qt5 Binaries=lib/qt5/bin Data=share/qt5 TargetSpec=linux-aarch64-gnu-g++ HostSpec=linux-aarch64-gnu-g++ Documentation=share/qt5/doc Examples=lib/aarch64-linux-gnu/qt5/examples Headers=include/aarch64-linux-gnu/qt5 HostBinaries=lib/qt5/bin HostData=lib/x86_64-linux-gnu/qt5 HostLibraries=lib/x86_64-linux-gnu Imports=lib/aarch64-linux-gnu/qt5/imports Libraries=lib/aarch64-linux-gnu LibraryExecutables=lib/aarch64-linux-gnu/qt5/libexec Plugins=lib/aarch64-linux-gnu/qt5/plugins Qml2Imports=lib/aarch64-linux-gnu/qt5/qml Settings=/etc/xdg Translations=share/qt5/translations Sysroot=/root/tf/kylin_test_cross/sysroot SysrootifyPrefix=true

例如sysroot位置,header文件查找位置,libraries库查找位置。

有了这个qt.conf,我们的一些环境变量会发生改变,例如,如果没有qt.conf,我们query的信息如下:

# qmake -query QT_SYSROOT: QT_INSTALL_PREFIX:/usr QT_INSTALL_ARCHDATA:/usr/lib/x86_64-linux-gnu/qt5 QT_INSTALL_DATA:/usr/share/qt5 QT_INSTALL_DOCS:/usr/share/qt5/doc QT_INSTALL_HEADERS:/usr/include/x86_64-linux-gnu/qt5 QT_INSTALL_LIBS:/usr/lib/x86_64-linux-gnu QT_INSTALL_LIBEXECS:/usr/lib/x86_64-linux-gnu/qt5/libexec QT_INSTALL_BINS:/usr/lib/qt5/bin QT_INSTALL_TESTS:/usr/tests QT_INSTALL_PLUGINS:/usr/lib/x86_64-linux-gnu/qt5/plugins QT_INSTALL_IMPORTS:/usr/lib/x86_64-linux-gnu/qt5/imports QT_INSTALL_QML:/usr/lib/x86_64-linux-gnu/qt5/qml QT_INSTALL_TRANSLATIONS:/usr/share/qt5/translations QT_INSTALL_CONFIGURATION:/etc/xdg QT_INSTALL_EXAMPLES:/usr/lib/x86_64-linux-gnu/qt5/examples QT_INSTALL_DEMOS:/usr/lib/x86_64-linux-gnu/qt5/examples QT_HOST_PREFIX:/usr QT_HOST_DATA:/usr/lib/x86_64-linux-gnu/qt5 QT_HOST_BINS:/usr/lib/qt5/bin QT_HOST_LIBS:/usr/lib/x86_64-linux-gnu QMAKE_SPEC:linux-g++ QMAKE_XSPEC:linux-g++ QMAKE_VERSION:3.1 QT_VERSION:5.12.8

可以发现其默认指向了本地的库和头文件,并未设置sysroot地址,如果我们指定qt.conf,则如下

# qmake -query -qtconf ./qt.conf QT_SYSROOT:/root/tf/kylin_test_cross/sysroot/ QT_SYSROOT:/root/tf/kylin_test_cross/sysroot QT_INSTALL_PREFIX:/root/tf/kylin_test_cross/sysroot/usr QT_INSTALL_PREFIX/raw:/usr QT_INSTALL_ARCHDATA:/root/tf/kylin_test_cross/sysroot/usr/lib/aarch64-linux-gnu/qt5 QT_INSTALL_ARCHDATA/raw:/usr/lib/aarch64-linux-gnu/qt5 QT_INSTALL_DATA:/root/tf/kylin_test_cross/sysroot/usr/share/qt5 QT_INSTALL_DATA/raw:/usr/share/qt5 QT_INSTALL_DOCS:/root/tf/kylin_test_cross/sysroot/usr/share/qt5/doc QT_INSTALL_DOCS/raw:/usr/share/qt5/doc QT_INSTALL_HEADERS:/root/tf/kylin_test_cross/sysroot/usr/include/aarch64-linux-gnu/qt5 QT_INSTALL_HEADERS/raw:/usr/include/aarch64-linux-gnu/qt5 QT_INSTALL_LIBS:/root/tf/kylin_test_cross/sysroot/usr/lib/aarch64-linux-gnu QT_INSTALL_LIBS/raw:/usr/lib/aarch64-linux-gnu QT_INSTALL_LIBEXECS:/root/tf/kylin_test_cross/sysroot/usr/lib/aarch64-linux-gnu/qt5/libexec QT_INSTALL_LIBEXECS/raw:/usr/lib/aarch64-linux-gnu/qt5/libexec QT_INSTALL_BINS:/root/tf/kylin_test_cross/sysroot/usr/lib/qt5/bin QT_INSTALL_BINS/raw:/usr/lib/qt5/bin QT_INSTALL_TESTS:/root/tf/kylin_test_cross/sysroot/usr/tests QT_INSTALL_TESTS/raw:/usr/tests QT_INSTALL_PLUGINS:/root/tf/kylin_test_cross/sysroot/usr/lib/aarch64-linux-gnu/qt5/plugins QT_INSTALL_PLUGINS/raw:/usr/lib/aarch64-linux-gnu/qt5/plugins QT_INSTALL_IMPORTS:/root/tf/kylin_test_cross/sysroot/usr/lib/aarch64-linux-gnu/qt5/imports QT_INSTALL_IMPORTS/raw:/usr/lib/aarch64-linux-gnu/qt5/imports QT_INSTALL_QML:/root/tf/kylin_test_cross/sysroot/usr/lib/aarch64-linux-gnu/qt5/qml QT_INSTALL_QML/raw:/usr/lib/aarch64-linux-gnu/qt5/qml QT_INSTALL_TRANSLATIONS:/root/tf/kylin_test_cross/sysroot/usr/share/qt5/translations QT_INSTALL_TRANSLATIONS/raw:/usr/share/qt5/translations QT_INSTALL_CONFIGURATION:/root/tf/kylin_test_cross/sysroot/etc/xdg QT_INSTALL_CONFIGURATION/raw:/etc/xdg QT_INSTALL_EXAMPLES:/root/tf/kylin_test_cross/sysroot/usr/lib/aarch64-linux-gnu/qt5/examples QT_INSTALL_EXAMPLES/raw:/usr/lib/aarch64-linux-gnu/qt5/examples QT_INSTALL_DEMOS:/root/tf/kylin_test_cross/sysroot/usr/lib/aarch64-linux-gnu/qt5/examples QT_INSTALL_DEMOS/raw:/usr/lib/aarch64-linux-gnu/qt5/examples QT_HOST_PREFIX:/usr QT_HOST_DATA:/usr/lib/x86_64-linux-gnu/qt5 QT_HOST_BINS:/usr/lib/qt5/bin QT_HOST_LIBS:/usr/lib/x86_64-linux-gnu QMAKE_SPEC:linux-aarch64-gnu-g++ QMAKE_XSPEC:linux-aarch64-gnu-g++ QMAKE_VERSION:3.1 QT_VERSION:5.12.8

可以发现,我们headers和libs等等都从正确的路径寻找。

至此,我们发现,整个qt.conf和qmake.conf已经正确配置,我们可以良好的进行编译构建。

三、演示

如果对于一个qt仓库,我们以qt的example为例,/usr/lib/x86_64-linux-gnu/qt5/examples/gui/analogclock。我们可以如下:

cd /usr/lib/x86_64-linux-gnu/qt5/examples/gui/analogclock

我们需要根据qmake生成Makefile,如下

/usr/lib/qt5/bin/qmake -qtconf ./qt.conf

然后直接make,如下:

make

此时,我们会生成如下文件

# file analogclock analogclock: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=5f848734c8f59a6958bf829be3a72dd4d6b0a124, for GNU/Linux 3.7.0, not stripped

此时,文件生成完成,可以发现是aarch64的qt程序,我们将其发送到实际机器上即可正常运行。