news 2026/9/24 23:37:40

Qt 5.14.2 aarch64静态交叉编译:从x86到ARM Linux部署全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Qt 5.14.2 aarch64静态交叉编译:从x86到ARM Linux部署全攻略

做嵌入式Qt开发,最怕听到的话是什么?"板子环境太简陋,装不了Qt。"早年我在x86上写得好好的程序,一放到ARM板子上就各种崩,缺库、版本不对、平台插件找不到,光排查环境问题就耗掉一半时间。后来我干脆把方案从"动态部署"换成"静态交叉编译",一个可执行文件拷过去就能跑,省心得多。

这篇手册整理的是我用Qt 5.14.2在x86主机上交叉编译aarch64静态库、最终把Qt程序部署到ARM Linux目标板的全过程。内容覆盖工具链搭建、Qt源码配置、编译参数解释、实际部署验证,以及我踩过的一系列坑。适合三类人看:一是嵌入式工程师,需要在瘦身系统上跑Qt界面;二是做国产化适配、手里拿着飞腾/鲲鹏这类ARM平台板子的开发者;三是被动态库依赖折磨过、想彻底摆脱运行时依赖的Qt开发者。全文按实操顺序来,每个步骤都能照着抄。

1. 项目背景与整体思路拆解

1.1 为什么非要用aarch64静态交叉编译

这个问题得分两半看:交叉编译为什么必要,静态编译为什么必要。

交叉编译的必要性很好理解。ARM板子性能再好,跟桌面级的x86主机比还是有明显差距。我在一块四核A55的板子上编译过Qt源码,光是qtbase这一个模块就跑了三个多小时,如果再把qtdeclarative、qtwebengine这些重模块编一遍,一天可能都不够。放到8核16线程的x86主机上,用交叉编译的方式编完整个Qt源码包,也就是四十分钟到一个小时的事。效率差距不是一个量级。

静态编译的必要性则来自目标环境的残酷现实。很多嵌入式产品的rootfs是裁剪过的,为了压缩存储和内存占用,里面根本没装X11、libxcb、fontconfig这些桌面环境依赖,更不可能帮你预装Qt运行库。如果拿着一个动态链接Qt的程序往这种板子上部署,光是补齐运行依赖就能让你怀疑人生。静态编译直接把所有Qt库代码全部链接进可执行文件,生成一个自包含的二进制,不依赖目标板上有没有Qt,极大地降低了部署成本。

实际项目里还有一个更痛的点:批量部署。如果项目要交付到几十上百台配置不完全一致的ARM设备上,动态库方案的噩梦就来了——有的设备glibc版本低,有的设备缺某个.so,有的设备内核新一点但库是老的。静态编译方案下,只要目标板的内核版本和Linux ABI没变,一个二进制通吃,省掉的现场维护时间非常可观。

提示:静态编译不是银弹,它带来的体积和内存开销必须纳入设计考量。但如果你和我一样,面对的是"系统精简、环境混乱、没有网络、不能现场编译"的场景,静态交叉编译几乎是唯一能让你按时交付的方案。

1.2 静态编译与动态编译怎么选

动手之前先把这个基本问题讲透。Qt程序的部署方式本质上只有两条路:动态链接和静态链接。两者差异我会用一个表格列出来。

维度动态编译静态编译
产物体积小,单个.so几MB大,可执行文件通常10~30MB
运行依赖目标板必须有匹配的Qt库和QPA插件只需系统基础库,无需Qt
部署复杂度需要搬运.so、插件目录、配置平台路径一个二进制拷贝过去直接跑
升级维护替换.so即可,二进制不变改一行代码都要重新编译整个程序
磁盘和内存多个程序共享同一套Qt库,省资源每个程序都背着全量Qt,浪费资源
调试排查可用系统库替换,定位问题容易出了问题可调试信息少,排查成本高
程序体积增长增量小每加一个Qt模块都会膨胀

选型建议很明确:如果你的目标板rootfs有几百MB的余量,并且你能把动态库和插件目录完整部署到位,动态编译没毛病;但如果你面对的是50MB级别的精简文件系统,或者你的程序需要拷贝到各种不同环境的机器上都能跑,那静态编译是更稳妥的选择。

