☰
麒麟系统arm64源码编译Qt 5.12.8:离线部署与避坑指南
2026/10/20 18:59:35 网站建设 项目流程

简介:本资源面向在国产化平台进行Qt应用开发的工程师,提供在Kylin-Server-10-SP2-Release-Build09-20210524-arm64系统上编译完成的Qt 5.12.8头文件集合,可解决ARM64架构下麒麟系统缺少对应Qt开发头文件、难以直接编译调试的问题,适合需要交叉编译或本地构建Qt项目的开发者参考使用。压缩包为gz格式,共包含2000个文件,全部为h头文件,整体约65.91MB,涵盖QLocale、QOpenGL、QUrl等模块的接口声明,便于在项目中直接引用或对照排查编译错误。目前已有251人学习下载,可作为麒麟系统ARM64环境下搭建Qt开发环境的实用参考,帮助读者快速补齐头文件依赖、理解模块划分,减少环境配置与编译适配的时间成本。

1. 麒麟系统上把 Qt 5.12.8 从源码啃下来:一份 arm64 编译产物的拆包记录

在国产化替代的交付现场,arm64 架构的麒麟服务器系统上跑 Qt 应用,最让人头疼的往往不是业务代码,而是运行环境里那个版本对不上的 Qt 库。系统自带源里的 Qt 版本要么太老,要么缺模块,而客户环境又不允许随意联网装包。这份资源就是针对这个场景的产物:在 Kylin-Server-10-SP2-Release-Build09-20210524 的 arm64 系统上,把 Qt 5.12.8 从源码完整编译了一遍,产出了一套可复用的编译结果。它适合需要在离线或半离线环境下部署 Qt 应用的嵌入式与桌面端开发者,尤其是做信创适配、军工项目或工业控制上位机的同行。如果你正被“系统 Qt 版本锁死、第三方库依赖冲突、交叉编译工具链对不上”这几件事反复折磨,这份东西能帮你省掉至少一整天的编译排错时间。

2. 为什么选源码编译而不是直接装包:arm64 麒麟的依赖困局

2.1 系统源里的 Qt 版本与模块缺口

Kylin-Server-10-SP2 基于较新的内核与 glibc,但默认软件源里的 Qt 开发包通常停留在 5.9 或 5.11 的某个小版本,且模块裁剪严重。最典型的是qtwebengine、qtmultimedia、qtcharts这几个模块,在服务器版镜像里经常被剥离,因为服务器场景默认不装图形化组件。但实际交付中,很多上位机软件偏偏要用到图表和多媒体播放。直接apt install qt5-default装出来的环境,编译业务代码时会在#include <QtCharts>这一行直接报找不到头文件。源码编译的第一个理由就是:模块可控,缺什么编什么,不依赖发行版维护者的裁剪策略。

另一个隐性问题是 ABI 兼容性。系统源里的 Qt 是用 GCC 某个版本编的,而你的业务代码可能用了更新的编译器或不同的 C++ 标准。混用之后,轻则运行时崩溃,重则链接阶段就报undefined reference to symbol。源码编译能保证 Qt 本身和你的应用使用同一套工具链,把 ABI 风险压到最低。

2.2 arm64 架构下的编译工具链选择

在 arm64 麒麟上编译 Qt,工具链其实比 x86 简单,因为不需要交叉编译,直接本机自举即可。但要注意 GCC 版本。Qt 5.12.8 官方测试过的 GCC 上限大约到 GCC 8,而 Kylin-Server-10-SP2 自带的 GCC 可能是 7.x 或 9.x。如果系统 GCC 是 9.x,编译 Qt 5.12.8 时会在qtbase的某个模板元编程处报错,这是已知的 C++17 特性冲突。常见做法是装一个 GCC 7 或 GCC 8 的并行版本,用update-alternatives切换,或者直接在 configure 阶段指定QMAKE_CC和QMAKE_CXX指向旧版编译器。

