ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RK3588 Qt交叉编译环境搭建全流程实战解析

RK3588 Qt交叉编译环境搭建全流程实战解析 简介面向RK3588开发板进行QT应用开发的工程师这份项目代码包提供了在Ubuntu 20.04.5上搭建交叉编译环境所需的配置框架。资源聚焦环境变量设置、qmake.conf修改、编译参数定义等关键操作能够帮助开发者快速理解并复现从交叉编译器配置到开发套件新建的完整流程尤其适合需要规避常见环境配置问题的中高级嵌入式开发者。包体十分精简共3个文件包含一个HTML说明页面、一个inscode工程环境配置以及一个gitignore规则文件总计仅6KB适合作为轻量级配置模板或笔记。目前已有232人学习下载。与常见的安装类文档不同该压缩包将编译配置要点浓缩为可直接参考的代码骨架结合描述中的步骤梳理读者可对照自身工程调整qmake与工具链路径并利用其中环境变量与宏定义示例检查自己的构建脚本从而减少盲试成本尽快在RK3588平台上运行起第一个QT程序。1. 在RK3588上跑Qt程序为什么绕不开交叉编译做RK3588平台开发的早晚会遇到一个坎程序在电脑上编译得好好的拷到开发板上要么运行不起来要么提示缺少某某so库要么丢核心文件。原因很简单——你的电脑是x86架构RK3588是ARM架构机器指令不通用。想在RK3588上跑Qt程序就必须先解决交叉编译这件事。我最早接手一块RK3588工控板时也觉得“不就是个Linux嘛直接上板编译不就行了”结果Qt源码拉下来、configure一跑编译到一半发现开发板的CPU风扇狂转整个rootfs被临时文件塞爆一个库编下来比预计时间多出几倍。后来老实回到“主机交叉编译 编译产物拷板运行”这条路才把整个流程稳定下来。所谓QT交叉编译环境搭建本质上就是在x86主机上准备一套“面向RK3588”的编译链让它生成能直接跑在ARM64平台上的Qt可执行文件和依赖库。这个过程有三个要素交叉编译器、目标系统的头文件与库sysroot以及Qt源码本身。三者只要有一个版本对不上后面就会冒出一堆奇怪错误。这套流程不搞明白不管你是做车载仪表、智能物流柜还是工控HMI后续开发都会非常痛苦。我推荐在Ubuntu 22.04 x86_64主机上做这套环境开发板烧写RK3588官方的Ubuntu或Debian镜像。这样主机和板子的系统都是接近的版本拷贝库的时候兼容性好很多。如果主机还在用老的Ubuntu 18.04也能做但gcc版本、libc版本跟板子的系统容易出现不匹配属于给自己挖坑。2. 先备齐这些材料主机、工具链、Sysroot与Qt源码的取舍2.1 主机与板卡系统的版本不要乱搭在动手前请先把三样东西准备好一台x86_64架构的Linux主机推荐Ubuntu 22.04内存16GB以上磁盘剩余空间至少20GB。一块RK3588开发板系统烧好能通过SSH访问。一个Qt源码包建议使用qt-everywhere-src-5.15.2.tar.xz或者选择LTS的5.12.10/5.15.x版本。Qt6在RK3588上不是不能用但插件的编译要求更高入门阶段没有必要增加复杂度。板卡系统建议用官方提供的Ubuntu或Debian镜像而不是从头做的busybox根文件系统。原因很实际桌面系统里已经包含了大量运行时依赖比如字体、标准库、input驱动出现问题时排查范围会小很多。如果你用的是Buildroot裁剪出来的系统后面每一个Qt依赖库都要手工补进rootfs排查环境问题的成本会直线上升。2.2 交叉编译器用apt还是用SDK工具链常见的交叉工具链有三种来源。第一种是Ubuntu官方源直接安装命令很简单sudo apt install gcc-aarch64-linux-gnu g-aarch64-linux-gnu安装后编译器的名字是aarch64-linux-gnu-gcc和aarch64-linux-gnu-g。这种方案适合快速搭建只要板子系统也是Debian/Ubuntu体系编译出来的程序大概率能直接跑不会出现libc版本差异问题。第二种是使用RK3588 SDK包里自带的工具链。官方SDK一般会把工具链放在sdk/tools/linux/目录下这类工具链的优点是和板卡BSP的内核头文件、驱动库配合得更好适合需要编内核模块、编译Mali GPU用户态库的场景。缺点是路径和版本更新频繁环境变量要仔细配对新手不太友好。第三种是Buildroot或Yocto生成的工具链。它和你裁剪的rootfs完全匹配最干净但初始化时间很长如果不是要给量产设备做系统镜像没必要一上来就用它。我的建议个人调试、项目验证直接用apt工具链把精力集中在Qt库和应用代码上等真正要量产了再评估是否切换到SDK工具链。2.3 Sysroot到底是什么怎么准备很多教程没有讲清楚sysroot导致读者卡在“为什么编译时说找不到stdio.h”这类问题上。交叉编译时编译器需要一个目标系统根目录里面要有usr/include、usr/lib/aarch64-linux-gnu这些目录交叉编译器从里面找头文件和库。这个根目录就是sysroot。用apt工具链时它默认自带的sysroot是/usr/aarch64-linux-gnu包含基础C/C库。但Qt依赖的第三方库比如libz、libpng、libjpeg、libts就不一定齐全。一种更省事的做法是把开发板系统里的/usr/include和/usr/lib目录的内容同步到主机某个目录再用--sysroot参数去指定。不过这样容易引入版本漂移实际中我建议先采用“缺什么编什么编完统一放进/opt/arm-libs”的方式不强行做完整sysroot镜像。3. 从编译Qt库说起configure参数背后的门道3.1 下载源码并确认依赖我在搭建时实际用的是5.15.2。下载解压之后先别急着configure先确认主机上有没有基础工具sudo apt install gcc g make perl python3 ninja-build \ libglib2.0-dev libfontconfig1-dev libfreetype6-dev \ libts-dev libxkbcommon-dev这里要说明上面一部分包是为了给Qt的交叉编译过程提供辅助工具比如perl是Qt构建脚本需要的。而libts-dev是触摸屏的库如果你要用电阻触摸屏就得先交叉编译tslib再把头文件放到交叉编译器的搜索路径里。不过Qt源码里也带了tslib的检测逻辑直接让它去链接开发板sysroot里的libts即可。3.2 configure参数配置这是最关键的一步直接影响后边能不能在板子上跑起来。我的完整命令如下mkdir build-qt5-aarch64 cd build-qt5-aarch64 ../qt-everywhere-src-5.15.2/configure \ -prefix /opt/qt5.15.2-aarch64 \ -xplatform linux-aarch64-gnu-g \ -release \ -opensource -confirm-license \ -no-opengl \ -no-xcb \ -no-cups \ -no-icu \ -linuxfb \ -no-eglfs \ -nomake examples -nomake tests \ -skip qtwebengine逐个解释一下这些参数-prefix指定Qt库安装路径。我这里装在/opt/qt5.15.2-aarch64后续在板子上也放到同样路径可以少改很多环境变量。-xplatform linux-aarch64-gnu-g告诉Qt构建系统我们要用目标平台是aarch64的交叉编译器它对应的mkspec是linux-aarch64-gnu-g。Qt源码的qtbase/mkspecs目录下会自带这个文件它默认调用aarch64-linux-gnu-g编译器。如果你用的是SDK工具链可能需要复制一个mkspec改一下编译器路径。-no-opengl和-no-eglfs因为我这个项目不依赖GPU加速直接用Linux Framebuffer显示所以不开OpenGL相关模块。如果你的界面需要复杂动画或摄像头叠加可以在板子的Mali库已经准备好的情况下加上-opengl es2 -eglfs但第一次搭建不建议这么干会引入一堆库依赖。-no-xcb关掉X11下的Qt平台插件。这样可以在后面把调试范围缩小到LinuxFB不至于被xcb相关依赖绊倒。-linuxfb启用Linux Framebuffer平台插件这是让Qt直接写/dev/fb0的显示后端适合没有桌面环境的嵌入设备。3.3 编译安装配置过程中如果提示缺某个模块按提示补装主机依赖即可。等configure通过后执行make -j$(nproc) make install编译时间取决于机器性能通常半小时到两小时不等。安装完成后重点检查/opt/qt5.15.2-aarch64/lib/下有没有libQt5Core.so.5、libQt5Widgets.so.5以及/opt/qt5.15.2-aarch64/plugins/platforms/下有没有libqlinuxfb.so。只有当这些文件存在后续动态库依赖才是完整的。4. 让项目代码跑起来交叉编译一个带文件对话框的应用4.1 最小可复现的项目结构标题里提到了[项目代码]这部分我直接给一套可复用的最小工程。项目结构如下qt_rk3588_demo/ ├── qt_rk3588_demo.pro ├── main.cpp └── mainwindow.hmain.cpp里我写了一个很简单的主窗口放一个按钮点击之后弹出文件选择对话框#include QApplication #include QPushButton #include QFileDialog #include QMessageBox #include QDebug int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button(选择文件); QObject::connect(button, QPushButton::clicked, [app]() { QString file QFileDialog::getOpenFileName(nullptr, 选择文件, /home, All Files (*)); if (!file.isEmpty()) { qDebug() select file: file; QMessageBox::information(nullptr, 结果, file); } }); button.resize(400, 200); button.show(); return app.exec(); }qt_rk3588_demo.pro内容如下QT core gui widgets TARGET qt_rk3588_demo TEMPLATE app CONFIG release SOURCES main.cpp这里有个小坑很多交叉编译教程会让你在pro里加QMAKE_LRELEASE、QMAKE_CC这种变量其实不需要。Qt源码编译出的qmake已经记录了交叉编译器路径直接用交叉qmake解析pro文件就行能够避免很多手工配置错误。4.2 使用交叉qmake编译编译之前需要把刚编译产物的bin目录放到PATH里export PATH/opt/qt5.15.2-aarch64/bin:$PATH qmake qt_rk3588_demo.pro make -j$(nproc)编译完成后执行file qt_rk3588_demo输出应该类似qt_rk3588_demo: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked看到ARM aarch64说明交叉编译成功。4.3 整理运行时依赖做成一个部署包直接把这个可执行文件拷到开发板是跑不起来的因为板子上没有Qt库也没有Qt插件。正确的做法是建一个部署目录把可执行文件、Qt库、插件、字体一起放进去。可以用下面的脚本收集依赖#!/bin/bash APPqt_rk3588_demo QTDIR/opt/qt5.15.2-aarch64 DEPLOY/home/yourname/rk3588_deploy mkdir -p $DEPLOY mkdir -p $DEPLOY/plugins/platforms mkdir -p $DEPLOY/lib cp $APP $DEPLOY/ cp -d $QTDIR/lib/libQt5Core.so.5* $DEPLOY/lib/ cp -d $QTDIR/lib/libQt5Widgets.so.5* $DEPLOY/lib/ cp -d $QTDIR/lib/libQt5Gui.so.5* $DEPLOY/lib/ cp -d $QTDIR/plugins/platforms/libqlinuxfb.so $DEPLOY/plugins/platforms/ # 用交叉ldd检查系统库依赖 aarch64-linux-gnu-ldd $APP执行aarch64-linux-gnu-ldd $APP之后会列出这个程序运行需要的动态库。除了Qt自己的库通常还会显示/lib/aarch64-linux-gnu/libstdc.so.6、libc.so.6、libm.so.6等系统库这些不用打进部署包板子的rootfs自带。但如果你编Qt库时依赖了某些第三方库比如libts、libpng就必须把对应的so也拷进部署包的lib目录。4.4 上板运行把rk3588_deploy整个目录拷贝到开发板的/opt下然后执行export LD_LIBRARY_PATH/opt/rk3588_deploy/lib:$LD_LIBRARY_PATH export QT_QPA_PLATFORMlinuxfb export QT_QPA_PLATFORM_PLUGIN_PATH/opt/rk3588_deploy/plugins/platforms /opt/rk3588_deploy/qt_rk3588_demo如果显示正常你会看到屏幕上出现一个按钮点击后能弹出文件选择对话框。整个过程基本验证了Qt交叉编译环境的可行性。5. 上板实测记录xcb找不到、字体发虚、触摸没反应怎么处理5.1 报错cxcbconnection: could not connect to display如果你在板子上直接执行时忘了设置QT_QPA_PLATFORMQt默认会尝试加载xcb插件而你的系统如果根本没有启动X Server或没有xcb插件就会报出这样一段错误。处理方法是先确认环境变量export QT_QPA_PLATFORMlinuxfb如果程序是带有-platform参数自己指定的也可以用./qt_rk3588_demo -platform linuxfb。开发板上没有桌面环境时使用LinuxFB是最稳妥的选择。5.2 ldd显示libqxcb.so缺失大量xcb相关依赖有些时候你为了界面效果还是想保留X11后端。编译Qt时如果不加-no-xcbQt会生成libqxcb.so但这一个插件依赖十几个图形相关的库完整性很难保证。如果你非要走xcb路线就得把这些库全部交叉编译出来并让Qt在板子上能找到它们。实际经历告诉我除非你的RK3588板子刷的是带桌面的Ubuntu镜像并且要跑在Xorg/Qt XCB后端下否则别折腾xcb。对大多数嵌入场景linuxfb已经够用如果之后需要GPU加速再转到eglfs也不迟。5.3 界面文字都是方块嵌入板系统的字库经常是空的Qt默认找不到字体就会用方框代替。解决方式很简单从Ubuntu主机拷贝一个字体到板子然后设置Qt字体路径mkdir -p /usr/share/fonts/truetype # 把主机上的 WenQuanYi Micro Hei 或 DejaVuSans.ttf 复制过去 export QT_QPA_FONTDIR/usr/share/fonts/truetype注意字体文件不能只看后缀名要确认是中文字体否则中文界面依然会花屏。我一般先下载wqy-microhei.ttc拷贝到板子效果比较稳。5.4 触摸屏没有反应如果板子带电容触摸屏很可能事件节点是/dev/input/event0或/dev/input/event1。先通过hexdump /dev/input/eventX检验触摸是否上报确认节点后再做两步。第一步是在编译Qt前准备tslib库并把头文件放进交叉编译器的sysroot第二步是在板子上设置export QT_QPA_FB_TSLIB1 export TSLIB_TSDEVICE/dev/input/event1 export TSLIB_CALIBFILE/etc/pointercal如果没有tslib只有单点触摸也可以考虑使用libinput插件但这需要Qt编译时开启-libinput并且板子系统里要运行libinput服务。这套链路相对复杂我建议先保证tslib通路再谈多点触摸和手势。6. 把环境固化下来后续新增依赖库的交叉编译套路6.1 典型第三方库zlog的交叉编译Qt项目很少单独裸跑通常会需要日志库、网络库或数据库。这里以zlog为例演示如何交叉编译一个纯C库再被Qt调用。zlog源码很小解压后执行./configure --hostaarch64-linux-gnu --prefix/opt/arm-libs make -j$(nproc) make install--host指定目标平台--prefix指定安装目录。安装完成后在Qt的pro文件里追加INCLUDEPATH /opt/arm-libs/include LIBS -L/opt/arm-libs/lib -lzlogqmake执行前记得把交叉编译器路径加到PATH里。然后重新编译就能通过。这个套路几乎适用于所有autotools体系的库比如curl、openssl、libpng、libjpeg。6.2 交叉编译时如何避免“编译成x86”我见过很多人写./configure时不加--host然后在链接时报“architecture of input file is not compatible”。原因就是configure默认把当前主机当成目标平台生成了x86的Makefile。交叉编译的第一步永远是--hostaarch64-linux-gnu。另外如果依赖了pkg-config解析的库还需要设置export PKG_CONFIG_PATH/opt/arm-libs/lib/pkgconfig export PKG_CONFIG_LIBDIR/opt/arm-libs/lib/pkgconfig export PKG_CONFIG_SYSROOT_DIR/opt/arm-libs不改这三项的话pkg-config很可能会把主机上的x86库路径报给编译器后面就是一团乱麻。6.3 如何让工具链长期可用每次打开新终端都要写一遍PATH不是一个好习惯。建议把环境配置写进~/.bashrc或项目级的env.sh#!/bin/bash export QT_ROOT/opt/qt5.15.2-aarch64 export PATH$QT_ROOT/bin:$PATH export LD_LIBRARY_PATH$QT_ROOT/lib:$LD_LIBRARY_PATH export QT_QPA_PLATFORMlinuxfb以后每次编译前source env.sh环境就固定了。项目里新增第三方库时统一装到/opt/arm-libs在pro文件里统一指定一次INCLUDEPATH和LIBS这样每条编译链路都可复用、可交接到其他同事手里。在我后续的RK3588项目里遇到Qt程序崩溃、插件缺失、显示层错乱等问题几乎都能回到这套流程里排查先确认是不是交叉编译工具链版本不对再确认Qt库和插件版本一致最后检查板子上的系统库和字体路径。只要环境本身是可控的剩下的问题基本就只剩业务逻辑了。如果你刚开始搭建议拿最小demo把这个流程完整跑通一次比看十篇教程都有用。本文还有配套的精品资源点击获取
返回列表