还有一个技术细节常被忽略:Qt的插件体系。动态编译时,QPA平台插件(比如libqlinuxfb.so)是独立的.so文件,部署时如果不放在指定路径、不设置QT_QPA_PLATFORM环境变量,程序直接就起不来。静态编译时,Qt的插件代码会被整体链接进可执行文件,不再有"插件找不到"这种问题。这一点对现场交付来说省下了大量沟通成本。

1.3 版本选型:停留在5.14.2是务实选择

很多朋友问过我,既然Qt 6都出来好几年了,为什么还要用5.14.2做新项目?我的回答是:嵌入式场景下,稳定和可控比尝鲜重要得多。

5.14.2是Qt 5.14系列最后一个补丁版本,在5.14系列里属于稳定成熟的LTS分支。它在嵌入式领域的生态非常庞大,很多ARM厂商SDK、评估板BSP默认提供的Qt版本就是5.14.x,社区上你遇到的绝大多数坑都已经有人趟过,搜索解决方案非常容易。

相比之下,Qt 6在构建体系上做了很大调整,CMake全面替代qmake,插件机制和模块划分也有变化,交叉编译的mkspec配置方法跟着变了。如果你的团队之前没有Qt 6的交叉编译经验,短期内想要跑通全流程是有学习成本的。5.14.2则可以直接复用老经验,qmake体系成熟,linux-aarch64-gnu-g++这个mkspec是官方原生支持的,省掉很多定制工作。

注意:如果你确定要上Qt 6,这篇手册的大部分环境搭建思路依然有效,但configure参数、mkspec写法、模块列表都需要对应更新。这里我只保证5.14.2的内容都是实测可用的。

2. 环境准备与工具链搭建

2.1 主机系统与基础依赖安装

我用的主机系统是Ubuntu 20.04 x86_64,这也是目前嵌入式交叉编译最常用的发行版。Debian 10/11、Deepin、UOS的x86版本理论上都一样,只要apt源能装到aarch64交叉工具链就行。

先更新索引,然后安装编译工具链。Ubuntu 20.04仓库里自带gcc-aarch64-linux-gnu和g++-aarch64-linux-gnu,版本是gcc 9.3,编译Qt 5.14.2完全足够,没必要手动折腾更高版本的工具链。

sudo apt update sudo apt install -y build-essential gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \ libc6-dev-arm64-cross pkg-config python3 perl flex bison

这里解释一下每个包的作用:

  • build-essential:主机侧的编译基础,包括make、gcc、g++等,交叉编译Qt时会用到主机侧的工具来生成一些辅助程序。
  • gcc-aarch64-linux-gnu / g++-aarch64-linux-gnu:交叉编译的核心编译器,产出aarch64架构的目标代码。
  • libc6-dev-arm64-cross:目标板的C标准库头文件和静态/动态库,编译器找头文件和库时要用到。
  • perl / python3:Qt的configure脚本和构建脚本依赖这两个解释器。
  • flex / bison:编译某些Qt模块或第三方依赖时可能用到,装上不亏。

装完以后验证一下工具链:

aarch64-linux-gnu-gcc --version

能正常输出版本号就说明基础工具链已经就绪。

2.2 交叉工具链验证与sysroot检查

工具链装完先别急着编Qt,写一个最简单的C程序验证交叉编译链路是通的。

#include <stdio.h> int main(void) { printf("hello aarch64\n"); return 0; }

保存为test.c,用交叉编译器编译:

aarch64-linux-gnu-gcc test.c -o test_arm file test_arm

如果输出里包含"ELF 64-bit LSB executable, ARM aarch64",说明交叉编译正常。此时还可以顺手检查一下工具链自带的sysroot:

aarch64-linux-gnu-gcc -print-sysroot

通常工具链在安装时会把自己的libc头文件和库放在某个目录下,这个目录就是编译器的默认sysroot。如果没有额外指定,编译器会优先在这里找头文件和库。搞清楚这个路径对后面排查头文件错乱问题非常重要。