我一般会先跑一遍gcc --version和g++ --version,确认版本号。如果是 9.x,不要硬扛,直接装gcc-8和g++-8,然后建软链接。这一步偷懒,后面会在编译到一半时炸出一堆模板错误,血泪经验。

2.3 编译产物的目录结构与复用逻辑

这份资源的核心价值在于“编译完成”四个字。它不是源码包,而是编译后的安装目录。典型的 Qt 源码编译安装结构是这样的:

目录内容复用方式
bin/qmake、moc、uic、rcc等工具直接加入 PATH
lib/libQt5Core.so.5等共享库加入LD_LIBRARY_PATH或拷入/usr/lib
include/Qt 模块头文件编译时通过qmake自动引用
plugins/平台插件、图像格式插件运行时通过QT_PLUGIN_PATH指定
mkspecs/平台相关的 qmake 配置qmake自动读取

复用逻辑很简单:把整个安装目录拷到目标机器,设置三个环境变量,业务代码用这个qmake重新生成 Makefile 即可。不需要在目标机器上再装任何 Qt 开发包。

3. 从源码到可用 qmake:编译步骤与关键参数拆解

3.1 源码包获取与编译前依赖安装

Qt 5.12.8 的源码包可以从官方归档站获取,单个模块包或完整包都行。完整包解压后是一个总目录,里面每个模块一个子目录。编译前需要装一堆依赖,在麒麟上可以用apt搞定:

# 基础编译工具 sudo apt install build-essential perl python3 git # Qt 核心依赖库 sudo apt install libgl1-mesa-dev libglu1-mesa-dev \ libx11-dev libxext-dev libxrender-dev libxcb1-dev \ libxkbcommon-dev libxkbcommon-x11-dev \ libfontconfig1-dev libfreetype6-dev \ libssl-dev libxcursor-dev libxcomposite-dev \ libxdamage-dev libxrandr-dev libxi-dev \ libsqlite3-dev libpq-dev libmysqlclient-dev \ libasound2-dev libpulse-dev libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev # 如果要用 QtWebEngine,还需要额外依赖 sudo apt install libnss3-dev libxss-dev libxtst-dev \ libegl1-mesa-dev libgles2-mesa-dev

这些依赖里,libxcb1-dev系列是图形界面必须的,libssl-dev影响网络模块的 HTTPS 支持,libsqlite3-dev影响 SQL 模块。如果编译服务器版无界面环境,可以跳过 X11 相关依赖,但那样编出来的 Qt 只能跑控制台程序。参数说明:build-essential提供 gcc/g++/make,perl和python3是 Qt 构建脚本需要的解释器。

3.2 configure 阶段的参数取舍

进入源码总目录后,先跑configure。这一步决定了哪些模块被编译、装到哪里、用什么特性。以下是我在麒麟 arm64 上验证过的配置命令:

./configure -prefix /opt/Qt5.12.8 \ -opensource -confirm-license \ -release -shared \ -nomake examples -nomake tests \ -no-opengl \ -skip qtwebengine \ -skip qtwayland \ -qt-zlib -qt-libpng -qt-libjpeg \ -qt-freetype -qt-pcre \ -sqlite -openssl-linked \ -I /usr/include/openssl \ -L /usr/lib/aarch64-linux-gnu \ -platform linux-g++

逐项说明:-prefix指定安装目录,我习惯放/opt下,避免污染系统目录。-opensource -confirm-license是开源版必须的确认参数。-release -shared表示编译发布版动态库,体积和性能平衡。-nomake examples -nomake tests跳过示例和测试,能省至少 40% 编译时间。-no-opengl在无显卡的服务器上很关键,否则会因找不到 GL 库而报错。-skip qtwebengine是因为这个模块编译极其耗时且依赖复杂,如果业务不需要浏览器内核,直接跳过。-qt-zlib系列表示用 Qt 自带的第三方库,避免和系统库版本冲突。-openssl-linked让网络模块静态链接 OpenSSL,减少运行时依赖。

