简介:本资源面向在国产化平台上进行 Qt 开发的工程师与信创项目适配人员,提供在 Kylin-Server-10-SP2-Release-Build09-20210524 arm64 系统上编译完成的 Qt 5.12.8 头文件集合,可直接用于交叉编译、二次开发或环境搭建时补齐缺失的 Qt 头文件依赖。压缩包为 gz 格式,共约 2000 个文件,全部为 .h 头文件,整体约 65.91MB,涵盖 QLocale、QOpenGL 系列函数、Valgrind 调试支持、QUrl 顶级域名等模块的声明,便于按需检索与集成。目前已有 251 人学习下载,适合需要快速获取麒麟 arm64 平台 Qt 头文件、避免重复编译的开发者参考使用。
1. 麒麟系统上把 Qt 5.12.8 从源码啃下来:为什么值得折腾
在 Kylin-Server-10-SP2-Release-Build09-20210524-arm64 这套国产化服务器环境里,系统自带的 Qt 版本往往停在 5.6 或 5.9,而不少工业上位机、组态软件、串口调试工具已经明确要求 qt5.12.8。直接apt install qt5-default拿到的版本对不上,跑起来不是缺QtWebEngine就是libQt5SerialPort符号版本冲突。更现实的问题是,arm64 架构下官方预编译包几乎找不到,能搜到的多是 x86_64 的二进制,硬塞进去只会报bad linux arm64 image magic这类让人头皮发麻的错误。所以在这台麒麟服务器上,从源码编译 qt5.12.8 基本是绕不开的一步。这篇笔记面向的是手里已经有一台麒麟 arm64 机器、需要把 Qt 开发环境搭起来、并且愿意花两三个小时跟编译错误死磕的工程师。我会把依赖怎么补、configure 参数怎么选、编译卡住时看哪里、装完怎么验证,按我实际踩过的顺序讲清楚。
2. 编译前的环境盘点与依赖补齐
2.1 先确认系统里到底缺什么
麒麟 SP2 基于较新的内核和 glibc,但默认软件源里的开发包并不完整。编译 Qt 5.12.8 之前,先把基础工具链和图形库依赖过一遍。我一般会先跑下面这几条命令看现状,而不是上来就make,否则报错会像雪片一样飞来。
# 查看系统版本和架构,确认是 aarch64 而不是 x86_64 uname -m cat /etc/kylin-release # 检查 gcc/g++ 版本,Qt 5.12.8 对 gcc 7 以上支持较好 gcc --version g++ --version # 查看是否已有 Qt 相关包,避免和系统自带冲突 rpm -qa | grep -i qt5逻辑说明:uname -m输出aarch64才说明是 arm64 环境,如果输出x86_64那后面所有 arm64 相关的参数都要重新考虑。rpm -qa | grep qt5是为了确认系统里有没有预装 Qt5 的运行库或开发包,如果有,编译前最好先记录版本,装完新版本后通过LD_LIBRARY_PATH或qtchooser切换,而不是直接卸载系统包,否则可能影响桌面环境。
参数说明:麒麟服务器版默认可能没有安装gcc-c++,如果g++ --version报 command not found,需要先yum install gcc-c++。另外make建议用make -j$(nproc),但第一次编译 Qt 时我建议先单线程跑一小段确认没有配置错误,再开多线程。
2.2 一次性补齐编译依赖
Qt 5.12.8 的依赖分几类:基础编译工具、X11 相关、字体与图像、数据库驱动、多媒体。在麒麟 arm64 上,下面这条命令是我验证过能覆盖绝大部分场景的依赖安装方式。
# 以 root 或 sudo 执行,安装编译 Qt 所需的核心依赖 yum install -y gcc-c++ make perl python3 \ libxcb libxcb-devel xcb-util xcb-util-devel \ libX11-devel libXext-devel libXrender-devel \ fontconfig-devel freetype-devel \ libpng-devel libjpeg-turbo-devel \ openssl-devel sqlite-devel \ alsa-lib-devel pulseaudio-libs-devel \ mesa-libGL-devel mesa-libGLU-devel \ libinput-devel mtdev-devel \ dbus-devel glib2-devel逻辑说明:libxcb系列是 Qt GUI 在 Linux 上跑起来的关键,缺了会在 configure 阶段报xcb找不到。fontconfig和freetype负责字体渲染,没有它们编译出的 Qt 程序界面文字会变成方块。openssl-devel影响网络模块,sqlite-devel影响 QtSql。alsa-lib和pulseaudio是多媒体模块的依赖,如果不需要 QtMultimedia 可以在 configure 时用-skip qtmultimedia跳过,但依赖先装上不亏。
参数说明:-y表示自动确认。如果麒麟源里某个包名和 CentOS 略有差异,比如libjpeg-turbo-devel可能叫libjpeg-devel,用yum provides "*/jpeglib.h"反查一下即可。这一步不要偷懒,依赖缺一个,后面 configure 就会失败一次,来回折腾更费时间。
提示:如果公司内网源不全,可以临时挂载麒麟 ISO 作为本地源,或者从同版本 arm64 的 CentOS 源里找对应包,但要注意 glibc 版本兼容性。
3. 源码获取与 configure 参数怎么定
3.1 拿到 qt5.12.8 源码并解压
Qt 5.12.8 的源码包在官方归档里可以找到,文件名通常是qt-everywhere-src-5.12.8.tar.xz。在 arm64 机器上直接下载或从内网文件服务器拷贝都行。我一般放在/usr/local/src下操作。
# 进入源码目录,解压 qt-everywhere-src-5.12.8 cd /usr/local/src tar -xf qt-everywhere-src-5.12.8.tar.xz cd qt-everywhere-src-5.12.8 # 查看顶层目录结构,确认包含 qtbase、qtdeclarative 等子模块 ls -d qt*逻辑说明:qt-everywhere-src是完整源码包,包含 qtbase、qtdeclarative、qtmultimedia 等所有模块。如果只需要核心功能,也可以只编译 qtbase,但大多数项目会用到 QtWidgets 和 QtNetwork,所以完整编译更省心。解压后进入目录,ls -d qt*能看到所有子模块目录,说明源码完整。
参数说明:tar -xf会自动识别 xz 压缩。如果磁盘空间紧张,完整编译大约需要 15GB 以上临时空间,建议先df -h确认/usr/local所在分区有足够余量。
3.2 configure 参数逐项拆解
这是整个编译过程中最关键的一步。参数选错,要么编译到一半报缺库,要么装完发现需要的模块没编进去。下面是我在麒麟 arm64 上实际用过的 configure 命令。
# 在源码根目录执行 configure,生成 Makefile ./configure -prefix /opt/qt-5.12.8 \ -opensource -confirm-license \ -release -shared \ -nomake examples -nomake tests \ -no-opengl \ -qt-zlib -qt-libpng -qt-libjpeg \ -qt-freetype -qt-pcre \ -qt-xcb \ -skip qtwebengine \ -skip qtwayland \ -v逻辑说明:-prefix /opt/qt-5.12.8指定安装路径,我习惯放在/opt下,和系统自带的 Qt 隔离。-opensource -confirm-license表示使用开源协议并自动确认,避免交互式提问卡住脚本。-release -shared编译发布版动态库,体积和性能平衡较好。-nomake examples -nomake tests跳过示例和测试,能省下大量编译时间。-no-opengl在服务器环境下通常不需要 OpenGL,如果项目确实需要可以去掉这个参数,但要确保mesa-libGL-devel已装。-qt-zlib -qt-libpng -qt-libjpeg表示使用 Qt 自带的压缩和图像库,避免依赖系统版本差异。-qt-xcb使用 Qt 自带的 xcb 代码,减少对系统 xcb 版本的敏感度。-skip qtwebengine是因为 QtWebEngine 在 arm64 上编译极其耗时且容易失败,如果项目不需要浏览器内核,直接跳过。-skip qtwayland在服务器上通常用不到 Wayland。-v输出详细配置信息,方便排查。
参数说明:如果 configure 报错提示某个 xcb 库找不到,可以把-qt-xcb换成-xcb,让 Qt 链接系统 xcb,但前提是系统 xcb 开发包齐全。如果报ERROR: Feature 'fontconfig' was enabled, but the pre-condition 'libs.fontconfig' failed,说明fontconfig-devel没装好,回第 2 章补依赖。configure 成功后最后会输出一份配置摘要,重点看Build options和Qt modules两段,确认需要的模块是yes。
注意:configure 阶段如果看到
WARNING: QDoc will not be compiled之类的提示可以忽略,不影响核心功能。但如果看到ERROR就必须解决,不要强行make。
4. 编译过程与常见报错排查
4.1 启动编译与资源控制
configure 通过后,make就是体力活了。但 arm64 服务器核数多,直接make -j$(nproc)可能因为内存不足触发 OOM,尤其是编译 qtdeclarative 时单个进程可能吃掉 2GB 以上内存。
# 查看 CPU 核数和内存,决定并行编译任务数 nproc free -h # 根据内存情况选择并行数,16GB 内存建议 -j4 或 -j6 make -j4 2>&1 | tee build.log逻辑说明:nproc看核数,free -h看可用内存。经验公式是每 2GB 内存对应一个编译任务,比如 16GB 内存最多-j8,但 Qt 编译峰值较高,保守用-j4更稳。2>&1 | tee build.log把标准输出和错误都写到日志文件,同时屏幕也能看到进度,方便后面翻查报错。
参数说明:如果编译过程中看到virtual memory exhausted: Cannot allocate memory,说明并行数太高,中断后改用make -j2继续,已经编译过的目标不会重来。如果只是某个模块报错,可以进入该模块子目录单独make,比如cd qtbase && make,这样错误信息更集中。
4.2 几个高频报错的处理方式
第一个常见报错是Project ERROR: Unknown module(s) in QT: xcb。这通常是因为-qt-xcb参数下某些 xcb 子库源码没被正确包含,解决办法是确认qtbase/src/plugins/platforms/xcb目录存在,或者改用-xcb并确保系统xcb-util-devel已安装。
第二个是fatal error: openssl/ssl.h: No such file or directory。说明openssl-devel没装或头文件路径不对。用rpm -ql openssl-devel | grep ssl.h确认头文件位置,如果确实缺失就补装。
第三个是链接阶段报undefined reference to 'pthread_...'。这在 arm64 上偶尔出现,原因是部分模块没有显式链接 pthread。可以在qtbase/mkspecs/linux-aarch64-gnu-g++/qmake.conf里给QMAKE_LFLAGS加上-lpthread,然后重新 configure 和 make。
第四个是编译到qtdeclarative时卡死或报internal compiler error: Killed。这就是内存不足被 OOM Killer 杀了。解决办法是单独进入qtdeclarative目录,用make -j1慢慢编,或者临时增加 swap 分区。
第五个是qmake: could not find a Qt installation of ''。这通常发生在 configure 成功后直接运行qmake时,因为qmake还没安装到-prefix指定路径。需要先make install,或者用源码目录下的bin/qmake并设置LD_LIBRARY_PATH指向qtbase/lib。
提示:编译日志里搜
error:比搜Error更准,因为很多警告也带 Error 字样。定位到第一个真正的 error 后,往上翻 20 行看上下文,通常能看到缺失的头文件或库名。
5. 安装、环境变量与验证方法
5.1 执行安装并配置环境
编译完成后,make install会把所有文件复制到/opt/qt-5.12.8。这一步通常不会报错,但要注意权限。
# 安装到 prefix 指定目录 make install # 配置环境变量,写入 /etc/profile.d/qt-5.12.8.sh cat > /etc/profile.d/qt-5.12.8.sh << 'EOF' export QT_HOME=/opt/qt-5.12.8 export PATH=$QT_HOME/bin:$PATH export LD_LIBRARY_PATH=$QT_HOME/lib:$LD_LIBRARY_PATH export QT_PLUGIN_PATH=$QT_HOME/plugins export QML2_IMPORT_PATH=$QT_HOME/qml EOF # 使环境变量立即生效 source /etc/profile.d/qt-5.12.8.sh逻辑说明:make install把编译产物复制到/opt/qt-5.12.8。环境变量脚本放在/etc/profile.d下,所有登录用户都能生效。QT_PLUGIN_PATH指向插件目录,否则 Qt 程序运行时可能找不到平台插件,报This application failed to start because no Qt platform plugin could be initialized。QML2_IMPORT_PATH是 QML 模块路径,如果项目用 QML 就必须设。
参数说明:LD_LIBRARY_PATH把 Qt 库路径放在系统库前面,避免链接到系统自带的旧版本 Qt。如果只想对当前用户生效,可以把脚本放到~/.bashrc里。注意不要覆盖系统原有的LD_LIBRARY_PATH,这里用:$LD_LIBRARY_PATH追加。
5.2 验证 qt5.12.8 是否可用
装完不验证,等于没装。我一般用三步确认:qmake 版本、编译一个最小 QtWidgets 程序、检查关键模块。
# 确认 qmake 版本和安装路径 which qmake qmake -v # 写一个最小 Qt 程序测试编译和运行 mkdir -p /tmp/qt-test && cd /tmp/qt-test cat > main.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 # 生成工程文件并编译 qmake -project qmake make逻辑说明:qmake -v应该输出QMake version 3.1和Using Qt version 5.12.8,如果版本不对说明 PATH 里找到的是系统旧 qmake。最小程序用QLabel验证 QtWidgets 模块是否正常。qmake -project自动生成.pro文件,qmake生成 Makefile,make编译。如果编译通过,说明头文件和库路径都正确。
参数说明:运行程序时如果报cannot connect to X server,说明当前是纯命令行环境没有图形显示,可以用QT_QPA_PLATFORM=offscreen ./qt-test做无界面验证。如果报缺libQt5Widgets.so.5,检查LD_LIBRARY_PATH是否包含/opt/qt-5.12.8/lib。
注意:麒麟服务器版默认可能没有安装 X11 显示服务,如果只是做后台服务开发,用
offscreen平台插件验证即可,不需要额外装桌面环境。
6. 几个只有实际编译过才会遇到的坑
6.1 系统自带 Qt 和新装 Qt 的冲突
现象:装完 qt5.12.8 后,运行qmake -v仍然显示系统自带的 5.9 版本,或者编译程序时链接到了/usr/lib64下的旧库。
原因:PATH和LD_LIBRARY_PATH的优先级问题,或者系统里存在/usr/bin/qmake的符号链接指向旧版本。
解决:用which -a qmake列出所有 qmake 路径,确认/opt/qt-5.12.8/bin/qmake排在第一位。如果/usr/bin/qmake是符号链接,不要直接删除,而是调整PATH顺序,或者在项目.pro文件里用QMAKE = /opt/qt-5.12.8/bin/qmake显式指定。
6.2 编译到 qtbase 时 xcb 报错反复出现
现象:configure 时加了-qt-xcb,但 make 到 qtbase 的 xcb 插件时仍然报xcb-xkb.h找不到。
原因:-qt-xcb只包含部分 xcb 库源码,xcb-xkb需要系统提供开发头文件。
解决:安装libxcb-devel和xcb-util-devel后,把 configure 参数改为-xcb而不是-qt-xcb,让 Qt 链接系统 xcb。如果系统 xcb 版本太旧,可以从源码编译新版 xcb 装到/usr/local,再在 configure 时加-I/usr/local/include -L/usr/local/lib。
6.3 编译 qtdeclarative 时内存爆掉
现象:make -j8跑到 qtdeclarative 模块时进程被 killed,日志显示Killed或internal compiler error。
原因:qtdeclarative 里的 QML 引擎代码模板展开后单个编译单元极大,g++ 内存占用飙升。
解决:单独进入qtdeclarative目录,用make -j1编译,或者临时增加 4GB swap。如果服务器内存实在紧张,可以在 configure 时加-skip qtdeclarative,但这样就没有 QML 支持了,需要根据项目实际需求权衡。
6.4 安装后程序运行报找不到平台插件
现象:编译好的 Qt 程序运行时报This application failed to start because no Qt platform plugin could be initialized。
原因:QT_PLUGIN_PATH没设置,或者plugins/platforms/libqxcb.so依赖的库缺失。
解决:确认/opt/qt-5.12.8/plugins/platforms/下有libqxcb.so。用ldd libqxcb.so检查依赖是否全部满足,常见缺失是libxcb-xinerama.so.0,补装xcb-util-xinerama即可。然后在环境变量里设置export QT_DEBUG_PLUGINS=1再运行程序,会打印插件加载的详细过程,定位到具体缺哪个库。
6.5 arm64 上 qmake 生成的 Makefile 链接参数不对
现象:编译项目时链接阶段报relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol ... can not be used when making a shared object。
原因:部分第三方库编译时没有加-fPIC,在 arm64 上链接共享库时对地址重定位要求更严格。
解决:确保所有依赖库都用-fPIC编译。对于 Qt 自身,configure 时加-force-pkg-config有时能改善。如果问题出在项目自己的代码,在.pro里加QMAKE_CXXFLAGS += -fPIC和QMAKE_LFLAGS += -fPIC。
7. 把 qt5.12.8 装进麒麟 arm64 之后还能做什么
编译完成只是第一步,真正让这套环境产生价值的是后续的交叉编译和部署。我习惯在/opt/qt-5.12.8装好之后,立刻做两件事:一是用qmake -query导出所有关键路径,写进项目的.pro或 CMake 工具链文件,这样团队里其他人不用重复猜路径;二是用linuxdeployqt或手动脚本把 Qt 程序依赖的库打包成独立目录,方便部署到没有装 Qt 的麒麟机器上。
# 导出 Qt 关键路径,方便写 CMake 工具链 qmake -query # 查看程序依赖的 Qt 库,确认没有链接到系统旧版本 ldd ./qt-test | grep Qt5逻辑说明:qmake -query会输出QT_INSTALL_PREFIX、QT_INSTALL_LIBS、QT_INSTALL_HEADERS等变量,把这些填进 CMake 的find_package(Qt5 ...)或CMAKE_PREFIX_PATH里,比硬编码路径可靠。ldd检查最终二进制链接的 Qt 库路径,如果出现/usr/lib64/libQt5Core.so.5而不是/opt/qt-5.12.8/lib/libQt5Core.so.5,说明运行时链接有问题,需要检查RPATH或LD_LIBRARY_PATH。
参数说明:如果项目用 CMake,在CMakeLists.txt里加set(CMAKE_PREFIX_PATH "/opt/qt-5.12.8")即可。如果希望二进制自带RPATH,在链接时加-Wl,-rpath,/opt/qt-5.12.8/lib,这样部署到其他机器只要库在相同路径就能跑。
还有一个进阶技巧是保留一份 configure 命令和 build.log。麒麟系统后续如果打补丁或升级 glibc,可能需要重新编译 Qt。把configure参数存成configure-qt5.12.8.sh,把build.log留着,下次重编时直接跑脚本,遇到相同报错翻旧日志,能省下大量回忆时间。我在第一次编译时没存日志,第二次遇到xcb-xkb报错又从头查了一遍,这个后悔药后来一直备着。
最后说一个验证编译质量的小方法:用QT_DEBUG_PLUGINS=1跑一个带界面的程序,看插件加载日志里有没有Cannot load字样。如果没有,说明平台插件、图像格式插件、字体插件都正常。这个习惯帮我在项目上线前发现过libqjpeg.so缺失导致图片无法显示的问题。希望帮到你。
本文还有配套的精品资源,点击获取