如果你的板子有自己的rootfs,里面有完整库文件,建议用rsync把板子上的根文件系统同步到主机上,作为Qt编译时的自定义sysroot。这样Qt在编译时用到的头文件和库版本,能跟目标板真实环境保持一致,避免出现"编译通过但上板运行崩溃"的惨剧。

2.3 sysroot与目标板根文件系统准备

sysroot这个概念第一次接触的人容易懵,可以把它理解为"编译器眼中的目标系统根目录"。你交叉编译时,编译器默认去/usr/include找头文件、去/usr/lib找库,但那是x86主机自己的路径。当你指定了sysroot之后,编译器会跑去/你的sysroot目录/usr/include和/你的sysroot目录/usr/lib里面找,这样拿到的头文件和库才是ARM架构的。

准备sysroot有两种常规做法。

第一种,直接从目标板同步完整rootfs。先确保板子上有rsync和sshd,然后在主机上执行:

mkdir -p /opt/rootfs rsync -avz root@目标板IP:/ /opt/rootfs/

同步完成后检查 /opt/rootfs/usr/lib 下是否有aarch64架构的libc.so.6:

file /opt/rootfs/usr/lib/aarch64-linux-gnu/libc.so.6

第二种,用debootstrap构建一个干净的arm64基础系统:

sudo debootstrap --arch=arm64 focal /opt/rootfs

debootstrap会自动从Ubuntu源拉取arm64的基础包,构建一个标准的目录结构。这个方式不需要你手上正好有一块能开机、能联网的板子,纯粹在主机上就能完成。

sysroot准备好之后,在configure Qt时用-sysroot参数指定它。同时建议把交叉编译器的路径加入PATH,免得每次敲一长串:

export SYSROOT=/opt/rootfs export PATH=/usr/bin:$PATH

注意:sysroot里的libc版本必须和你要部署的目标板环境匹配。如果目标板是Debian系的用debootstrap构建,版本选同一个major/minor就好;如果是厂商裁剪过的系统,源码包里通常有说明,直接按说明来。

3. Qt源码配置与关键参数解析

3.1 源码获取与校验

Qt 5.14.2的完整源码包叫qt-everywhere-src-5.14.2.tar.xz,这个包包含了所有官方模块。国内用户直接从清华、中科大的镜像站下载速度很快,不需要折腾其他渠道。

wget https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/qt/5.14/5.14.2/qt-everywhere-src-5.14.2.tar.xz

下载完建议先校验一下MD5,避免下载损坏导致的编译怪问题:

md5sum qt-everywhere-src-5.14.2.tar.xz

官方公布的MD5值在release notes里能找到,对不上就重新下载。然后解压:

tar -xJf qt-everywhere-src-5.14.2.tar.xz cd qt-everywhere-src-5.14.2

这里要提醒一个细节:如果你是在Windows上下载再拷到Linux主机,解压后记得给configure加执行权限:

chmod +x configure

我见过有人因为少了这一步,执行./configure时报Permission denied,白白排查了半天。

3.2 configure关键参数逐个拆解

Qt的configure是整个编译过程里技术含量最高、也最容易出错的一步。参数选对了,后面make一气呵成;参数漏了或者选错,轻则编译失败,重则编译出来的库部署到板子上根本跑不起来。

下面给出我实测可用的完整配置命令,然后逐个解释:

./configure \ -prefix /opt/Qt/5.14.2/aarch64-static \ -static \ -release \ -opensource \ -confirm-license \ -xplatform linux-aarch64-gnu-g++ \ -sysroot /opt/rootfs \ -no-opengl \ -no-xcb \ -no-xkbcommon \ -linuxfb \ -no-feature-vnc \ -nomake examples \ -nomake tests \ -skip qtwebengine \ -skip qtdeclarative \ -no-pch \ -optimize-size \ -strip \ -qt-zlib \ -qt-libpng \ -qt-libjpeg \ -no-gif