提示:如果目标机器有 GPU 且需要 QtQuick 硬件加速,把-no-opengl换成-opengl es2,并确保装了对应的 Mesa 驱动。

3.3 编译与安装:make 的并行度与内存控制

configure 成功后,会生成 Makefile。接下来是漫长的编译过程。arm64 服务器通常核数不少,但内存可能有限。并行编译的-j参数不是越大越好:

# 查看 CPU 核数和内存 nproc free -h # 根据内存决定并行度:每核大约需要 1.5GB 内存 # 假设 8 核 16GB 内存,用 -j6 比较稳妥 make -j6 # 如果编译过程中因内存不足被 kill,降低并行度重试 make -j2 # 编译完成后安装到 prefix 目录 sudo make install

逻辑说明:Qt 编译时单个编译单元(尤其是qtdeclarative和qtlocation)可能吃掉 2GB 以上内存。如果-j设得过高,系统 OOM Killer 会直接杀掉编译进程,表现为make: *** [xxx] Killed。这时候不要怀疑代码有问题,就是内存不够。降到-j2甚至-j1重试即可。安装阶段用sudo是因为要写入/opt目录。

3.4 环境变量配置与 qmake 验证

安装完成后,需要把 Qt 的工具和库路径暴露给系统。在/etc/profile.d/下建一个脚本:

# /etc/profile.d/qt5.sh export QT_DIR=/opt/Qt5.12.8 export PATH=$QT_DIR/bin:$PATH export LD_LIBRARY_PATH=$QT_DIR/lib:$LD_LIBRARY_PATH export QT_PLUGIN_PATH=$QT_DIR/plugins export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_DIR/plugins/platforms

保存后source /etc/profile.d/qt5.sh,然后验证:

qmake -v # 应输出:QMake version 3.1 # Using Qt version 5.12.8 in /opt/Qt5.12.8/lib # 编译一个最小测试程序 mkdir -p /tmp/qttest && cd /tmp/qttest cat > main.cpp << 'EOF' #include <QCoreApplication> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qDebug() << "Qt version:" << QT_VERSION_STR; return 0; } EOF qmake -project qmake make ./qttest

如果输出Qt version: 5.12.8,说明编译产物完全可用。这一步是分水岭:过了,后面业务代码直接编;不过,回去检查LD_LIBRARY_PATH和qmake的路径优先级。

4. 避坑与排查:arm64 麒麟编译 Qt 的五个翻车现场

4.1 现象:configure 报 “ERROR: Feature ‘xcb’ was enabled, but the pre-condition failed”

原因:缺少 X11 相关的开发库,或者pkg-config找不到xcb的.pc文件。麒麟的包名和通用 Ubuntu 略有差异,有时候装了libxcb1-dev但没装libxcb-xinerama0-dev。

解决:先跑pkg-config --exists xcb && echo ok确认。如果失败,用apt-file search xcb.pc找到对应的开发包名,补装。实在不行,在 configure 时加-no-xcb跳过 X11 支持,但那样只能编控制台程序。

4.2 现象:编译到qtbase/src/corelib时报 “internal compiler error: Segmentation fault”

原因:GCC 版本过高(9.x)与 Qt 5.12.8 的模板代码不兼容,触发编译器自身崩溃。这不是 Qt 代码的问题,是编译器 bug。

解决:装gcc-8和g++-8,然后在 configure 时指定:

./configure ... QMAKE_CC=gcc-8 QMAKE_CXX=g++-8 QMAKE_LINK=g++-8

如果系统没有 gcc-8 的包,可以从源码编一个,或者用update-alternatives把默认 gcc 切到 7.x。

4.3 现象:make install后qmake -v显示的路径不对,或者版本还是系统的旧版

原因:PATH里/usr/bin排在/opt/Qt5.12.8/bin前面,系统优先找到了旧版 qmake。

