恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
RK3568嵌入式Linux Qt交叉编译环境搭建与远程调试实战
首页
资讯中心
/
RK3568嵌入式Linux Qt交叉编译环境搭建与远程调试实战
RK3568嵌入式Linux Qt交叉编译环境搭建与远程调试实战
发布时间:2026/10/5 15:01:15
刚接触嵌入式Linux开发的同学十有八九会在“交叉编译”这道坎上卡上一阵子。我自己当年第一次给瑞芯微RK3568开发板搭Qt开发环境时就是因为在Ubuntu上直接编译了一个Qt程序scp到板子上之后跑不起来报了一堆乱七八糟的错误折腾了两天才把环境彻底捋顺。现在回头看核心问题其实只有一个没有把宿主机PC上的Ubuntu和开发板之间的编译架构、运行库和工具链理顺。这篇文章就以RK3568开发板为例完整走一遍在Ubuntu环境下搭建Qt交叉编译环境、配置Qt Creator、远程调试的流程适合手里有一块RK3568开发板、想在板子上跑Qt界面程序却不知道怎么把开发环境搭起来的同学。1. 为什么必须交叉编译一个崩溃程序的“破案”过程1.1 RK3568是ARM架构Ubuntu是x86架构两者的“语言”不通RK3568是瑞芯微推出的一款四核Cortex-A55处理器是典型的ARM架构SoC。而我们的开发主机无论是笔记本还是台式机基本上都是x86_64架构。这里说的“架构”可以理解成机器各自使用的指令集x86_64的机器能直接执行x86_64的二进制指令ARM的机器则只能执行ARM指令。两个架构之间CPU不认识对方的“母语”。所以当你把Ubuntu上编译出来的程序直接拷贝到RK3568开发板上系统根本无法把它加载进来。最常见的执行结果只有两种终端提示cannot execute binary file: Exec format error或者所有依赖库都找不到、报No such file or directory。前者说明CPU架构对不上后者常见的坑是我下面会专门展开的——程序是ARM二进制不假但动态链接器路径不对本质上是交叉编译时链接配置出错。1.2 交叉编译的核心在一台机器上编译出另一台机器能跑的程序交叉编译cross compile的意思很简单编译行为发生在宿主机x86_64的Ubuntu上但编译产物的目标平台是开发板aarch64架构。整个链条里最核心的工具是交叉编译器Ubuntu仓库里直接有对应的包gcc-aarch64-linux-gnu和g-aarch64-linux-gnu。装上之后用aarch64-linux-gnu-gcc代替平时的gcc编译出来的就是ARM机器能识别的二进制。但仅仅有编译器还不够。一个Qt程序会依赖Qt运行库、C/C标准库、动态链接器等一大堆支撑文件。这些“支撑文件”也必须是aarch64架构的版本。缺了它们就算编译器生成了正确的ARM指令程序在板子上依然起不来。这就是为什么交叉编译一个Qt项目通常要先在Ubuntu上交叉编译出一整套aarch64的Qt库再让Qt Creator指向这套库来写代码、编译程序。1.3 为什么不直接在开发板上编译有同学会问RK3568好歹是四核A55为什么不能在板子上直接装GCC编译Qt程序呢答案很简单太慢且不适合日常开发。板子的性能定位是嵌入式、工控、边缘计算而不是作为一台编译服务器。我有一次尝试在RK3568板子上直接编译一个中等规模的Qt Widgets项目光是编译链接就花了近十分钟而同样的工程在PC上交叉编译只需要十几秒。再加上Qt库本身源码量巨大在板子上编译整个Qt几乎是不可接受的。开发阶段频繁改代码、频繁编译还是把Ubuntu当作编译主机来得舒服板子仅作为程序运行和调试的目标设备。2. 动手前先摸底Ubuntu环境、工具链和板子信息一个都不能少2.1 宿主机Ubuntu版本与基础依赖我目前使用的宿主机系统是Ubuntu 20.04 LTS和22.04 LTS两个版本都算稳定。如果你是其他较新的LTS版本也完全可以但务必保证软件源能正常更新。首先执行基础的依赖安装sudo apt update sudo apt install build-essential git wget bzip2 flex bison \ libx11-dev libxext-dev libxcb1-dev libfontconfig1-dev libfreetype6-dev \ libxkbcommon-dev libgl1-mesa-dev这些依赖中有一部分是交叉编译Qt时configure阶段用来检测宿主环境的有一部分是编译宿主机辅助工具如qmake、moc、uic等时需要的。很多教程只让你装build-essential最后configure时会报“No XCB”之类的错就是因为缺少这些X11相关头文件。这里一次装齐可以省掉后面的连锁麻烦。2.2 安装aarch64交叉编译工具链Ubuntu仓库自带了aarch64交叉编译工具链安装非常方便sudo apt install gcc-aarch64-linux-gnu g-aarch64-linux-gnu安装完成后验证一下aarch64-linux-gnu-gcc --version如果终端能正常输出版本信息说明工具链已经可用。这里补充一个选型建议如果你的开发板是跟着厂商SDK来的比如瑞芯微官方SDK、正点原子或迅为的BSP包里通常带了一份预编译的交叉编译器位置一般在SDK目录的prebuilt/gcc/linux-x86/aarch64/下面。这种情况下我建议优先使用厂商自带的工具链而不是系统包的工具链因为板子上的内核模块、二进制库很可能是用这份工具链编译的大家用的GCC版本和C库版本一致ABI兼容性更好。我的演示沿用apt安装的aarch64-linux-gnu-系列命令原理完全一样。2.3 摸清开发板底细架构、系统与已有Qt拿到一台开发板不要急着写代码。先通过串口或SSH登进去执行下面几条命令把板子的“基因”摸清楚uname -a cat /etc/os-release ldd --version我手上这台RK3568跑的是Debian系统uname -a输出里有明确的aarch64字样/etc/os-release能看出是哪个发行版ldd --version则用于确认板子上的glibc版本。为什么要确认这些因为后面我们在Ubuntu上交叉编译的程序最终要动态链接到板子上的C库。如果Ubuntu交叉工具链对应的glibc版本比板子上的高程序拷过去很可能报“version GLIBC_2.34 not found”。这是一个非常经典的坑我在第6章会专门说排查方法。接着看板子上是否已经带Qt运行库ls /usr/lib/aarch64-linux-gnu/ | grep libQt5很多官方发布的根文件系统里其实只预装Qt运行库为了跑预置程序并不带头文件和开发用的.so链接文件。这意味着即便板子上能跑Qt程序想在Ubuntu上写代码链接到这套库也做不到。这也是我们为什么必须自己交叉编译一份完整Qt库的根本原因。如果你在板子上看到了libQt5Core.so等文件记下它的版本号尽量选择源码里对应的Qt版本交叉编译保持两边一致。3. 编译Qt库给RK3568准备一整套“合身”的Qt3.1 获取Qt源码与版本选择交叉编译Qt最主流的路线是下载Qt Open Source源码包在Ubuntu上用交叉编译工具链构建出一套aarch64的Qt SDK。版本选择上嵌入式领域用Qt 5的仍然非常多因为对老模块支持好、配置成熟、资料也多。我以Qt 5.15.2为例它在RK3568这类ARMv8平台上非常稳也是我做项目的主力版本。Qt 6虽然在桌面端很红火但在嵌入式板卡上的生态支持还处于过渡期如果不追求新特性稳定优先选5.15.2即可。源码下载wget https://download.qt.io/archive/qt/5.15/5.15.2/single/qt-everywhere-opensource-src-5.15.2.tar.xz tar xf qt-everywhere-opensource-src-5.15.2.tar.xz cd qt-everywhere-opensource-src-5.15.23.2 configure参数核心是 -xplatform、-prefix 和模块裁剪Qt的交叉编译核心在于configure阶段。我的经历是这个阶段90%的错误都出在参数没给对。下面给出一个我在实际项目中验证过的配置./configure -prefix /opt/rk3568/qt5.15.2 \ -opensource -confirm-license -release \ -xplatform linux-aarch64-gnu-g \ -no-opengl -no-glib \ -skip qtwebengine -skip qtwebview -skip qtwayland -skip qt3d \ -skip qtconnectivity -skip qtlocation -skip qtscript \ -no-feature-cups -no-iconv \ -make libs -nomake examples -nomake tests几个关键参数我解释一下-prefix /opt/rk3568/qt5.15.2交叉编译产物的安装目录。这个目录决定后面Qt Creator要选的qmake路径也决定你要把哪些文件同步到开发板上。-xplatform linux-aarch64-gnu-g告诉configure目标是aarch64架构。Qt 5.15的源码里自带linux-aarch64-gnu-g这个mkspec如果你的Qt版本较老找不到可以拷贝linux-arm-gnueabi-g改成对应的aarch64版本。-no-openglRK3568本身有GPU但OpenGL在纯Buildroot/Debian环境下配置起来比较复杂如果没有具体显示需求先用软件渲染的linuxfb方式跑Qt界面最省事。后续需要GPU加速再重新编译带EGL支持的Qt版本也不迟。-skip qtwebengineQt WebEngine编译极慢、体积巨大、依赖又多嵌入式场景除非做浏览器否则一定要跳过。类似的webview、wayland、3d模块也一并剪掉。-no-iconv、-no-feature-cups是为了避免configure阶段探测到宿主机/板子的iconv和CUPS环境不同而报错。实际项目中基本用不到这两个功能关掉最稳妥。3.3 make与make install等待、验证与常见报错configure跑完后会生成Makefile接着编译make -j$(nproc) sudo make install首次编译Qt库耗时较长我测试过在8核CPU的机器上大约需要20到40分钟取决于机器性能。如果中途出现编译错误不要盲目重来先看错误日志。最常见的有两类一类是configure阶段没报错、make阶段报错基本是缺少宿主工具或依赖头文件回头补装对应依赖后需要重新configure另一类是工具链版本过老比如Qt 6要求GCC 10以上但系统包默认给的gcc-aarch64-linux-gnu版本是7或8这时候就需要升级工具链或者改用厂商或Linaro的较新版本。编译完成后验证file /opt/rk3568/qt5.15.2/lib/libQt5Core.so输出里应该包含ELF 64-bit LSB shared object, ARM aarch64字样说明这套Qt库确实是aarch64架构的可以放心提供给后续Qt Creator使用。4. Qt Creator中的Kit配置把编译器、Qt和设备串成一个完整链条4.1 Qt Creator版本选择与基本准备Qt Creator本身是一个IDE需要从Qt官网单独下载安装或者通过Qt在线安装器安装。它最大的价值在于把编译器、Qt库、设备、调试器这些松散组件关联成一套可用的工具链。很多人只会在Qt Creator里新建工程、点运行却从没理解过底层的Kit逻辑导致交叉编译时各种“跑不起来”。安装完成后先别急着建项目我们把环境一项项配好。打开Qt Creator选择菜单栏的“工具”-“选项”进入后能看到设备、编译器、Qt版本、Debuggers等配置页。4.2 添加编译器与Qt版本这一步的作用是告诉Qt Creator我们有一套专门面向aarch64的GCC编译器还有一套交叉编译出来的Qt库。在“Kits”-“编译器”页面点“添加”-“GCC”-“C”编译器路径选择/usr/bin/aarch64-linux-gnu-gcc同样再添加一个“C”编译器/usr/bin/aarch64-linux-gnu-g添加完后Qt Creator会自动识别出它们是aarch64架构。如果识别不准确可以手动在编译器页面把ABI设置为aarch64-linux-generic-elf-64之类的ARM64选项。接着在“Kits”-“Qt版本”页面点“添加”路径选择/opt/rk3568/qt5.15.2/bin/qmake看到版本信息显示为Qt 5.15.2说明这套Qt库已被Qt Creator识别。4.3 添加设备让Qt Creator认识你的RK3568设备配置是为了后续的远程部署、远程运行和远程调试。在“设备”页面点“添加”-“泛型Linux设备Generic Linux Device”填写开发板的IP地址、用户名和密码。我的板子系统账号是root就填root和对应的密码或密钥。填完后点“测试”确保Qt Creator能通过SSH连上板子并执行基本命令。如果测试失败先确认板子SSH服务是否开启以及Ubuntu和板子之间的网络是否互通。4.4 新建Kit并验证编译产物架构在“Kits”页点“添加”给这个套件起一个清晰的名字比如“RK3568-qt5.15.2”。然后分别做以下关联配置项选择内容编译器Caarch64-linux-gnu-gcc编译器Caarch64-linux-gnu-g调试器aarch64-linux-gnu-gdb没有就先用系统gdb-multiarchQt版本Qt 5.15.2/opt/rk3568/qt5.15.2CMake工具宿主机的cmake如果你用CMake构建设备RK3568开发板Sysroot可先留空后续有需要再指定板子的根文件系统这里我要单独说一下Sysroot。它本质上是一个“.sdk目录”把开发板的根文件系统拷贝一份到Ubuntu上里面包含了板子上的/usr、/lib目录。设置Sysroot后交叉编译时编译器会优先从这个目录里找头文件和库从而保证编译链接使用的版本与板子实际运行环境完全一致。对于精度要求很高的项目Sysroot是必需品如果图省事很多情况下不设也能跑但遇到链接到板子独有库的项目就可能出现“找不到头文件”的诡异问题。选好Kit后新建或打开一个最简单的Qt Widgets项目构建套件选择“RK3568-qt5.15.2”然后点击“构建”。编译完成后找到生成的二进制文件一般在build目录下用file命令验证file ./build-TestApp-.../TestApp如果输出是ELF 64-bit LSB executable, ARM aarch64说明你的Qt Creator交叉编译搭建已经成功。这一步是最重要的分水岭能生成aarch64可执行文件说明编译链路通了后面要做的只是部署和调试。5. 部署到RK3568并远程调试程序和开发板正式“接上头”5.1 配置部署步骤把可执行文件送到板子上程序编译出来并不等于能在板子上跑还需要把可执行文件和它依赖的Qt库一起部署到开发板。部署最直接的方式是手动scp但对于频繁开发调试的场景手动操作太低效。Qt Creator提供了一键部署功能非常值得配置。打开项目窗口左侧的“项目”标签页在你的Kit配置里找到“部署”步骤点“添加部署步骤”。Qt Creator支持通过“SFTP上传文件”这个方式把本地的可执行文件上传到开发板的指定目录比如/opt/app/。配置好之后每次点绿色三角运行按钮Qt Creator会先自动编译再通过SSH把可执行文件复制到板子上最后在板子上启动程序。部署时要注意Qt程序是动态链接的二进制本身只有几百KB甚至几MB但运行依赖的libQt5Core.so、libQt5Widgets.so、libQt5Gui.so等一堆动态库加起来可能有大几十MB。编译好的Qt库在Ubuntu的/opt/rk3568/qt5.15.2/lib目录下你需要把整个lib目录拷贝到板子上scp -r /opt/rk3568/qt5.15.2 root板子IP:/opt/然后在板子上设置环境变量export LD_LIBRARY_PATH/opt/qt5.15.2/lib:$LD_LIBRARY_PATH export QT_QPA_PLATFORM_PLUGIN_PATH/opt/qt5.15.2/pluginsLD_LIBRARY_PATH让动态链接器优先从新目录寻找Qt库QT_QPA_PLATFORM_PLUGIN_PATH告诉Qt去哪里找平台插件。这两行不设后面十有八九会碰到Could not load the Qt platform plugin xcb或者libQt5Core.so.5找不到的问题。5.2 远程运行与远程调试Qt Creator如何接管板子上的进程远程运行配置在“项目”-“运行”页面。构建配置里选择“作为远程运行”远程可执行文件路径写板子上的部署目录比如/opt/app/TestApp工作目录也一并设置。参数部分根据程序需要如果要用linuxfb平台显示就加-platform linuxfb。远程调试是这篇文章的重头戏也是很多人觉得玄乎的地方。简单说远程调试的原理是板子上运行一个gdbserver程序宿主机上的GDB通过网络与它通信控制板子上的被调试程序。Qt Creator通过SSH在板子上自动启动gdbserver再把宿主机上交叉编译出的调试信息与板子上的程序符号对应起来于是你就能像调试本地程序一样在Ubuntu的Qt Creator界面里看到板子上程序的断点、变量、调用栈。要使远程调试跑通三个东西必须齐活板子上有gdbserver。通过板子自带的包管理器安装即可Debian/Ubuntu系apt install gdbserver如果板子系统是裁剪过的Buildroot可能需要自己在Buildroot里开启gdbserver并重新烧录根文件系统。宿主机有一个支持aarch64的GDB。优先安装gdb-multiarchsudo apt install gdb-multiarch然后在Qt Creator的“Kits”-“调试器”里为“RK3568-qt5.15.2”这个套件手动指定调试器路径为/usr/bin/gdb-multiarch。被调试的程序保留调试符号不要用strip处理。平时编译release版本时Qt Creator可能会自动strip要在项目构建步骤里把“Strip二进制文件”选项关掉或者干脆用debug模式编译远程调试版。都准备好后直接在Qt Creator里点调试按钮F5它会自动完成部署到板子、启动gdbserver、建立连接这一连串动作。第一次跑通远程调试时你会在Qt Creator的Debugger Console里看到类似Remote debugging from host 192.168.1.100的日志这就说明板子上的gdbserver已经挂上了。5.3 让程序在板子上正常显示Qt平台插件选型Qt程序在嵌入式设备上显示与桌面Linux环境下“直接弹窗”不一样它依赖QPAQt Platform Abstraction平台插件。最常用的三种平台插件适用场景说明linuxfb无窗口系统、有framebuffer最简单裸机或Buildroot环境首选eglfs有GPU/EGL环境需要Mali等GPU驱动支持性能好xcb板子系统带X11显示服务如果板子跑的是完整桌面版Debian/Ubuntu才使用我交叉编译Qt时用了-no-opengl因此可用的平台插件主要是linuxfb。在板子上执行export QT_QPA_PLATFORMlinuxfb ./TestApp如果程序启动后没有任何错误输出而屏幕上出现了Qt界面说明显示链路已经通。这里有一个常见误区很多人在xcb平台上卡了很久实际上板子根本没有X11服务怎么等都等不出窗口。搞清楚自己板子的显示架构再选择对应的平台插件可以少走很多弯路。6. 这些坑我踩过编译、链接与运行阶段的典型问题排查6.1 “cannot execute binary file”其实是架构不匹配这是最基础的报错。看到cannot execute binary file第一反应是检查二进制架构file ./TestApp如果输出显示的是x86-64说明你编译时选错了KitQt Creator里构建套件没有切到“RK3568-qt5.15.2”而是用了默认的桌面Qt。这种情况不用动代码重新选择构建套件编译即可。如果输出已经是ARM aarch64但依旧无法执行那就不是架构问题而是动态链接器或库路径的问题。6.2 动态链接库失踪案ldd与readelf的用法程序能加载但报No such file or directory或者运行时报找不到libQt5Core.so.5这属于动态链接问题。在开发板上用下面的命令查看程序依赖了哪些动态库ldd ./TestApp如果发现libQt5Core.so显示not found说明LD_LIBRARY_PATH没设置对或者依赖的Qt库版本与程序编译时不一致。另一种情况是二进制里的动态链接器路径不对用readelf确认readelf -l ./TestApp | grep interp正常情况下应该显示/lib/ld-linux-aarch64.so.1。如果你的交叉编译工具链C库路径与板子不一致这里可能指向一个不存在的位置结果就是“No such file or directory”。遇到这种问题可以在开发板上建立对应的软链接或者重新用与板子glibc版本匹配的工具链编译。6.3 gdb远程调试时的两个高频问题远程调试最让人抓狂的报错是Remote g packet reply is too long。这个错误几乎都是宿主机GDB与板子gdbserver版本不匹配造成的比如板子上的gdbserver是GDB 10宿主机上的gdb是GDB 8。解决办法很直观升级宿主机上的gdb-multiarch到最新版确保两边的GDB协议版本兼容。另一个常见问题是断点打不上。程序明明跑起来了但Qt Creator里怎么点断点都无效原因多半是二进制被strip过调试符号丢失。只需关闭strip选项或者用debug模式重新编译即可。还有一个容易忽略的点如果程序已经部署到板子上而宿主机GDB加载的符号文件路径与实际部署路径不一致也可能导致源码无法关联。Qt Creator里可以通过“调试”-“调试模式”-“源码文件映射”手动纠正宿主源码路径与板子源码路径的对应关系。6.4 一点实用的调试习惯最后分享一个我自己的习惯远程调试之前永远先在板子上手动跑一遍程序。gdbserver :2345 ./TestAppgdbserver启动成功后宿主机上再用命令行GDB连上gdb-multiarch ./TestApp (gdb) target remote 板子IP:2345 (gdb) continue先在命令行方式下跑通一次远程调试再回到Qt Creator图形界面操作能避免很多环境类的低级问题。因为当程序无法启动、插件加载失败、环境变量缺失这些基础问题没有解决时图形化调试只会让错误变得更难定位。先命令行跑通再图形化调试这是我整个RK3568开发过程中觉得最省时间的做事顺序。RK3568的Qt交叉编译环境搭建说穿了就是“架构匹配”“工具链一致”“路径正确”这三件事。把每一步验证到位剩下的就是正常的Qt开发流程了。等你把第一个Qt程序成功部署到板子上、在屏幕上看到自己的界面时那种感觉值得前面所有折腾。