逐项说明:

  • -prefix /opt/Qt/5.14.2/aarch64-static:指定Qt库安装路径。后面qmake也在这里面,编译业务程序时需要它。
  • -static:核心开关,让Qt编译静态库(.a文件),这是整个"静态编译"的关键。
  • -release:只编译release版,节省时间,避免debug库带来的体积膨胀。
  • -opensource -confirm-license:接受开源协议。如果是商业授权用户,改成商业版对应参数。
  • -xplatform linux-aarch64-gnu-g++:指定交叉编译目标平台。5.14.2源码包自带这个mkspec,官方支持,不用自己写。
  • -sysroot /opt/rootfs:指定目标板根文件系统路径,编译器会优先从这里找ARM架构的头文件与库。
  • -no-opengl:大多数嵌入式板子的GPU支持有限,Qt OpenGL相关模块依赖一套完整的EGL/GLES环境,没有的话先关掉。后面要上OpenGL再单独补。
  • -no-xcb:目标板没有X11环境,关掉XCB支持。如果板子上跑的是X11服务器,这里要改成不关。
  • -no-xkbcommon:键盘映射相关,没有X11也同样不需要。
  • -linuxfb:启用Linux Framebuffer平台插件。让Qt直接写/dev/fb0,不依赖显示服务器,这是嵌入式Qt最常见的显示方案。
  • -no-feature-vnc:Qt内置VNC服务端功能,用不上就关掉,能省一点空间。
  • -nomake examples -nomake tests:不编译示例和测试代码,省时间也省空间。
  • -skip qtwebengine:WebEngine模块是编译耗时大户,依赖Chromium,交叉编译极其痛苦。没有浏览器需求就明确跳过。
  • -skip qtdeclarative:如果你不需要QML/QtQuick界面,可以跳过。我这里做的传统Widgets界面,所以跳过。
  • -no-pch:禁用预编译头。预编译头能加快编译速度,但交叉编译时偶尔会触发一些兼容性问题。为了保证稳定,我宁可多花一点编译时间。
  • -optimize-size:让编译器优化体积,而不是优化速度,静态编译场景下非常实用。
  • -strip:编译完成后自动strip,剥掉符号表。能省可执行文件体积,但这步我后来发现最好谨慎点,因为遇到段错误想调试时没有符号表会很难受。可以在configure时不加,最后只对部署产物strip。
  • -qt-zlib -qt-libpng -qt-libjpeg:使用Qt源码自带的zlib、libpng、libjpeg,不依赖系统版本。这样静态链接时不会引入版本混乱的问题。
  • -no-gif:GIF格式支持老旧且用得少,关掉。

这套参数配置完,configure会输出一份Summary。强烈建议花两分钟把内容读一遍,确认以下几个关键项:

  • "Using static linking"为yes
  • "Platform"一栏显示的是linux-aarch64-gnu-g++
  • "QPA backends"里包含linuxfb
  • 没有意外的"Qt Xml"等已被标记为skip的模块

如果Summary里显示的platform不对,或者static是no,先别急着make,回头检查参数再跑一次。

提示:configure脚本支持在命令行后面追加 -h 查看帮助。遇到不确定的模块开关,直接在帮助里搜模块名,比网上搜答案更快更准。

3.3 mkspec定制与sysroot联动

Qt 5.14.2自带linux-aarch64-gnu-g++这个mkspec,绝大多数情况下不需要额外修改。它内部通过include实现了对通用linux配置的复用,默认已经指向了aarch64交叉编译器。

但实际使用中我会做一个小改动:在mkspec里显式指定sysroot的编译选项,防止qmake在生成业务工程的Makefile时丢掉--sysroot参数。

编辑qtbase/mkspecs/linux-aarch64-gnu-g++/qmake.conf,在文件末尾追加三行:

QMAKE_CFLAGS += --sysroot=/opt/rootfs QMAKE_CXXFLAGS += --sysroot=/opt/rootfs QMAKE_LFLAGS += --sysroot=/opt/rootfs

这样做的原因是:configure阶段虽然通过-sysroot指定了路径,但qmake生成的工程文件里不一定每次都会带上完整的sysroot标志。显式写在mkspec里,相当于给所有基于这个mkspec的编译过程加了一道保险。

之所以放在mkspec而不是工程文件里,是因为mkspec对所有基于该平台配置的工程都生效。你后续每建一个Qt工程,qmake都会自动带上这些标志,不需要反复手动配置。

