Qt 5.14.2 x86_64 静态编译 ------ 从零搭建完整手册
声明:文章由AI编写,但内容经本人落地验证可行!
适用场景:在一台 x86_64 Linux (银河麒麟 V10 / openEuler 20.03 系)上,从零搭建一套 本地静态 Qt 编译环境 ,以后每个 Qt 项目都能编出单文件、零依赖部署的 x86 程序 (拷到任意 x86_64 Linux 桌面机直接运行,不需要装 Qt)。
全程约 1~1.5 小时(其中 Qt 编译约 1 小时无需值守)。 本手册自包含:全部操作都是直接在终端执行的命令,照抄即可,不需要创建任何脚本文件。
QT版本:5.14.2; 系统:Kylin Linux Advanced Server release V10 (Halberd); version 4.19.90-89.11.v2401.ky10.x86_64 下载链接:pan.quark.cn/s/ce2fffc14... 提取码:6rZE
第 0 章:开始之前
0.1 三个名词(3 分钟看懂)
| 名词 | 一句话解释 |
|---|---|
| 静态编译 | 把 Qt 库直接"焊"进你的程序里。产物是一个大文件,目标机不用装任何 Qt |
| 动态依赖 | 程序运行时仍需要的少量系统库(X11、OpenGL 等)。这些必须保持动态,否则在别人机器上画不出窗口 |
| 前缀(prefix) | 这套静态 Qt 安装到哪。本文用 /opt/qt5.14.2-x86_64-static,与系统的、交叉的 Qt 互不干扰 |
0.2 与"ARM 交叉编译"的区别(如果你搭过那套)
| ARM 交叉版 | x86 本地版(本手册) | |
|---|---|---|
| 产出 | ARM 目标机跑的程序 | x86 机器跑的程序 |
| 编译器 | aarch64-linux-gnu-g++ | 本机 g++ |
| sysroot / 工具链文件 | 需要 | 全部不需要 |
| 步骤 | 多(工具链→sysroot→.pc 清理→...) | 少(6 个步骤做完) |
| 依赖白名单 | 19 项 | 18 项 |
0.3 环境要求自查表
| 项目 | 要求 | 不满足怎么办 |
|---|---|---|
| 系统 | x86_64 Linux(麒麟 V10/openEuler 20.03 同系最佳) | 先换机或确认 glibc ≥ 2.17 |
| 用户 | root(或 sudo) | --- |
| 磁盘 | /opt 下 ≥ 15GB 空闲(源码 3GB + 构建 6GB + 安装 2GB) |
清理或换分区 |
| 内存 | ≥ 4GB(8GB 更稳,-j8 编译峰值大) | 内存小就用 -j4(见附录 A 第 3 条) |
| 网络 | 能访问 download.qt.io + yum 源可用 | 见步骤 2 的备用下载方案;yum 见步骤 3 失败处理 |
| 终端 | 全新终端,未 source 任何交叉 profile | 这是全流程的隐形前提,见步骤 1 |
0.4 流程总览(6 个步骤按顺序做完)
ini
步骤 1 环境准备(确认终端干净、磁盘够、建工作目录)
步骤 2 下载 Qt 5.14.2 源码(官方直链 + md5 校验 + 解压)
步骤 3 安装依赖(yum 装 -devel 包 + 逐项确认在位)
步骤 4 编译 Qt(configure 带 -no-icu → make → install,约 1 小时)
步骤 5 藏 xkbcommon 链接入口(1 分钟,程序少 2 个动态依赖)
步骤 6 demo 验收(预期 NEEDED = 18 个,零红线)
│
▼
日常使用:新项目 5 分钟出包(第七章)
若机器上已有 ARM 交叉编译环境:本手册所有命令都做了隔离设计(独立前缀、独立构建树、 每步先净化环境、结尾复查交叉环境),照做不会破坏它。
步骤 1:环境准备(2 分钟)
bash
# 1. 切 root
su - root
# 2. 【关键】确认当前终端是"干净"的
gcc -dumpmachine
# 预期输出:x86_64-linux-gnu
# 若输出 aarch64-xxx 或报错 command not found:
# 说明 source 过 /etc/profile.d/cross-aarch64.sh → 开一个新终端重来
# 3. 确认磁盘
df -h /opt
# 预期:可用 ≥ 15GB
# 4. 建工作目录
mkdir -p /opt/qtwork && cd /opt/qtwork
⚠️ 唯一的铁律 :编 x86 的整个过程中,任何终端都不要 source 交叉环境 (如果这台机器搭过 ARM 交叉编译)。一旦混入,pkg-config 会解析到 ARM 的库, 轻则链接报"跳过不兼容的",重则编出废件。步骤 4 里也有检查命令兜底,但提前避开最省事。
步骤 2:下载 Qt 源码(约 10 分钟)
国内镜像(清华/中科大/上交等)已全部裁剪 5.14 老版本归档,只有官方主站还有。 archive 直链不需要 Qt 账号。
bash
cd /opt/qtwork
# 2.1 下载(约 524MB;wget -c 支持断点续传,中断后重敲同一条命令即可接着下)
wget -c https://download.qt.io/archive/qt/5.14/5.14.2/single/qt-everywhere-src-5.14.2.tar.xz
# 2.2 校验完整性(必须一致再继续)
md5sum qt-everywhere-src-5.14.2.tar.xz
# 预期输出:b3d2b6d00e6ca8a8ede6d1c9bdc74daf qt-everywhere-src-5.14.2.tar.xz
# 不一致 = 文件损坏,rm 删掉后重新下载
# 2.3 解压(约 1~2 分钟)
tar -xJf qt-everywhere-src-5.14.2.tar.xz
# 2.4 确认解压成功
ls qt-everywhere-src-5.14.2/configure
# 预期输出:qt-everywhere-src-5.14.2/configure
下载太慢的两个替代方案:
bash
# 方案 A:多线程下载(装了 aria2 的话)
aria2c -x 8 -s 8 https://download.qt.io/archive/qt/5.14/5.14.2/single/qt-everywhere-src-5.14.2.tar.xz
# 方案 B:从已搭好的机器整目录打包拷来(最快,5 分钟)
# 在老机器上执行:
# tar -cJf qt-src.tar.xz -C /opt/qtwork qt-everywhere-src-5.14.2
# scp qt-src.tar.xz root@新机器:/opt/qtwork/
# 在新机器上解压后,直接进入步骤 3
步骤 3:安装依赖(2 分钟)
3.1 一条命令装齐全部 -devel 包
bash
yum install -y gcc gcc-c++ make perl \
openssl-devel zlib-devel \
freetype-devel fontconfig-devel \
libxcb-devel libX11-devel libXext-devel \
libSM-devel libICE-devel \
mesa-libGL-devel mesa-libEGL-devel \
libxkbcommon-devel libxkbcommon-x11-devel
说明:
-qt-xcb会在编译时内置 xcb-util 全家桶(icccm/image/keysyms/...), 所以不用单独装那一串 xcb-util 包;这里装的都是 Qt 真正的外部依赖。 yum 幂等,重复执行安全。
3.2 逐项确认关键文件在位(configure 的硬前提)
bash
ls /usr/include/openssl/ssl.h /usr/lib64/libssl.a /usr/lib64/libcrypto.a \
/usr/include/zlib.h \
/usr/include/freetype2/freetype/freetype.h \
/usr/include/fontconfig/fontconfig.h \
/usr/include/X11/Xlib.h /usr/include/X11/Xlib-xcb.h \
/usr/include/xcb/xcb.h /usr/include/GL/gl.h \
/usr/include/xkbcommon/xkbcommon-x11.h \
/usr/lib64/libGL.so /usr/lib64/libEGL.so /usr/lib64/libSM.so
预期结果 :所有文件路径原样列出,没有任何一行 不存在 / No such file。
| 失败现象 | 处理 |
|---|---|
| 有包装不上 + 对应文件缺失 | yum 源问题:挂本系统 x86_64 安装 ISO 做本地源(mount -o loop Kylin-*.iso /mnt 后配置 repo),装上对应包后重跑 3.2 确认 |
| libEGL.so 缺失 | 非致命(configure 会自动关闭对应特性),但建议装上 mesa-libEGL-devel |
步骤 4:编译 Qt(约 1 小时,其中 make 阶段无需值守)
4.1 环境净化(防交叉污染,搭过 ARM 环境的机器必做;其他机器无副作用)
bash
# 临时清掉交叉变量(只在当前终端生效,不改任何配置文件)
unset PKG_CONFIG_PATH PKG_CONFIG_LIBDIR PKG_CONFIG_SYSROOT_DIR CC CXX \
CFLAGS CXXFLAGS LDFLAGS
# 把 bootlin(交叉工具链目录)从当前终端的 PATH 里剔除
export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v bootlin | paste -sd:)
# 三项确认
which pkg-config # 预期:/usr/bin/pkg-config
gcc -dumpmachine # 预期:x86_64-linux-gnu
ls /opt/qtwork/qt-everywhere-src-5.14.2/configure # 预期:路径原样列出
4.2 建构建目录(干净起点)
bash
cd /opt/qtwork
rm -rf build-x86-static
mkdir -p build-x86-static && cd build-x86-static
rm -rf是为了清掉可能存在的历史半成品(configure 中断会留下残缺状态污染下次构建)。 全新机器上这个目录本来就不存在,命令同样安全。
4.3 configure(核心命令,注意两点)
⚠️ 注意一 :源码根目录的 configure 是一个"转发器",它自己会转给 qtbase/configure 并自动加 -top-level 参数------所以这里不能再传 -top-level , 传了会报 Unknown command line option(实测踩过的坑)。
⚠️ 注意二 :-no-icu 必须在第一次编译就带上(作用:去掉 icu 三个约 25MB 的 动态依赖;QRegularExpression 正则走内置 pcre 不受影响,仅各国语言排序退化为码点序, 多数程序无感知)。
bash
cd /opt/qtwork/build-x86-static
/opt/qtwork/qt-everywhere-src-5.14.2/configure \
-opensource -confirm-license -release -static \
-prefix /opt/qt5.14.2-x86_64-static -extprefix /opt/qt5.14.2-x86_64-static \
-nomake tests -nomake examples \
-skip qtwebengine -skip qtwebview -skip qtwebchannel -skip qtwayland -skip qtscript -skip qtgamepad \
-skip qtspeech -skip qtremoteobjects -skip qtscxml -skip qtlottie -skip qtdatavis3d \
-skip qtsensors -skip qtlocation -skip qtserialbus -skip qtconnectivity -skip qtpurchasing -skip qtquick3d \
-xcb -qt-xcb -xcb-xlib -fontconfig -system-freetype \
-openssl-linked -opengl desktop -linuxfb -evdev \
-no-eglfs -no-dbus -no-glib -no-icu \
-qt-libpng -qt-libjpeg -qt-harfbuzz -qt-pcre -qt-zlib -sql-sqlite \
-no-warnings-are-errors \
2>&1 | tee ../configure-x86-static.log
参数速览(为什么是这些):
| 参数 | 作用 |
|---|---|
-static |
Qt 全静态,程序单文件 |
-qt-xcb |
xcb 及 14 个子库全部编进 Qt,消除一堆动态依赖 |
-no-dbus / -no-glib / -no-eglfs |
各砍掉一串传递依赖(dbus→systemd→gcrypt...、glib→pcre/ffi...、eglfs→drm/gbm) |
-no-icu |
去掉 icu 三个动态依赖(约 25MB) |
-qt-libpng -qt-libjpeg -qt-harfbuzz -qt-pcre -qt-zlib |
这些第三方库用 Qt 内置源码,不链系统的 |
16 个 -skip |
裁掉嵌入式不可行/罕用模块(webengine、wayland、sensors 等) |
4.4 核对 config.summary(六项,错了就别往下走)
bash
grep -E "Qt D-Bus|GLib |OpenSSL |directly linked|Desktop OpenGL|EGLFS|XCB XKB" config.summary
| 关键项 | 期望值 | 含义 |
|---|---|---|
Qt D-Bus ............................... no |
no | 故意关掉(省一串传递依赖) |
GLib ................................... no |
no | 故意关掉 |
OpenSSL ................................ yes |
yes | openssl-linked 生效 |
Qt directly linked to OpenSSL ........ yes |
yes | OpenSSL 直接链入 |
Desktop OpenGL ....................... yes |
yes | OpenGL 支持 |
EGLFS .................................. no |
no | 故意关掉(xcb 桌面用不到) |
XCB XKB .............................. yes |
yes | 键盘支持,必须 yes,否则程序没键盘输入 |
若
XCB XKB是 no:说明步骤 3 的libxkbcommon-x11-devel没装上,回去重装再从 4.2 重来。
4.5 make(约 1 小时,无需值守)
bash
make -j$(nproc) 2>&1 | tee ../make-x86-static.log
编译期间想看进度(另开一个终端,不影响编译):
bash
tail -3 /opt/qtwork/make-x86-static.log # 进度(模块名会滚动变化)
grep -cE "error:" /opt/qtwork/make-x86-static.log # 0 = 健康
free -h # 内存水位
make 失败时的两种已知情况(按现象对号入座):
| 现象 | 处理 |
|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|------------------------------------------------|
| make 莫名消失 / 退出码 137 | 内存不足(OOM)。直接敲 `make -j4 2>&1 | tee -a ../make-x86-static.log` 续编(已编完的模块不会重编) |
| qtvirtualkeyboard 报 cstdlib:75: fatal error: stdlib.h | 已知 PCH 坑(xorg proto 系列 .pc 注入的 -I/usr/include 变成 -isystem 后破坏 gcc 的 #include_next)。执行下面 4.5.1 的修复命令后续编 |
| 其他报错 | 把 tail -60 /opt/qtwork/make-x86-static.log 的输出贴出来排查 |
4.5.1 PCH 坑的修复命令(仅在上面第二种情况发生时执行):
bash
# 清掉构建树 Makefile 里的 -isystem /usr/include(锚定匹配,不伤子目录形式)
find /opt/qtwork/build-x86-static -name Makefile -exec \
sed -i 's@-isystem /usr/include\( \|$\)@ @g' {} +
# 续编(增量,已编完的模块不重编)
cd /opt/qtwork/build-x86-static
make -j$(nproc) 2>&1 | tee -a ../make-x86-static.log
4.6 安装
bash
# 若之前装过旧版本,先清空安装目录(旧产物残留会被程序链入,不清白编;全新机器可跳过)
rm -rf /opt/qt5.14.2-x86_64-static
cd /opt/qtwork/build-x86-static
make install 2>&1 | tee ../install-x86-static.log
# 安装验证一:qmake 版本
/opt/qt5.14.2-x86_64-static/bin/qmake -v
# 预期两行:QMake version 3.1 / Using Qt version 5.14.2 in /opt/qt5.14.2-x86_64-static/lib
# 安装验证二:五个核心库
ls -lh /opt/qt5.14.2-x86_64-static/lib/libQt5Core.a \
/opt/qt5.14.2-x86_64-static/lib/libQt5Gui.a \
/opt/qt5.14.2-x86_64-static/lib/libQt5Widgets.a \
/opt/qt5.14.2-x86_64-static/lib/libQt5VirtualKeyboard.a \
/opt/qt5.14.2-x86_64-static/plugins/platforms/libqxcb.a
# 预期:5 行全部列出(大小约 14M/15M/17M/1.4M/13K)
4.7 自愈检查:安装文件里有没有烙进交叉 sysroot 路径
这一步只对搭过 ARM 交叉环境的机器有意义(若 configure 阶段 PATH 混入过交叉 pkg-config,ARM 库路径会被烙进 Qt 安装文件,之后链接程序时会报一串"跳过不兼容的"):
bash
# 检查(预期:无任何输出)
grep -rl -- "-L/opt/bootlin" /opt/qt5.14.2-x86_64-static --include='*.prl' --include='*.pri'
若有输出,执行清理(只剔除 -L 路径,不影响库依赖本身):
bash
grep -rl -- "-L/opt/bootlin" /opt/qt5.14.2-x86_64-static --include='*.prl' --include='*.pri' | \
xargs -r sed -i 's@-L/opt/bootlin[^ ]*@@g'
4.8 交叉环境复查(搭过 ARM 环境的机器做,全新机器跳过)
bash
/opt/qt5.14.2-aarch64-static-xcb/bin/qmake -v # 预期:仍正常输出版本信息
ls -d /opt/qtwork/build-desktop-full # 预期:目录仍存在
步骤 5:藏 xkbcommon 链接入口(1 分钟,程序少 2 个动态依赖)
做什么 :把 /usr/lib64 里两个无版本号的 .so 链接入口 挪走,让链接器只能选 devel 包自带的静态库 .a。
原理 :静态 Qt 的库里留着 xkb_* 未定义符号,真正决定链 .so 还是 .a 的时刻是 你编最终程序的那次链接 ------两者都在时 ld 永远优先选 .so。Qt 源码树没内置 xkbcommon(不存在 -qt-xkbcommon 参数),所以"藏 .so 入口"就是标准做法。 只藏链接器入口,运行时真身 libxkbcommon.so.0 原地不动------系统里已运行/之后运行的 程序完全不受影响,只影响"之后新发生的链接"。
5.1 确认静态库在位(libxkbcommon-devel 提供)
bash
ls /usr/lib64/libxkbcommon.a /usr/lib64/libxkbcommon-x11.a
# 预期:两行都列出
若报不存在:说明 devel 包没带静态库,跳过整个步骤 5 也可以(程序会多 2 个 xkbcommon 动态依赖,x86 桌面机器都自带,不影响运行)。
5.2 藏入口
bash
mkdir -p /opt/qtwork/x86-so-hidden
mv /usr/lib64/libxkbcommon.so /usr/lib64/libxkbcommon-x11.so /opt/qtwork/x86-so-hidden/
5.3 验证
bash
ls /usr/lib64/libxkbcommon.so /usr/lib64/libxkbcommon-x11.so
# 预期:No such file or directory(藏匿生效)
恢复动态链接(如需还原系统默认):
bash
mv /opt/qtwork/x86-so-hidden/libxkbcommon*.so /usr/lib64/ && ldconfig
步骤 6:demo 验收(2 分钟)
6.1 建 demo 源码
bash
mkdir -p /opt/qtwork/demo-x86 && cd /opt/qtwork/demo-x86
cat > main.cpp <<'EOF'
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QLabel l(QStringLiteral("Qt 5.14.2 x86_64 静态编译 OK"));
l.resize(420, 120);
l.show();
return app.exec();
}
EOF
cat > demo.pro <<'EOF'
TARGET = demo
QT += widgets
CONFIG += release
SOURCES += main.cpp
EOF
⚠️
SOURCES += main.cpp不能漏 ------qmake 不会自动收集目录里的 .cpp, 漏了链接会报undefined reference to main(实测踩过的坑)。
6.2 编译(qmake 必须用全路径)
bash
# 若当前终端 source 过交叉环境,先净化(同 4.1 的三条)
unset PKG_CONFIG_PATH PKG_CONFIG_LIBDIR PKG_CONFIG_SYSROOT_DIR CC CXX CFLAGS CXXFLAGS LDFLAGS
export PATH=$(echo "$PATH" | tr ':' '\n' | grep -v bootlin | paste -sd:)
/opt/qt5.14.2-x86_64-static/bin/qmake
make -j$(nproc)
6.3 瘦身(可选,顺序不能反)
bash
# gcc7 的 note bug:必须先移除该 section 再 strip
objcopy --remove-section .gnu.build.attributes demo
strip demo
ls -lh demo
6.4 依赖总览
bash
readelf -d demo | grep NEEDED
验收标准------18 项白名单(NEEDED 只能是这些,实测基线):
| 类别 | 库 |
|---|---|
| 显示/图形 | libEGL.so.1、libGL.so.1 |
| 字体 | libfontconfig.so.1、libfreetype.so.6 |
| X11 | libX11.so.6、libX11-xcb.so.1、libXext.so.6、libSM.so.6、libICE.so.6 |
| xcb | libxcb.so.1、libxcb-glx.so.0 |
| C 运行时 | libc.so.6、libm.so.6、libdl.so.2、libpthread.so.0、libstdc++.so.6、libgcc_s.so.1、ld-linux-x86-64.so.2 |
6.5 红线检查(一条命令,无输出 = 通过)
bash
readelf -d demo | grep -E "libQt5|libdbus|libglib|libgthread|libffi|libdrm|libicu|libxkbcommon|libxcb-icccm|libxcb-image|libxcb-keysyms|libxcb-randr|libxcb-render|libxcb-shape|libxcb-sync|libxcb-xfixes|libxcb-xinerama|libxcb-xinput"
| 红线项(若出现) | 含义 |
|---|---|
任何 libQt5*.so |
Qt 不是静态的,qmake 用错了 |
libxkbcommon* |
步骤 5 的 .so 被还原了 → 重做步骤 5 |
libicu* |
编译时没带 -no-icu,或用错前缀 → 从步骤 4 重来 |
libglib* / libdbus* / xcb 碎片库 |
误用了别的 Qt 或环境污染 |
6.6 冒烟测试
bash
# 有桌面环境(DISPLAY 存在)时:直接跑,窗口正常弹出即通过
./demo
# 无桌面环境时:拷到任意 x86_64 桌面机再验证
scp demo 用户@某桌面机:~/ # 然后在桌面机上 ./demo
注意:不要用
QT_QPA_PLATFORM=offscreen测------静态 demo 只链入了 qxcb 平台插件, offscreen 插件不在内,会 qFatal 退出(表现为"已放弃"),这是插件缺失不是程序问题。
验收全过 = 环境搭建完成。 部署:单文件 scp 到任意 x86_64 Linux 桌面机直接运行,零配置。
第七章:日常使用(以后每个新项目 5 分钟出包)
7.1 qmake 项目(三步)
bash
# 前提:新终端,未 source 交叉 profile
cd /opt/qtwork/myapp
/opt/qt5.14.2-x86_64-static/bin/qmake myapp.pro # 必须全路径,防误用别的 qmake
make -j$(nproc)
# 可选瘦身(顺序不能反):
objcopy --remove-section .gnu.build.attributes myapp
strip myapp
# 验收(30 秒,白名单/红线见步骤 6):
readelf -d myapp | grep NEEDED
7.2 CMake 项目
qmake 会自动把平台插件/图片插件"焊"进程序,CMake 不会 ------不补的话编译能过、 运行报 no Qt platform plugin could be initialized。需要补两样(内容全部给全):
① 新建 plugin_import.cpp(加进 add_executable 的源文件列表):
cpp
#include <QtPlugin>
/* 平台插件(必须)------窗口能在 X11 桌面显示全靠它 */
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
/* GL 集成插件(2 个,必须)------OpenGL 渲染路径(GLX/EGL)的桥接 */
Q_IMPORT_PLUGIN(QXcbEglIntegrationPlugin)
Q_IMPORT_PLUGIN(QXcbGlxIntegrationPlugin)
/* 图片格式插件:8 个全上。全加零风险------静态库不增加动态依赖,只多 1~2MB 体积 */
Q_IMPORT_PLUGIN(QGifPlugin) // gif
Q_IMPORT_PLUGIN(QICNSPlugin) // icns(注意 QICNS 全大写)
Q_IMPORT_PLUGIN(QICOPlugin) // ico/cur(注意 QICO 全大写)
Q_IMPORT_PLUGIN(QJpegPlugin) // jpg/jpeg
Q_IMPORT_PLUGIN(QTgaPlugin) // tga(注意 QTga 大小写)
Q_IMPORT_PLUGIN(QTiffPlugin) // tiff/tif
Q_IMPORT_PLUGIN(QWbmpPlugin) // wbmp
Q_IMPORT_PLUGIN(QWebpPlugin) // webp
② CMakeLists.txt 追加(插件目标与 Q_IMPORT_PLUGIN 一一对应):
cmake
target_link_libraries(myapp PRIVATE
Qt5::Widgets
Qt5::QXcbIntegrationPlugin
Qt5::QXcbEglIntegrationPlugin
Qt5::QXcbGlxIntegrationPlugin
Qt5::QGifPlugin
Qt5::QICNSPlugin
Qt5::QICOPlugin
Qt5::QJpegPlugin
Qt5::QTgaPlugin
Qt5::QTiffPlugin
Qt5::QWbmpPlugin
Qt5::QWebpPlugin
)
③ 编译命令(不需要任何工具链文件):
bash
cd /opt/qtwork/myapp
mkdir -p build-x86 && cd build-x86
cmake .. \
-DCMAKE_PREFIX_PATH=/opt/qt5.14.2-x86_64-static \
-DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
7.3 常见问题速查
| 现象 | 原因与解决 |
|---|---|
| 编出的程序拷到别的 x86 机器"无法执行" | 用了交叉 qmake(编出的是 ARM 程序),检查 qmake 全路径 |
链接报一串 跳过不兼容的 .../bootlin/... |
source 过交叉 profile。开新终端,并按 6.2 的两条命令净化环境后重编 |
NEEDED 出现 libxkbcommon.so.0 |
步骤 5 的 .so 被还原 → 重做步骤 5;不重藏也能跑(桌面机自带) |
NEEDED 出现 libicu* |
编译时没带 -no-icu,或用错了 Qt 前缀 |
strip 报 corrupt GNU build attribute note |
先 objcopy 去 note 再 strip(顺序不能反) |
| cmake 改环境后结果诡异 | rm -rf build-x86 重来(CMake 缓存了旧编译器路径) |
运行报 no Qt platform plugin could be initialized |
CMake 项目没加 plugin_import.cpp / 没链插件目标 |
| 想用 WebEngine / dbus 模块 | 编译时被 skip / -no-dbus,没有。可用:Widgets、Quick/QML、Charts、SVG、Network、SerialPort、Multimedia、VirtualKeyboard、Sql+SQLite 等 |
附录 A:踩坑全记录(每条的解法都已固化在手册步骤里,照做不会踩)
| # | 坑 | 现象 | 根因 | 手册里固化在哪 |
|---|---|---|---|---|
| 1 | -top-level 不能手传 |
configure 秒退 Unknown command line option '-top-level' |
tarball 根目录的 configure 是转发器,自己会加 -top-level,再传就重复 |
步骤 4.3 的"注意一" |
| 2 | .pro 漏 SOURCES | 链接报 undefined reference to main |
qmake 不会自动收集目录里的 .cpp | 步骤 6.1 的 demo.pro(含 SOURCES)+ 警告 |
| 3 | 内存不足 | make 静默消失 / 退出码 137 | -j8 编译峰值内存超限 | 4.5 故障表:make -j4 续编即可 |
| 4 | 交叉环境污染 .prl | 链接行混入 -L/opt/bootlin-...,ld 报"跳过不兼容" |
configure 期 PATH 里的交叉 pkg-config 把 ARM 库路径烙进 Qt 安装文件 | 4.1 净化环境(治本)+ 4.7 自愈检查(兜底) |
| 5 | vkb PCH 编译失败 | qtvirtualkeyboard 报 stdlib.h:75 fatal error |
xorg proto 系列 .pc 注入 -I/usr/include,变 -isystem 后破坏 #include_next |
4.5.1 修复命令 |
| 6 | icu 拖 25MB | NEEDED 多 libicui18n/uc/data 三项(约 25MB) | Qt 默认链系统 icu | 4.3 首次编译就带 -no-icu |
| 7 | xkbcommon 动态依赖 | NEEDED 多 libxkbcommon/xkbcommon-x11 两项 | ld 优先选 .so;Qt 无 -qt-xkbcommon 参数(源码树未内置) |
步骤 5 藏 .so 入口(对系统零影响,可逆) |
| 8 | offscreen 冒烟假失败 | QT_QPA_PLATFORM=offscreen 跑 demo "已放弃" |
静态 demo 只链了 qxcb 平台插件,offscreen 插件不在内,qFatal 退出 | 6.6 的"注意" |
| 9 | gcc7 note bug | strip 报 corrupt GNU build attribute note: bad description size |
gcc 7 生成损坏的 note section | 6.3 瘦身顺序(先 objcopy 后 strip) |
| 10 | 安装残留混链 | 重编后程序仍链入旧库 | 安装目录没清空,旧 .a 残留 | 4.6 安装前 rm -rf 前缀 |
附录 B:产物清单与回滚
这套环境的全部"资产":
| 路径 | 内容 | 可否删 |
|---|---|---|
/opt/qt5.14.2-x86_64-static/ |
静态 Qt 本体(核心资产) | ❌ 删了就要重跑步骤 4 |
/opt/qtwork/qt-everywhere-src-5.14.2/ |
Qt 源码(约 3GB) | ✅ 可删(重编时需重下/重拷) |
/opt/qtwork/build-x86-static/ |
构建树(约 6GB) | ✅ 可删(只是缓存,重编会重建) |
/opt/qtwork/x86-so-hidden/ |
藏起来的 xkbcommon .so 入口 |
⚠️ 删前先 mv 回 /usr/lib64/ |
完全回滚(卸载这套环境):
bash
mv /opt/qtwork/x86-so-hidden/libxkbcommon*.so /usr/lib64/ 2>/dev/null; ldconfig # 先还系统库
rm -rf /opt/qt5.14.2-x86_64-static /opt/qtwork/build-x86-static /opt/qtwork/demo-x86
# 可选:连源码一起删
# rm -rf /opt/qtwork/qt-everywhere-src-5.14.2
(已搭过 ARM 交叉环境的机器:上述命令不碰 /opt/qt5.14.2-aarch64-static-xcb、 /opt/qtwork/build-desktop-full、/opt/bootlin-*,交叉环境完好。)
附录 C:为什么有些库保持动态
| 依赖 | 为什么必须动态 |
|---|---|
| X11 / xcb ×7 | 要与目标机 X server 对话,静态化直接跑不了 |
| GL / EGL | 要匹配目标机 GPU 驱动 |
| fontconfig / freetype | 所有 Linux 桌面 100% 自带,静态化需源码编译,零收益 |
| glibc / libstdc++ | 全静态有 NSS/dlopen 隐患且无兼容性收益 |
这 18 个就是实际最优解(ARM 版收工时同款结论)。