解决:检查which qmake的输出。如果是/usr/bin/qmake,调整PATH顺序,把 Qt 的 bin 目录放到最前面。或者直接在业务项目的 Makefile 里写绝对路径/opt/Qt5.12.8/bin/qmake,避免环境变量污染。

4.4 现象:运行编译好的 Qt 程序时报 “This application failed to start because no Qt platform plugin could be initialized”

原因:QT_QPA_PLATFORM_PLUGIN_PATH没设,或者plugins/platforms/libqxcb.so依赖的库缺失。用ldd查:

ldd /opt/Qt5.12.8/plugins/platforms/libqxcb.so | grep "not found"

解决:缺什么补什么。常见的是缺libxcb-xinerama.so.0,装libxcb-xinerama0即可。另一个原因是QT_PLUGIN_PATH指向了错误的目录,确保它指向$QT_DIR/plugins。

4.5 现象:编译业务代码时链接报 “undefined reference to `QChart::QChart()’”

原因:QtCharts 模块在 configure 时被跳过了,或者QT += charts没写进.pro文件。

解决:检查$QT_DIR/include/下有没有QtCharts目录。如果没有,说明编译时-skip qtcharts了,需要重新 configure 并加上该模块。如果有目录但链接失败,在.pro里加QT += charts,然后重新qmake && make。

5. 进阶用法:把编译产物做成可迁移的离线部署包

编译一次,到处运行,这才是源码编译的终极价值。但直接tar整个/opt/Qt5.12.8拷到另一台机器,往往会因为路径硬编码而翻车。Qt 的qmake生成的 Makefile 里会写死-I/opt/Qt5.12.8/include这样的绝对路径。如果目标机器上 Qt 装在别的位置,编译就断了。

我一般会做两件事。第一,在打包前用sed批量替换安装目录里的硬编码路径:

# 把 /opt/Qt5.12.8 替换成相对路径或目标路径 cd /opt/Qt5.12.8 grep -rl "/opt/Qt5.12.8" . | while read f; do sed -i 's|/opt/Qt5.12.8|$QT_DIR|g' "$f" done

但这样会破坏二进制文件,所以更稳妥的做法是:目标机器上把 Qt 解压到相同路径/opt/Qt5.12.8,然后用一个启动脚本动态设置环境变量。这样不需要改任何文件。

第二,写一个qt-env.sh随包分发:

#!/bin/bash # qt-env.sh - 离线 Qt 环境激活脚本 export QT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" export PATH="$QT_DIR/bin:$PATH" export LD_LIBRARY_PATH="$QT_DIR/lib:$LD_LIBRARY_PATH" export QT_PLUGIN_PATH="$QT_DIR/plugins" export QT_QPA_PLATFORM_PLUGIN_PATH="$QT_DIR/plugins/platforms" echo "Qt 5.12.8 environment activated: $QT_DIR"

把这个脚本放在 Qt 目录的根下,目标机器上source qt-env.sh就能用。业务代码编译时,用$QT_DIR/bin/qmake生成 Makefile,链接的库路径会自动指向当前目录。

验证迁移是否成功,跑一个带界面的最小程序:

# 测试图形界面和插件加载 cat > /tmp/qtwidget_test.cpp << 'EOF' #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label("Qt 5.12.8 on Kylin arm64 OK"); label.show(); return app.exec(); } EOF cd /tmp $QT_DIR/bin/qmake -project $QT_DIR/bin/qmake make ./qtwidget_test

如果窗口正常弹出,说明平台插件、字体、X11 依赖全部就位。如果报错,用QT_DEBUG_PLUGINS=1 ./qtwidget_test看插件加载日志,里面会明确告诉你缺哪个.so。

从那以后我每次交付前,都会在目标机器上强制走一遍这个最小界面测试,确认插件路径和库依赖没问题再部署业务程序。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询