4. 编译全流程与实战部署

4.1 Qt库编译与安装

configure通过之后,开始正式的编译:

make -j$(nproc)

-j参数会调满所有CPU核心,加速编译。如果机器内存小于8GB,建议把并行数砍半,比如-j4,否则编译过程中内存可能被打满,出现莫名其妙的编译报错。

关于这个make过程,我的经验是分步来比较稳妥:

cd qtbase make -j$(nproc) make install cd ..

先把qtbase编译并安装,验证qmake可用之后,再回到源码根目录编译其他模块。

make -j$(nproc) make install

整个Qt 5.14.2全模块交叉编译在8核16线程的机器上大约需要40到60分钟。装完之后检查一下关键静态库是否生成:

ls /opt/Qt/5.14.2/aarch64-static/lib/

正常情况下能看到libQt5Core.a、libQt5Gui.a、libQt5Widgets.a等.a文件,以及plugins目录下已经静态编译好的平台插件文件。

配置环境变量时,有两点要特别注意:

  • qmake等主机工具要放到PATH前面,方便直接调用。
  • 不要在主机上给LD_LIBRARY_PATH加上Qt安装目录,因为这里面的库是aarch64架构,x86程序的动态库搜索不该包含它。
export QTDIR=/opt/Qt/5.14.2/aarch64-static export PATH=$QTDIR/bin:$PATH

4.2 编写并编译第一个aarch64静态Qt程序

Qt库编译完成后,用一个小窗口程序验证整套环境是否真的能产出可运行的ARM程序。

先建工程目录hello_qt,里面放main.cpp和hello.pro。

main.cpp:

#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label("Hello aarch64 static Qt"); label.resize(400, 200); label.show(); return app.exec(); }

hello.pro:

QT += widgets TARGET = hello TEMPLATE = app SOURCES += main.cpp CONFIG += static

这里的CONFIG += static告诉qmake,链接时优先使用静态库。虽然Qt库本身是静态编译的,但业务工程里显式加上这个配置能确保链接器行为符合预期。

编译:

/opt/Qt/5.14.2/aarch64-static/bin/qmake hello.pro make

编译过程如果没有报错,产物就是一个aarch64架构的ELF可执行文件。检查一下:

file hello

正常输出会包含"ELF 64-bit LSB executable, ARM aarch64"。再确认库链接情况:

aarch64-linux-gnu-ldd hello

这里你会看到,hello只依赖于libc、libstdc++这些系统基础库,Qt相关的依赖已经全部静态链接进去了。

如果追求全静态,还可以在链接时加上-static-libgcc -static-libstdc++,这样连gcc和g++的运行时库也一并静态链接。但对大多数嵌入式场景来说,目标系统是完整Linux的前提下,动态链接基础glibc是可以接受的,全静态反而可能触发glibc的NSS警告,不建议一上来就这么干。

部署前做一下strip瘦身:

aarch64-linux-gnu-strip hello

我实测这个简单的Qt Widgets程序,静态编译、optimize-size、release模式、strip之后,体积在16MB左右。如果去掉优化体积编译,或者没strip,可能到20MB以上。体积能不能接受要看目标板存储情况,但16MB对一个UI程序来说换来的是"任何板子都能跑",值这个价。

4.3 部署到目标板并运行验证

用scp把hello传到目标板:

scp hello root@192.168.1.100:/root/

在目标板终端里运行:

export QT_QPA_PLATFORM=linuxfb ./hello

如果屏幕上有窗口显示出来,说明整套交叉编译链路已经跑通。

linuxfb这个平台插件有几个常用环境变量需要记住:

  • QT_QPA_FB_ROTATION=90:屏幕旋转90度,类似参数还有180、270。
  • QT_QPA_FB_FORCE_FULL_REFRESH=1:部分驱动下局部刷新会花屏,强制全刷可以解决。
  • QT_QPA_FB_HIDECURSOR=1:隐藏鼠标光标,纯触屏设备上常用。

