简介这份资源面向使用 Kylin-Desktop-V10-GFB-Release-020-ARM64 系统的 Qt 开发人员是一份 Lenovo 适配的 QT 5.12.10 预编译环境已在国产飞腾/鲲鹏平台上验证可用。它重点解决 ARM64 环境下从源码编译 Qt 耗时较长、依赖项缺失、工具链配置繁琐等现实问题特别适合昭阳 N4720Z 一类联想国产化终端上的应用开发与调试。资源包压缩后大小约 84.62MB共包含 2000 个文件主体是 Qt 的头文件覆盖 qopengl、qlocale、qurltlds 等常用模块的接口声明便于编译时进行 API 查阅与代码提示由于包体相对精简可直接拷贝到 /opt 目录使用。与从源码构建相比它已提前完成库文件整理与版本校验解压后在 Qt Creator 中指向对应 qmake 即可被识别大幅度缩短国产化平台上的环境搭建时间。该版本已在对应麒麟系统上实测可用目前已有 1065 人学习下载适合正在做国产化迁移或 ARM64 应用适配的团队直接参考和复用。1. 项目背景与核心思路1.1 为什么要在麒麟V10 ARM64上重新编译QT先交代一下我这次做的事。项目标题写得很直白Kylin-Desktop-V10-GFB-Release-020-ARM64在联想Lenovo机型上完成QT5.12.10的源码编译。这几年国产化平台的适配需求越来越普遍麒麟V10作为桌面级国产操作系统在政务、金融、能源等行业的装机量不小。而QT是在Linux下做GUI应用最主流的选择很多业务系统、自研软件、工控界面都是基于QT开发的。但有个现实问题系统自带的QT版本往往不是你想要的版本或者默认安装的版本缺少某些模块、补丁、编译选项没法直接满足项目需求。我这次遇到的场景就是典型目标机器是联想某款基于ARM架构的台式机系统镜像版本是Kylin-Desktop-V10-GFB-Release-020-ARM64需要在这个环境上跑一个依赖QT 5.12.10的存量项目。系统仓库里的qt版本不是太高就是太低直接拿来用根本不合适于是只能自己做源码编译。这基本是所有做国产化适配的开发者绕不开的一条路拿到机器装好系统评估环境然后自己编译依赖库。这篇文章就是把整个过程记录下来包括环境准备、configure参数配置、编译参数选择、打包部署以及中间踩过的几个比较典型的坑。如果你正好在处理麒麟V10 ARM64上的QT适配这篇文章能帮你少走很多弯路。1.2 ARM64平台的编译特点ARM64也叫AArch64和x86_64相比在编译这件事上有几个明显区别做之前得先有数目标架构不同编译出来的库、可执行文件都是ARM64格式只能在ARM机器上跑x86机器跑不了。指令集差异某些代码里包含x86特有的内联汇编、SSE指令在ARM平台编译会报错需要修改或替换实现。第三方库依赖很多依赖库需要从源码编译不能直接复用x86的二进制包。麒麟V10基于Ubuntu生态APT源里虽然有很多ARM64的包但某些特定版本并不一定有。性能差距ARM平台编译速度比同价位的x86慢不少尤其是纯软件编译大项目时差距更明显要有心理准备。这里面最有意思的是第三点——依赖库的可用性。麒麟系统的软件源虽然能用但里面默认的QT版本和GCC版本可能跟你预期的不一样。比如这次我编译QT 5.12.10系统默认GCC是9.x而QT 5.12.10在部分GCC版本下会有编译告警甚至错误需要针对性处理。2. 编译前的环境准备2.1 系统版本与基础软件确认首先确认系统基础信息。用下面这三条命令打开局面uname -a cat /etc/os-release gcc --version我这次的实际输出大致是Linux kylin 4.19.0-9-desktop #9 SMP ... aarch64 aarch64 aarch64 GNU/Linux Kylin V10 SP1GFBRelease 020 gcc (kylin 9.3.0-11) 9.3.0注意uname -a里明确写了aarch64这确认了架构。另外GFB版本是“国防版”的缩写这类定制系统在软件源、预装软件上可能跟通用版有所不同但基础编译环境大同小异。接着检查编译工具链是否齐全which make which cmake which g ld --version如果发现make或g缺失直接用麒麟的软件源安装sudo yum install -y make gcc-c # 麒麟V10通用版和GFB版目前用yum/dnf都能装2.2 依赖库安装QT编译需要的依赖包不少核心的是这几个大类字体渲染freetype/fontconfig、图形基础libxcb系列、OpenGL相关mesa-libGL等、输入设备libudev、libinput、GTK平台插件可选以及压缩库zlib/libpng。麒麟V10的软件源里这些包基本都有直接用yum安装。我这次实际执行的是sudo yum install -y libxcb-devel xcb-util-devel xcb-util-image-devel \ xcb-util-keysyms-devel xcb-util-wm-devel xcb-util-renderutil-devel \ freetype-devel fontconfig-devel libpng-devel zlib-devel \ mesa-libGL-devel mesa-libEGL-devel libxkbcommon-devel \ libxkbcommon-x11-devel libudev-devel libinput-devel \ libdrm-devel libgbm-devel这些包分别是做什么的简单对应一下libxcb系列X11的C接口封装QT的xcb平台插件必须用缺失会导致编译出来的QT跑不起来。freetype/fontconfig字体渲染核心库没有它们QT界面上的中文全变豆腐块。mesa-libGL/mesa-libEGLOpenGL基础库影响QML、GPU加速渲染和窗口合成。libxkbcommon键盘事件映射缺失会导致输入异常或者编译xcb插件直接报错。注意如果你的机器显卡比较特殊特别是国产显卡、集成显卡可能还需要额外装一些驱动相关的开发包否则到了运行时阶段会出现“无法创建OpenGL上下文”的错误。这个后面在排查章节细说。2.3 确定安装路径与规划安装路径我一律推荐装到/opt/Qt5.12.10这种独立目录不要直接塞进系统目录。原因很现实后续升级、卸载、多版本共存都方便而且不会污染系统自带的QT万一系统组件依赖旧版QT呢。另外考虑到之后可能要部署到多台机器上路径统一很关键。如果每台机器安装路径不一致QT程序找库的路径rpath就会乱套。我这次统一规划为源码目录/data/build/qt-everywhere-src-5.12.10安装前缀/opt/Qt5.12.10配置文件目录/opt/Qt5.12.10/conf编译后手动创建源码包到QT官网下载或者从国内镜像站拉取。QT 5.12.10的源码包名是qt-everywhere-src-5.12.10.tar.xz体积大约是500MB左右下载解压后用md5校验一下完整性。wget https://download.qt.io/archive/qt/5.12/5.12.10/single/qt-everywhere-src-5.12.10.tar.xz tar -xf qt-everywhere-src-5.12.10.tar.xz -C /data/build/ cd /data/build/qt-everywhere-src-5.12.10提示如果你是在Windows上下载再传到Linux记得检查压缩包是否损坏。我见过很多次传了一半导致解压失败的案例校验md5是省时间的好习惯。3. configure配置与编译参数精细调优3.1 configure配置项的取舍QT源码包解压以后正式编译前的关键一步是执行configure脚本。这个脚本会检查编译环境、依赖库是否齐全然后生成Makefile和qmake配置。我这次用的是如下配置./configure -prefix /opt/Qt5.12.10 \ -release -opensource -confirm-license \ -shared \ -nomake examples -nomake tests \ -xcb -xcb-xlib \ -system-freetype -system-libpng -system-zlib \ -no-openssl \ -no-cups -no-nis \ -skip qtwebengine -skip qtwebchannel \ -qt-xcb逐项解释一下我为什么这么选-release编译release版本不要debug。生产环境和业务部署用debug毫无意义而且debug版本体积大、运行慢。-opensource -confirm-license确认LGPL开源许可商用也没问题关键是不能改QT本身源码后又闭源分发。-shared编译器链接动态库。业务程序部署时动态库方便替换如果某个库有patch只需要替换对应.so即可不用重新编译整个程序。-nomake examples -nomake tests不编译示例和测试代码省至少20%编译时间。-xcb -qt-xcb启用xcb平台插件同时用QT自带的xcb库。麒麟V10是X11桌面环境xcb就是QT跟显示服务器之间通信的桥梁。这个选项不加编译出来的QT无法在X11桌面下启动GUI程序。-system-freetype -system-libpng -system-zlib这些库使用系统版本而不是QT自带的。原因很直接系统库有安全补丁升级方便也能减小QT的体积。-no-openssl禁用OpenSSL。如果你的业务不需要HTTPS通信或加密传输这块可以关掉省去编译OpenSSL的开发包依赖。-skip qtwebengine跳过WebEngine模块。这是QT里面最庞大的模块自带Chromium内核编译它单独都需要一两个小时而且在国产平台环境下还经常出编译错误。多数业务系统用不到浏览器功能跳过省时省力。-no-cups -no-nis禁用打印和旧式NIS目录服务都是咱们业务用不到的东西。3.2 关于交叉编译与本地编译的选择这部分要单独强调一下这次是本地编译不是交叉编译。区别是本地编译是指在麒麟ARM64机器上直接编译生成目标平台代码编译工具链跑在同一台机器上交叉编译是指在x86机器上用交叉编译工具链比如aarch64-linux-gnu-gcc编译ARM64目标代码。为什么这很重要因为很多新手一搜教程出来的全是交叉编译的内容尤其关键词里还有 “qt5.12.10交叉编译”容易让人走偏。实际上如果你手里已经有麒麟ARM64的实机或有一定性能的ARM虚拟机本地编译是最稳、最简单的方式省去了交叉编译工具链的配置、sysroot管理、跨平台依赖等一堆麻烦。我这次选择本地编译还有一个现实考量麒麟V10自带的GCC 9.3.0本身就是aarch64版本直接编译出来的库保证跟系统完全兼容不会出现跨版本glibc不兼容的问题。如果你是批量交付项目且没有实机环境再去研究交叉编译也不迟但原理和依赖处理会复杂一个量级。3.3 编译与安装configure完成后正式编译。ARM64机器上编译QT是个考验耐心的活尤其GTX这种显卡的机器还好如果是ARM处理器的整机时间会明显拉长。我这次实测在4核8GB的ARM整机上完整编译大概花了1个多小时如果在性能更好的机器上比如飞腾D2000或者麒麟990时间能压到40分钟左右。make -j4-j4表示4个编译任务并行。不要盲目调高并行数内存不够的话会直接OOM。8GB内存的机器-j4比较安全16GB可以用-j8。编译期间可能遇到各种报错我后面会专门讲问题排查。一切顺利的话编译结束后执行安装make install安装完成后QT就部署到了 /opt/Qt5.12.10 目录下。可以看到bin、lib、qml、plugins等子目录。验证是否成功先看版本号/opt/Qt5.12.10/bin/qmake --version能看到QMake version 3.1、Using Qt version 5.12.10这样的输出基本就说明安装到位了。4. 核心环节的验证与多进程场景实测4.1 写个最小程序验证编译链安装完成只在“装好了”的意义上成立。真正要确认QT能干活需要编译一个测试程序。我习惯写一个带中文界面的最小QT程序验证三件事编译是否通过、程序能否启动、中文渲染是否正常。创建 test.pro 文件QT widgets TARGET test TEMPLATE app SOURCES main.cpp创建 main.cpp#include QApplication #include QLabel int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label(麒麟QT编译测试); label.resize(240, 80); label.show(); return app.exec(); }编译/opt/Qt5.12.10/bin/qmake test.pro make这时应该会生成名为test的可执行文件运行它./test如果是桌面环境里执行或者通过远程桌面应该能看到窗口出现上面显示“麒麟QT编译测试”。这一步非常重要因为很多QT编译问题不是编译时暴露的——编译出来很顺利运行阶段却直接段错误或者找不到平台插件。所以写完编译做完只是一半跑起来才是完整闭环。4.2 多进程并发编译的稳定性测试因为业务里有一个后台任务队列经常要同时启动多个QT程序实例来处理数据所以我还用写好的测试程序做了一个简单的并发验证同时启动10个进程每个进程运行3秒退出循环3轮。for i in {1..10}; do ./test done; wait跑了几轮下来没有出现崩溃、卡死、窗口抢资源的问题。说明QT基本库和xcb平台插件在麒麟V10 ARM64上是稳定的。如果是GUI程序这种并发验证还能提前发现X11连接资源耗尽之类的隐患。4.3 部署到其他机器时的依赖收集编译好的程序要部署到其他没有装QT的机器上需要带上依赖的动态库。这一步可以说是国产化部署时最容易出问题的地方。有一台机器程序编译出来多大就在多大机器上复制不行因为依赖库不在目标机上。我用的是ldd命令查看依赖关系ldd ./test | grep -E Qt|not found输出会比较长这里不去逐行贴。关键是找出哪些QT库需要一起带上。一般情况下test程序依赖libQt5Core.so.5、libQt5Gui.so.5、libQt5Widgets.so.5以及平台插件libqxcb.so这个在QT安装目录的plugins/platforms下面。把这些库和插件打包到一起分发放到目标机之后用LD_LIBRARY_PATH指定库路径export LD_LIBRARY_PATH/opt/Qt5.12.10/lib:$LD_LIBRARY_PATH更稳健的做法是用QT自带的linuxdeployqt工具自动收集依赖但这个工具在ARM64上有时不太灵光。我一般是写个小脚本手动把关键库拷贝到部署目录。为了省事也可以直接用rsync把整个 /opt/Qt5.12.10/lib 和 plugins 目录同步到目标机器虽然体积大一点但胜在心里踏实。5. 常见问题与排查实录5.1 configure检查报错缺少 xcb 相关开发包这个报错出现概率极高症状是configure过程中提示找不到 xcb-xlib.h 或者 xcb/util-keysyms.h 之类的头文件。原因就是前面说的一堆 xcb 开发包没装全。解决方式sudo yum install -y xcb-util-devel xcb-util-image-devel \ xcb-util-keysyms-devel xcb-util-wm-devel装完重新执行configure它会重新检测。这里有个小技巧configure的检测结果会有缓存吗其实没有重新跑一遍configure必须删掉之前生成的config.cache文件再执行否则它拿以前的检测结果直接跳过。rm -f config.cache ./configure ...5.2 编译时提示 “undefined reference todlopen”这个是比较典型的链接错误常见于老版本GCC搭配新版本glibc的情况但在ARM平台也不少见。本质上是因为程序链接时缺少-ldl参数。解决办法分两个层面一是configure时给QT加上额外的qmake变量把dl库手动连上./configure -prefix /opt/Qt5.12.10 ... QMAKE_LIBS-ldl二是在编译生成自己的代码时如果遇到同样问题在 .pro 文件里手动加LIBS -ldl5.3 编译QML相关模块时报 “unknown module(s) in QT: qml”这通常不是QT本身的问题而是你只编译了QtWidgets部分或者部分模块被跳过了。检查configure时的输出是否已经成功识别qml模块。如果没识别到通常是依赖库缺失比如libxkbcommon-dev没有装。另一种可能configure设置里用了-skip qtdeclarativeQML模块的名字回头需要去掉这个skip项重新编译。5.4 运行时提示 “could not find or load the Qt platform plugin xcb”这是部署阶段最常见的错误。程序能正常编译但放到别的机器上运行时返回这个错误。原因很简单QT找不到对应平台插件libqxcb.so或者xcb插件的依赖库在目标机不存在。解决办法确认libqxcb.so存在/opt/Qt5.12.10/plugins/platforms/libqxcb.so。设置环境变量export QT_QPA_PLATFORM_PLUGIN_PATH/opt/Qt5.12.10/plugins/platforms如果还不行用ldd检查libqxcb.so在目标机的依赖是否都满足ldd /opt/Qt5.12.10/plugins/platforms/libqxcb.so看到not found的字样就说明目标机缺库用yum或直接拷贝补上。我记得有一次碰到的case就是目标机上缺了libxkbcommon-x11.so.0拷贝过去立马就好了。5.5 编译速度比预期慢太多ARM机器编译慢是常态但如果你觉得慢得离谱八成是并行度没调好。看看CPU有几个核再比一下内存。合理配置并行数能节省大量时间nproc # 查看逻辑核数 free -h # 查看内存一般来说4核4GB-j24核8GB-j48核16GB-j6或-j8超出内存承受能力去提高并行度编译器进程互相挤内存swap开始大量读写速度反而更慢。5.6 中文显示成方块编译和运行都正常就是界面上中文全部变成方块或者乱码。这类问题多半是字体配置缺失而不是QT本身的问题。先看系统里有没有中文字体fc-list :langzh如果输出为空安装中文字体sudo yum install -y wqy-zenhei-fonts wqy-microhei-fonts装完后运行程序通常就正常了。另外如果程序用了QSS设置了固定的font-family要确保那个字体在系统里存在否则回车自动选替代字体效果不可控。5.7 GL相关的诡异问题窗口黑屏、渲染错误如果ARM机器上显卡驱动不完整有时候QT程序窗口能弹出来但内容是黑的或者QML界面渲染错误。检查当前使用的图形平台export QT_DEBUG_PLUGINS1 ./test这样启动时会打印所有平台插件的加载日志能看出来是不是GL初始化失败。解决办法是降级渲染方式比如强制使用软件渲染export QT_QT_QUICK_BACKENDsoftware export QT_OPENGLsoftware如果只是临时验证也可以加-platform xcb参数。但如果目标环境以后要长期跑QML/3D应用建议还是把显卡驱动搞定软件渲染的性能损失在ARM平台上非常明显。6. 关于“Lenovo版本”的适配差异标题里特意写了“Lenovo版本”这意味着目标机器是联想整机。联想在国产化整机里比较常见的是搭载飞腾Phytium或者麒麟Kylin处理器的型号。这类整机的系统镜像虽然还是麒麟V10但部分BSP板级支持包、内核补丁、固件与通用版可能不同。从实际操作来看最可能踩的坑有这几个方向第一内核版本差异。有些联想机型用的内核开启了特定选项或补了特定的硬件驱动这会影响某些系统库的ABI兼容性。不过QT作为用户态软件只要遵循系统库依赖规则一般不受影响。第二显卡驱动差异。联想整机有可能用AMD或国产显卡比如景嘉微这些显卡在Linux下的驱动成熟度参差不齐。如果编译QT后运行窗口一直黑屏或渲染错乱优先级最高的事是去查显卡驱动是否加载、GL扩展是否可用而不是怀疑QT没编好。第三预装软件冲突。有的联想整机出厂的系统镜像里预装了自家定制的QT版本环境变量、路径可能已经有了残留配置。比如 /etc/profile.d/ 下可能有特定脚本设置了QT_QPA_PLATFORM 或者 QTDIR。这种情况先env | grep -i qt看看环境变量该清理就清理。我在另一台联想ARM整机上还遇到过一个问题系统镜像的软件源里某个依赖包的版本比较老跟QT编译要求的最低版本有差距。解决方式是回退QT的某个特性或者在configure里关闭对应模块没必要因为一个依赖跟系统干到底。7. 个人实操中的体会与扩展建议整套流程走下来我对国产平台上做QT开发适配的最大感触是编译本身不可怕可怕的是环境不透明。麒麟V10实际上是一个经过了深度定制的系统虽然有Ubuntu/Debian的血统但你不能完全用Ubuntu的思维去看待它。软件源里某些包版本可能跟上游不一致某些开发库默认没装全甚至部分包的名称就有出入。所以遇到编译问题先查环境再查代码最后才是查QT本身的bug。另外我强烈建议做这一步之前先把系统快照做好。不管是虚拟机还是物理机装完依赖库、编译完QT之后环境跟初始状态已经不一样了。一旦后面系统更新把某个关键的库版本顶掉QT可能莫名其妙跑不起来。给系统盘做一份镜像或者快照排查问题时可以随时回滚亲测能救急。这个编译好的QT后续还可以继续扩展用linuxdeployqt或手写脚本把编译产物做成可分发的tar包碰到新机器解压即用。基于这个QT继续编译QScintillaPython和C都需要、QCustomPlot 这类第三方库业务集成时会用到。如果QML性能不满足需求再研究一下是否启用GLES支持很多ARM平台用OpenGL ES比桌面GL更稳定。最后再分享一个小技巧我编译完QT后会在 /etc/profile.d/qt.sh 里加一段环境变量配置让所有用户登录后都能直接使用新编译的QT这样后续编译自己的业务程序不需要每次手动指定路径。export QTDIR/opt/Qt5.12.10 export PATH$QTDIR/bin:$PATH export LD_LIBRARY_PATH$QTDIR/lib:$LD_LIBRARY_PATH export QT_QPA_PLATFORM_PLUGIN_PATH$QTDIR/plugins/platforms加上之后记得source /etc/profile或者重新登录。整体来说在麒麟V10 ARM64上编译QT 5.12.10是一次非常典型的国产化适配过程流程不复杂细节却很多。把这套流程跑通之后后续在这个平台上做其他依赖库的编译、业务系统的对接都会顺手很多。本文还有配套的精品资源点击获取