ARTICLE DETAIL

资讯详情

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

Qt 5.14.2 aarch64静态交叉编译指南:从工具链到sysroot完整实践

Qt 5.14.2 aarch64静态交叉编译指南:从工具链到sysroot完整实践 做嵌入式Linux开发的朋友大概率都有过这样的经历拿到一块aarch64架构的开发板系统盘空间紧张跑个Qt程序却要在目标板上手动拷贝一堆so库版本稍微对不上程序起来就白白闪退。我最早用动态库方式部署Qt应用时就被这种麻烦折腾得够呛后来干脆下决心把Qt 5.14.2在x86宿主机上做一次完整的aarch64静态交叉编译编出一个自带全部依赖、拷过去就能跑的可执行文件。这篇文章就把我从零开始搭建Qt 5.14.2 aarch64静态交叉编译环境的全过程记录下来包括工具链选择、sysroot准备、configure参数逐一拆解、常见报错和排查思路给准备入坑或正在踩坑的同行一份可以直接照抄的完整手册。文章内容适合已经写过Linux C/C、了解qmake基本用法、但对嵌入式交叉编译还不太熟的开发者。如果你从来没接触过交叉编译读起来也没问题我会把每一步背后的原理和为什么要这么做讲清楚而不是只丢给你一串命令。1. 为什么选 Qt 5.14.2 加静态交叉编译1.1 版本选择的现实考量很多教程都推荐直接用最新版Qt但在嵌入式项目里我个人的体会是Qt 5.14.2的生态资料在这个时间点最完整。很多开发板的BSP文档、芯片厂商的SDK、网上能搜到的交叉编译案例大多集中在5.14.x这个系列遇到问题基本都能找到对应解决方案。尤其是一些老的传感器、摄像头、图像处理依赖库它们的官方库文件往往是在Qt 5.14时代编译的换个太新的Qt版本链接阶段反而容易出兼容性坑。从Qt本身的角度看5.14.2属于Qt 5系列中比较稳定的一个版本在模块划分上也比较规整。做静态编译时我们需要裁剪掉不需要的模块老版本Qt模块之间的依赖关系看configure脚本的输出就能理解得很清楚代码层面没有太多花里胡哨的东西出错也好追。如果你用的是5.15或者6.x静态编译的大逻辑是一样的但部分configure参数名和模块名会有差异本文的命令就不能直接等价搬过去了。我建议先明确一个事实Qt官方并没有提供Linux aarch64静态库的现成通用包。你从Qt Installer里装的都是针对当前宿主机架构的预编译包而且是动态库版本。想得到aarch64静态库只能从源码自己编译这就是这篇手册存在的根本原因。1.2 静态编译与动态部署的取舍静态编译的核心思路是把Qt的核心模块库libQt5Core.a、libQt5Gui.a等直接编进你的可执行文件里运行时不再依赖目标板上的Qt动态库。带来的好处太明显了部署时只需要拷一个文件到板子不用再同步一堆so文件也没有库搜索路径的烦恼。目标板上即使什么都没有安装程序也能自己跑起来调试环境极其干净。实测下来静态编出来的程序在系统资源紧张的嵌入式环境下启动速度通常会比动态版更快少了解析和加载so的过程。代价也不是没有。最直观的就是二进制体积变大。我这边一个最简单的QWidget空窗口程序动态编译出来1MB左右静态编译到了9MB多如果引入Widgets和对网络模块再膨胀一些十几MB很正常。另一个问题是如果Qt部分功能用了LGPL协议的库静态链接时需要留意开源许可证的合规要求发布时该提供的源码要约要提供给对方。从部署便捷性来说静态编译在中小型嵌入式设备、工业控制面板、车载终端这类场景下绝对是比动态库分发更省心的方案。如果你目标板上本来就装好了完全一致的Qt运行库那用动态库更省磁盘但大多数情况下静态编译的“一键部署”优势会让你少掉很多头发。1.3 交叉编译的基本模型交叉编译的机制性和生活化类比其实很简单想象你是一个中国主厨但你要做的是意大利菜厨房里的刀具是中式菜刀食材却是意面、罗勒叶。你用的厨具编译器和构建工具运行在x86宿主机上但它操作的对象却全是aarch64平台的东西。具体到Qt编译涉及三个角色宿主机host你进行编译工作的x86_64 Linux机器负责执行编译程序。目标机target最终运行程序的aarch64设备。工具链toolchain一套运行在宿主机上、但生成目标机机器码的编译器与二进制工具例如aarch64-linux-gnu-gcc。当你执行./configure时这个脚本本身跑在x86宿主机上它会检查宿主机上的工具链能力并且通过-xplatform参数告诉qmake我最终生成的目标平台是aarch64。随后make过程就会调用aarch64交叉编译器将Qt源码编译成aarch64架构的静态库。关键点在于所有编译产物都是aarch64的但这些编译过程全部发生在宿主机上。如果不理解这个模型后续看到宿主机和解压出的aarch64 sysroot目录结构时就会一头雾水。2. 环境准备宿主机、工具链与 sysroot2.1 宿主机环境与基础依赖我使用的宿主机是Ubuntu 20.04.6 LTS x86_64内核比较普通。Qt 5.14.2的configure需要系统里装有一些基础工具否则执行到一半就会因为缺perl或者python而报错。以下是我在干净系统上执行的依赖安装命令sudo apt update sudo apt install build-essential perl python3 git \ libglib2.0-dev libfontconfig1-dev libfreetype6-dev \ libx11-dev libxkbcommon-dev libxcb1-dev \ libxcb-glx0-dev libxcb-xinerama0-dev libxcb-cursor-dev \ gcc-aarch64-linux-gnu g-aarch64-linux-gnu \ sysroot的制作工具我们会用到的工具rsync需要特别强调的是不要在一个装了过多图形库的宿主机上直接构建Qt否则configure可能会因为检测到宿主机上的xcb开发库而偷偷启用一些不必要的模块给后面的交叉编译增加意外变量。我建议尽量用一台干净的Ubuntu server不要装桌面环境。2.2 交叉编译工具链安装与验证Ubuntu的软件源里直接提供了aarch64交叉编译工具链安装很方便sudo apt install gcc-aarch64-linux-gnu g-aarch64-linux-gnu安装完成后检查版本和工作状态aarch64-linux-gnu-gcc --version aarch64-linux-gnu-g --version如果工具链可用会看到gcc 9.x或10.x的版本信息。这里要提醒一句Qt 5.14.2与GCC 11及以上版本的兼容性问题在社区里一直有反馈典型症状是编译过程中出现atomic相关或std::vector内部的奇怪报错。所以如果你想少折腾就用系统源里的gcc 9或10。如果系统源给的版本太高也可以手动安装aarch64专属的gcc-10工具链包sudo apt install gcc-10-aarch64-linux-gnu g-10-aarch64-linux-gnu安装后可以通过update-alternatives切换默认版本或者直接使用带版本号的命令aarch64-linux-gnu-gcc-10。工具链准备好后再做一个最小验证写一个helloworld交叉编译放到板子上跑通这一步可以帮助你区分“工具链问题”和“Qt编译问题”aarch64-linux-gnu-g hello.cpp -o hello_arm file hello_arm如果file命令输出中显示“ELF 64-bit LSB executable, ARM aarch64”就说明交叉工具链工作正常。2.3 准备目标板 sysrootsysroot就是目标板根文件系统的一个精简副本里面至少要有/aarch64设备上运行程序需要的头文件和库。交叉编译Qt时编译器需要链接libc、libstdc等基础库它们都来自sysroot。没有sysroot交叉编译器只能生成纯功能代码链接阶段必然报错找不到一堆系统库。准备sysroot有几种常见方式我推荐用rsync直接从运行中的目标板同步这样最能保证版本一致mkdir -p /opt/aarch64-sysroot rsync -avz root目标板IP:/lib /opt/aarch64-sysroot/ rsync -avz root目标板IP:/usr/include /opt/aarch64-sysroot/usr/ rsync -avz root目标板IP:/usr/lib /opt/aarch64-sysroot/usr/ rsync -avz root目标板IP:/usr/local/lib /opt/aarch64-sysroot/usr/local/注意rsync同步时可能会破坏软链接所以要在目标板上先打包再在宿主机解压的方式更稳妥。我自己常用的做法是# 在目标板上执行 tar czf /tmp/sysroot.tar.gz /lib /usr/include /usr/lib /usr/local/lib # 拷回到宿主机 scp root目标板IP:/tmp/sysroot.tar.gz /opt/ # 在宿主机上解压 cd /opt tar xzf sysroot.tar.gz这样拷过来的sysroot中/lib下就可以看到ld-linux-aarch64.so.1、libc.so.6等目标板运行库。Qt configure在检查系统库时就会在这个sysroot里找而不是去翻宿主机上x86的库。sysroot目录结构不需要完整到烧录镜像那种程度但/usr/include、/usr/lib和/lib这三块一定要有否则编译Qt库时头文件会缺失。如果你的目标板没有编译器系统头文件可能不全这种情况下可以用芯片厂商BSP包自带的sysroot目录这也是很常见的选择。3. Qt 5.14.2 源码获取与 configure 全程配置3.1 下载源码与解压Qt官方存档里下载源码包是一个固定动作。选择qt-everywhere-opensource-src包它包含了qtbase、qtdeclarative、qtmultimedia等所有补充模块后续裁剪空间更大cd ~/build wget https://download.qt.io/archive/qt/5.14/5.14.2/qt-everywhere-opensource-src-5.14.2.tar.xz tar xf qt-everywhere-opensource-src-5.14.2.tar.xz cd qt-everywhere-opensource-src-5.14.2我建议不要直接在源码目录里编译而是在源码目录外建一个独立的build目录把构建产物和源码分开这样后续二次编译比较清爽。可以这样创建mkdir -p ~/build/qtbuild cd ~/build/qtbuild但要说明一点Qt的configure脚本在源码目录外执行时有路径要求最稳妥的方式是在源码目录内部创建build子目录然后在build子目录里运行上级目录的configuremkdir -p qt-everywhere-opensource-src-5.14.2/build cd qt-everywhere-opensource-src-5.14.2/build ../configure ...这样既能在独立目录编译又不会让configure找不到模块相对路径。3.2 configure 关键参数逐项解读configure这一步是全流程的核心参数选择直接决定最终产物形态和编译能否成功。我在实际项目中整理了一套比较稳妥的配置先贴出来../configure \ -static \ -release \ -opensource \ -confirm-license \ -prefix /opt/qt-aarch64-static \ -xplatform linux-aarch64-gnu-g \ -sysroot /opt/aarch64-sysroot \ -nomake examples \ -nomake tests \ -no-opengl \ -no-xcb \ -no-gtk \ -qt-zlib \ -qt-libpng \ -qt-libjpeg \ -no-openssl \ -skip qtdeclarative \ -skip qtmultimedia \ -skip qtwebengine \ -skip qtcharts \ -no-compile-examples下面逐项说明每个参数的含义以及为什么这么设置。-static和-release组合是“静态发布”的标配。-release表示编译release版本不做debug符号减小体积-static告诉Qt构建静态库而非默认的动态库。如果你还要调试可以改用-debug或者再添加一个debug_and_release配置但在嵌入式简化场景下没必要。-opensource -confirm-license用于在命令行直接确认开源许可避免configure交互卡在等待输入的地方。-prefix指定Qt静态库最终安装路径后续我们手写的项目Makefile会用到这个路径来定位qmake头文件和库文件。-xplatform linux-aarch64-gnu-g的作用是告知qmake“目标平台的名字”。Qt源码的mkspecs目录里预置了很多平台描述其中就包含linux-aarch64-gnu-g。这个平台选项会让qmake生成aarch64专用的Makefile规则。-sysroot指向我们准备好的aarch64根文件系统副本所有交叉编译过程中的系统库搜索都会在这里进行。这个参数是aarch64交叉编译的命脉忘了加或者路径写错后面编译Qt时一定会出现找不到linux/input.h之类的系统头文件错误。-module裁剪方面我的策略是“省电模式”嵌入式场景用不到QML画布、多媒体框架、WebEngine这种重量级模块直接通过-skip参数跳过去既减少编译时间又降低产物体积。上面命令里我skip掉了qtdeclarative、qtmultimedia、qtwebengine、qtcharts等实际使用中你可以按需调整。有一点要记住QtBase模块是所有模块的地基不能skip而且它的构成非常庞杂里面有核心库、GUI库、网络库、sql库、widgets等其中很多子模块仍会被编译。如果想进一步精简需要在configure时用更细的参数禁用例如-no-sql-sqlite也可以考虑不过SQLite在很多项目里还是有点用的我一般保留。-no-opengl -no-xcb -no-gtk这组参数在Linux嵌入式环境中的意义是把Qt与桌面显示服务器的关联切断。如果你的目标板没有GPU驱动、也不需要跑完整的X11/Wayland桌面那么直接禁用这些模块Qt会退回到linuxfb、minimal、offscreen这类更轻量的QPA平台插件。这在很多工业控制屏、车载设备里是正常配置。如果你确实需要eglfs跑GPU加速那再把-no-opengl改成-opengl es2之类的但这需要目标板上有配套GPU驱动属于另一个故事了。-qt-zlib -qt-libpng -qt-libjpeg这组参数表示让Qt使用源码内部携带的zlib、libpng、libjpeg实现而不是去sysroot里找系统库。对嵌入式平台来说这往往更保险因为目标板上这些库的版本不一定符合Qt要求用内置的反而省心。-no-openssl表示不启用OpenSSL支持。嵌入式设备如果不需要HTTPS加密通信直接关掉能省去针缝里翻找ssl证书和OpenSSL交叉编译的麻烦。如果你的板子需要连网建议后续单独交叉编译OpenSSL再通过-openssl-linked把这些库接进来。3.3 定制 mkspecs 适配本机工具链理论上-xplatform linux-aarch64-gnu-g 指向的mkspecs文件可能和你实际安装的工具链命令不完全匹配。比如我系统里装的是aarch64-linux-gnu-gcc-10而mkspecs里默认写的是aarch64-linux-gnu-gcc。这种小偏差在编译时不会立刻报错但到了链接可能会因为工具链不统一产生奇怪问题。我的做法是先打开mkspecs文件看一眼确认编译器名称vim qtbase/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 QMAKE_AR aarch64-linux-gnu-ar cqs QMAKE_OBJCOPY aarch64-linux-gnu-objcopy QMAKE_NM aarch64-linux-gnu-nm QMAKE_STRIP aarch64-linux-gnu-strip如果发现工具链命令和我安装的不一致直接修改这个文件把默认的程序名改成自己环境中的工具名。比如我系统里是gcc-10就可以改成QMAKE_CC aarch64-linux-gnu-gcc-10 QMAKE_CXX aarch64-linux-gnu-g-10改完记得保存。这一步虽然很小却是我多次折腾后总结出来的坑很多人非要拿自带的mkspecs硬扛结果编译到一半提示找不到编译器或者ar工具排查半天才发现是名字写错了。4. 编译、裁剪与安装落地4.1 并行编译与时长预期configure执行完成后如果一切顺利在build目录下会生成Makefile和qmake配置。接下来就可以开始正式编译。我一般推荐用比CPU核数稍少的并行任务数避免一次性把内存占满make -j$(nproc)我第一次在8核16线程的虚拟机上编译时全量编译大约用了40多分钟如果按我上面的裁剪配置去掉大量模块之后通常20到30分钟就能跑完。编译过程中会看到一屏一屏的编译指令在滚动很多人第一次看到会觉得是不是死循环了其实只要最后能看到类似“Qt is now configured for building”之后的编译顺利完成没有明显报错就说明进行得很正常。如果中途有编译错误先看error上面的几行日志。大部分情况都是头文件找不到或者依赖库缺失直接把宿主环境缺的库装好重新make就行。make命令支持断点续编不会从头再来。4.2 静态库产物验证编译完成后在build目录的lib子目录下会生成大量.a结尾的静态库文件例如libQt5Core.a、libQt5Gui.a、libQt5Widgets.a等。可以用文件信息确认架构file lib/libQt5Core.a输出会显示这是aarch64的归档文件。看到这里就可以放心确认已经成功生产了aarch64静态库。如果你细心一点还会发现在lib目录下除了.a文件还会有几个so文件或者so的软链接这并不奇怪。少数模块还是会以动态库形式生成比如Qt平台插件中有一部分不得不以.so形式存在。真正运行时如果程序依赖这些插件仍然需要拷贝对应so文件。不过对于纯Widgets应用通常用不到的这种额外插件。4.3 make install 安装与验证编译完成后把静态库安装到我们指定的prefix目录make install安装完成后检查安装目录ls /opt/qt-aarch64-static/bin/ ls /opt/qt-aarch64-static/lib/正常情况下bin目录下能看到qmake和其他Qt工具lib目录下能看到libQt5*系列静态库include目录下是Qt头文件。这里补充一个经验qmake这个工具本身是宿主机x86架构的不要直接丢到aarch64板子上跑它只是宿主机用来生成Makefile的工具并不参与目标板运行。这一点很多人容易混淆我当年也犯过把qmake拷贝到板子的低级错误。验证qmake能否正常工作/opt/qt-aarch64-static/bin/qmake -v如果输出QMake version 3.1并显示Qt version 5.14.2就说明安装成功。至此Qt aarch64静态库的构建阶段算是彻底完工接下来就是如何使用它来编自己的应用了。5. 工程配置与目标板部署实战5.1 编写一个测试工程为了验证静态库可用我写一个最传统的QWidget弹窗程序。工程目录中创建三个文件main.cpp、test.pro。main.cpp#include QApplication #include QLabel #include QPushButton #include QVBoxLayout int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.setWindowTitle(Qt Static on aarch64); QVBoxLayout *layout new QVBoxLayout(window); QLabel *label new QLabel(Hello, aarch64 Qt!); QPushButton *button new QPushButton(Quit); layout-addWidget(label); layout-addWidget(button); QObject::connect(button, QPushButton::clicked, app, QApplication::quit); window.resize(320, 200); window.show(); return app.exec(); }test.proQT core gui widgets TARGET test_qt TEMPLATE app CONFIG c11 SOURCES main.cpp生成Makefile并编译/opt/qt-aarch64-static/bin/qmake test.pro make这一步执行完当前目录下会生成test_qt可执行文件。用file检查它的架构file test_qt输出应当显示ELF 64-bit LSB executable, ARM aarch64说明已经交叉编译成功。5.2 静态链接的库顺序与裁剪细节如果编译时出现undefined reference错误很多时候不是Qt库没装好而是链接库的顺序不对。使用qmake生成的Makefile时顺序是自动化处理的一般不会出问题。但如果我们手动拼g命令就必须注意依赖库的顺序被依赖的库要放在依赖它的库之后。例如widgets依赖guigui依赖core那么命令行里就要写成-lQt5Widgets -lQt5Gui -lQt5Core顺序不能颠倒。另外静态编译时qmake默认会把所有Qt模块库链接进来有一些不需要的库可以用-l参数手动排除但通过qmake管理会更简单。如果出现个别菱形依赖导致链接失败优先检查QMAKE_LIBS相关配置或者手动添加额外系统库例如-lpthread -ldl -lrt在静态链接前期经常需要这些。还有一点需要特别提醒如果你的程序用到QIcon、图片加载这些功能静态编译时默认不会把所有图片格式插件编进可执行文件。常见症状是程序运行后图片显示不出来控制台打印“no such plugin for format png”之类的错误。解决办法是在pro文件中显式加上插件QTPLUGIN qico qjpeg qgif qpng或者在你自己的代码里使用静态插件初始化的宏#include QtPlugin Q_IMPORT_PLUGIN(qjpeg)这类插件初始化问题在动态库编译时很少遇到但一旦切换成静态编译就非常典型我见过太多人栽在这里。5.3 拷贝到目标板并运行编译完成后把test_qt拷贝到目标板。如果你的目标板开启了SSH服务可以这样传scp test_qt root目标板IP:/root/在目标板上执行前先加执行权限chmod x /root/test_qt /root/test_qt此时如果目标板上有framebuffer设备或者X11环境窗口会正常显示出来。如果没有显示设备或者你想验证程序能否运行可以先用offscreen平台插件QT_QPA_PLATFORMoffscreen /root/test_qt如果程序正常启动并保持运行说明静态编译的Qt库在目标板上完全可用。这时候用ldd命令看一下程序动态依赖ldd /root/test_qt你会看到它依然依赖libc.so.6、libstdc.so.6等少数几个系统基础库这些都是目标板Linux系统必然提供的不用额外打包。如果想让程序彻底不依赖任何系统的C运行时理论上可以做全静态编译但那样对glibc的兼容性要求更高反而容易碰坑。实际工程中“Qt全静态 依赖目标板基础系统库”的方案已经完全够用稳定性和部署便利性平衡得最好。6. 常见问题与排查实录6.1 configure 阶段的经典报错我在自己搭建和帮同事排查的过程中见过最多的一类问题是configure执行到一半提示缺少某些工具或头文件直接退出。比如configure: error: Perl not found解决方式是sudo apt install perl。configure: error: The OpenGL functionality test failed!解决方式是确认自己是否真需要OpenGL不需要就加上-no-opengl。configure: error: Basic XLib functionality test failed!这种情况通常是因为sysroot里缺少X11相关的头文件或者你选了-xcb但这里的头文件不全。嵌入式环境直接加-no-xcb绕开。这类问题看着吓人但本质就是“configure在做平台能力探测探测不过就不往下走”。排查思路就是顺着报错提示回顾自己之前设置的参数看是模块选多了还是sysroot确实缺库不要一上来就怀疑编译器坏了。6.2 编译期和链接期的工具链报错编译期最常见的报错是找不到头文件。报错信息里往往写着某个路径比如/usr/include/gnu/stubs-32.h不存在这种情况基本可以确定是sysroot内容不完整。尤其那些只拷贝了/libs和/usr/lib、却遗漏/usr/include的sysroot一编译就崩。解决方法是补齐目标板头文件重新走一遍rsync或解压完整rootfs。链接期的undefined reference则分为两类一类是缺Qt模块比如你在pro里用了QT network却没有链接libQt5Network.a这时把QT变量补上即可另一类是缺系统库比如lzma、pthread、dl需要在高编译配置里加上LIBS -lpthread -ldl这些额外项。静态链接下这些系统库出现的频率远高于动态链接习惯了就好。还有一类比较隐蔽的报错是二进制体积超过某个限制时出现relocation truncated to fit。这种通常是编译选项里有-fPIC相关的坑在嵌入式静态编译中偶尔出现。解决方法是给qmake补上QMAKE_CFLAGS -fPIC -fvisibilityhidden重新编译Qt源码。不过这属于偶发情况先不要主动加遇到再加。6.3 运行期 QPA 插件问题静态编译的程序运行时还有一个高频问题就是找不到QPA平台插件。报错往往是这样的This application failed to start because no Qt platform plugin could be initialized. Available platform plugins are: linuxfb, minimal, offscreen, vnc.出现这个提示说明你的静态链接里没有把对应的QPA platform插件编进去。Qt的QPA插件本质上是动态加载的模块在静态编译下如果没有显式引进来运行时自然找不到。两种解决方案我都验证过方案一设置环境变量告诉Qt使用某个内置插件export QT_QPA_PLATFORMlinuxfb ./test_qt如果目标板存在/dev/fb0帧缓冲设备linuxfb是正统方案如果没有显示设备则用offscreen或者minimal。方案二在pro文件里用QTPLUGIN强制导入插件QTPLUGIN qlinuxfb或者在代码里加#include QtPlugin Q_IMPORT_PLUGIN(qlinuxfb)我在实际项目里倾向于在目标板上先手动export QT_QPA_PLATFORM验证再在工程里用QTPLUGIN固定下来避免每次启动都要手动设置环境变量。6.4 经验速查表整个过程中我踩坑最多的地方整理成一张表方便你对照排查阶段常见报错根本原因处理方法configurePerl not found缺少perlapt install perlconfigureOpenGL functionality test failed无OpenGL或sysroot缺GL头文件加-no-openglconfigureBasic XLib functionality test failedxcb相关头文件缺失加-no-xcbmakegnu/stubs-32.h not foundsysroot不完整补全sysroot的/usr/includemakeundefined reference to glibc符号工具链glibc版本过新或过旧换gcc 9/10版本工具链链接QTPLUGIN相关插件缺失静态插件未导入在pro中加QTPLUGIN运行no Qt platform pluginQPA插件未内置设置QT_QPA_PLATFORM或导入插件体积二进制过大静态打包了全部Qt模块裁剪模块、strip符号另外所有编出来的aarch64可执行文件在宿主机上看起来都是“运行不了”的因为x86系统没有aarch64动态加载器。不要在宿主机上直接运行test_qt那只会得到“Exec format error”或者看不到任何反应。验证架构用file跑程序必须到目标板上。我在实际使用中发现静态编译的Qt程序在目标板上调试时还有一个小技巧可以先用交叉工具链的strip把符号表去掉体积能小不少aarch64-linux-gnu-strip test_qtrelease模式下原本30MB的程序strip后到20MB左右很正常。如果你后续还要调整代码留着完整版别急着strip等最后发布版再瘦身。最后再分享一点个人体会整个Qt aarch64静态交叉编译过程中最能节省时间的环节就是把sysroot准备好、把configure参数想清楚。sysroot不完整后面会反复报错你来回查资料的时间远远超过编译本身configure参数不匹配有时候编译能过但跑起来发现平台插件的坑、显示模块的坑排查更麻烦。先把这两步做扎实后面基本就是make循环的体力活了。
返回列表