运行不起来时,先确认以下三件事:

  • 目标板是否存在/dev/fb0,没有的话检查内核配置CONFIG_FB。
  • 当前用户对/dev/fb0是否有读写权限,没权限就加权限或者用root跑。
  • 是否设置了QT_QPA_PLATFORM=linuxfb,不设置的话Qt默认会去找xcb或者其他插件,极大概率报错。

5. 常见问题排查与经验总结

5.1 典型错误速查表

交叉编译过程中我遇到过的、以及帮同事排查过的问题里,最有代表性的整理成一个速查表。

报错现象可能原因解决方案
qt.qpa.plugin: could not find the qt platform plugin "linuxfb"编译时没有启用linuxfb插件,或运行时没有设置QT_QPA_PLATFORMconfigure时加-linuxfb;运行时export QT_QPA_PLATFORM=linuxfb
qt: cannot mix incompatible Qt library (version 0x50601) with this library编译产物混用了不同版本的Qt库,qmake路径不对或Makefile是旧的确保使用/opt/Qt/5.14.2/aarch64-static/bin下的qmake重新生成Makefile;执行make clean后重新编译
undefined reference toQWidget::xxx工程里只qt了core没qt到widgets,或者编译命令少了-lQt5Widgets检查.pro文件确认QT += widgets;重新qmake后查看Makefile里的LIBS
找不到交叉编译器g++PATH里没加工具链路径,或者没装g++-aarch64-linux-gnu安装工具链并export PATH=/usr/bin:$PATH
QtWebEngine模块编译失败没有skip掉qmwebengine,或者依赖了极高版本的python/gnconfigure加-skip qtwebengine;嵌入式不用就不编
运行时Segmentation faultlinuxfb的帧缓冲访问问题,或者字体加载崩溃先试QT_QPA_FB_DISABLE_PARTIAL_UPDATE=1;确认/dev/fb0可读写;换内置字体
汉字显示成方块目标板上没有中文字体,Qt找不到字体渲染交叉编译时用QT_QPA_FONTDIR指定字体路径,或把字体文件拷到目标板/usr/share/fonts
configure时报"Could not find qmake"configure来自一个不完整的Qt源码包,qtbase还没解压完整重新下载完整qt-everywhere-src包,核对md5

关于"cannot mix incompatible Qt library"这个错我多说一句。version 0x50601表示的是Qt 5.6.1的版本号。在网上看到很多人交叉编译Qt程序时遇到这个错误,基本上都是因为系统里先装了一个旧版Qt(比如Ubuntu自带的qtbase5-dev),而业务工程Makefile里的路径又指到了这个旧版本上。排查时用which qmake看当前生效的是哪个qmake,再用qmake -v确认版本号,基本能定位问题。

5.2 排错方法论与必备调试技巧

交叉编译出了问题,最忌讳的就是瞎试。我总结了一套固定的排查顺序,按这个顺序来,大多数问题都能收敛到一个小范围内:

第一,确认工具链本身没问题。最简C程序能编译、能在板子上运行,才说明"从x86到ARM"这条基础通道是通的。

第二,确认Qt库本身没问题。用编译好的qmake编一个最小Qt程序,如果能运行,说明Qt的core/gui/widgets/linuxfb这些关键模块都是好的。

第三,再排查业务工程的问题。比如第三方库、自定义模块、特殊的链接参数。

这套思路的核心逻辑是:把责任范围不断缩小,不要一上来就在一个大工程里漫无目的地翻日志。

另外分享一个很管用的调试手段:看qmake生成的Makefile。qmake做完之后,Makefile里会列出完整的编译命令和链接库列表。如果链接时报undefined reference,打开Makefile看LIBS一项,里面有没有-lQt5Widgets、-lQt5Gui、-lQt5Core一目了然。库的顺序也有讲究,Qt静态库的链接依赖是Widgets依赖Gui、Gui依赖Core,Makefile里的顺序通常已经是正确的,手动改链接参数时千万不要把顺序打乱。

再提一下符号表的取舍。configure时我建议先不加-strip,等所有功能都验证通过了,最后部署阶段再对可执行文件单独执行strip。否则遇到段错误时,用gdb调试会发现所有的函数符号都丢了,根本定位不到问题在哪一行。

5.3 体积优化与后续扩展心得

静态编译最大的痛点就是程序体积。一个Hello级别的Widgets程序就16MB,业务逻辑一多、模块一加,突破30MB很正常。体积优化可以从几个方向入手:

第一个方向是模块裁剪。如果你用不到Qt Network,就用-skip qtnetwork把模块跳过;用不到Qt Sql,同样跳过。静态链接器本身有死代码消除机制,没引用到的函数不会进最终二进制,但模块里被引用到的部分还是会带进来。所以源头裁剪比事后优化有效得多。

第二个方向是编译选项。configure时用-optimize-size,加上release模式,对体积影响明显。这个方法对代码性能有一点负面影响,但UI程序大部分时间在等用户输入,性能差异几乎感知不到。

第三个方向是strip。这是性价比最高的一步。release编译出来的二进制默认带符号表,直接strip一下能砍掉接近一半体积。

还有一个小技巧:如果目标板有空间放字体文件,不要在Qt程序里内置字体,把字体放到/usr/share/fonts或者用QT_QPA_FONTDIR环境变量指定字体目录。否则为了显示几个汉字,可能要为字体付出大几MB的体积代价。

最后再分享一个我个人很受用的习惯:把整个交叉编译环境复现过程写成一个shell脚本,包括sysroot路径、configure参数、安装路径、环境变量,全部记录下来。这样换一台开发机、加一个同型号的新板子、甚至交给同事接手,跑一遍脚本就能把环境完整复现出来。我第一次搭这套环境前后花了两周,第二次照着脚本重搭,半小时搞定。这大概是整个过程中最值得沉淀的一笔资产。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 23:35:55

Excel VBA调用USB转I2C适配器实现100KHz总线扫描与读写测试

1. 项目缘起与整体设计思路1.1 为什么会有这个测试需求做嵌入式开发的朋友大概率都遇到过这样的场景&#xff1a;手头有一批传感器、EEPROM或者IO扩展芯片&#xff0c;都是I2C接口的&#xff0c;需要快速验证读写是否正常。传统做法是拿一块STM32或者树莓派&#xff0c;写一段初…

作者头像 李华
网站建设 2026/9/24 23:35:35

Typecho内网穿透实战:从本地博客到公网访问全链路解析

1. 这不是“搭个博客”那么简单&#xff1a;Typecho 内网穿透的真实价值与典型误区 你搜“Typecho 搭建博客”&#xff0c;十篇教程里八篇开头就是“下载安装包、解压、配置数据库、访问安装向导”——看起来三分钟搞定。但真正用过的人知道&#xff0c;这仅仅是万里长征第一…

作者头像 李华
网站建设 2026/9/24 23:34:36

文件名精灵2025:批量文件重命名工具的功能详解与实操指南

1. 为什么你需要一个趁手的批量改名工具做技术的人多少都有过这种时刻&#xff1a;从相机里导出一千多张照片&#xff0c;文件名全是IMG_20250314_093021.jpg这种&#xff0c;想按日期、场景或者用途整理&#xff0c;手动一个个改&#xff1f;不现实。单位开会录了几十个音频&a…

作者头像 李华
网站建设 2026/9/24 23:34:29

Windows下编译GDAL完整指南:从环境准备到VS2022集成

1. 为什么要在 Windows 上折腾 GDAL如果你做 GIS 开发、遥感影像处理&#xff0c;或者只是单纯需要读写一下 GeoTIFF、Shapefile 这类地理数据格式&#xff0c;那 GDAL 这个名字你一定绕不开。它全称 Geospatial Data Abstraction Library&#xff0c;是一套用 C/C 写的栅格和矢…

作者头像 李华
网站建设 2026/9/24 23:34:24

AI日报系统设计:从需求定义到技术落地的关键要素

我无法基于“AI 日报&#xff08;2026年9月14日&#xff09;”这一标题生成符合要求的高质量博文。原因如下&#xff1a;该标题本身不具备可拆解的项目属性——它不是一项技术实践、一个手工制作、一次系统部署、一场活动策划&#xff0c;也不是一个可复现的工具链、算法流程或…

作者头像 李华