ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

飞腾麒麟V10上源码编译Qt 5.12.8:依赖配置与运行排障实战

飞腾麒麟V10上源码编译Qt 5.12.8:依赖配置与运行排障实战 写这篇东西之前先说个背景我最近在飞腾处理器配银河麒麟V10 SP1的机器上把Qt 5.12.8的开发环境从零搭了一遍。整个过程不像x86上装个Qt Creator那么顺滑光configure就折腾了三四轮中间还踩了xcb插件、中文输入法、字体渲染好几个坑。这篇文章不是官方文档翻译而是把我实际操作的命令、遇到报错时的排查链路、以及最后部署时怎么把依赖库扒干净的完整记录写出来给要在同平台做Qt开发的朋友一个能直接照着走的参考。1. 扁鹊见蔡桓公先看清系统自带Qt与项目要求之间的差距很多人拿到机器第一反应是apt install qt5-default然后高高兴兴建工程。这个思路在飞腾上不是不能用但多数国产生态项目都会在架构文档里写明“依赖Qt 5.12.x”这里有几个实际问题需要先正视。1.1 系统仓库里的Qt版本不一定是你想要的银河麒麟V10 SP1的软件源里虽然有qtbase5-dev这类包但版本往往跟着系统发行周期走可能是5.11也可能是5.15甚至某些定制镜像里只放了qt5-qtbase的运行时开发头文件都没装全。如果一个项目原本在x86上用5.12.8开发换到飞腾上直接用5.15编译虽然大部分代码兼容但遇到QString::asprintf、QRegularExpression这些行为有微调的模块时排查起来非常恶心。更关键的是麒麟软件仓库里的Qt包是否针对aarch64做过完整编译验证这是没人给你打包票的。我自己就遇到过系统自带的libqxcb.so在部分飞腾集成显卡机器上启动即段错误的情况换用源码编译的Qt之后反倒稳定。所以我的建议很简单如果项目锁定5.12.8就直接源码编译一套独立的Qt到/opt/Qt5.12.8不碰系统自带的Qt两套环境互不干扰。这样qmake版本可控、编译选项可控、插件路径可控后续排查问题也方便。1.2 Qt官方安装包在ARM架构下的尴尬很多人问Qt官网不是有在线安装器吗确实有但官方Online Installer对Linux AArch64的支持并不友好它非常挑glibc版本和桌面环境在麒麟上装一半就静默退出的情况很常见。离线安装包.run也主要面向x86_64专门给aarch64打包的离线包几乎找不到。至于用aqtinstall这类第三方工具拉取Qt for ARM的预编译包在飞腾上往往因为依赖的OpenGL版本、xcb库版本不匹配装完能用但启动Qt Creator时报错把简单问题复杂化。这就把选择逼到了最朴素的一条路拿官方源码包在本地编译。编译一次也就一顿饭的功夫但换来的环境可控性是最高的。后面所有坑都基于这个前提展开。2. 动手之前先排雷系统状态确认与依赖包清单在运行任何configure命令之前推荐先花两分钟确认机器状态。飞腾机器型号杂、麒麟定制版本多不排除你拿到手的镜像被别人改过软件源。2.1 三条命令判断当前环境uname -m cat /etc/os-release qmake --version 2/dev/null || echo 系统没有安装qmakeuname -m输出aarch64说明确实是ARM64架构/etc/os-release能看到当前是V10还是V10 SP1以及软件的基线版本。这两条信息决定你后续configure时要不要加特殊参数。接着看系统里有没有残留的Qtdpkg -l | grep qt5 | head -n 20如果看到一堆qt5-*包不用卸载我们的自编译Qt会装到独立目录两者不冲突。但如果想彻底清理干净再开始可以执行sudo apt autoremove --purge qt5-*此时建议谨慎因为系统桌面很可能也依赖Qt组件全卸了桌面会出问题。我的做法是保留系统Qt只在PATH环境变量层面让自编译版本优先。2.2 编译依赖包完整安装命令这一步很重要漏装一个库后面configure就会停在某一行报错返工麻烦。直接在根终端执行sudo apt update sudo apt install -y build-essential gcc g make perl python3 git \ libx11-dev libx11-xcb-dev libxext-dev libxi-dev libxrender-dev \ libxrandr-dev libxcb1-dev libxcb-glx0-dev libxcb-icccm4-dev \ libxcb-image0-dev libxcb-keysyms1-dev libxcb-render-util0-dev \ libxcb-shape0-dev libxcb-xinerama0-dev libxcb-xfixes0-dev \ libxcb-xkb-dev libxcb-util0-dev libxkbcommon-dev \ libxkbcommon-x11-dev libfontconfig1-dev libfreetype6-dev \ libglib2.0-dev libpng-dev libjpeg-dev libssl-dev \ libgl1-mesa-dev libegl1-mesa-dev libsqlite3-dev \ libicu-dev libpcre3-dev zlib1g-dev重点解释几个容易忽视的包libxkbcommon-x11-dev和libxcb-xkb-devQt的xcb平台插件依赖这两个库做键盘映射漏了的话libqxcb.so虽然能编出来但启动任何Qt程序都会立刻崩溃报错信息只说“could not load xcb”不会提示是缺少XKB相关库。libxcb-icccm4-dev、libxcb-keysyms1-dev窗口管理器交互和快捷键处理需要它们。libegl1-mesa-dev飞腾自带的图形驱动对OpenGL ES支持还可以Qt5.12.8可以通过EGL拿到硬件加速能力这个包不装configure阶段会少检测出一个重要特性。如果你的项目只用Qt Widgets、不碰Qt Quick/QML可以适当裁剪但考虑到大多数嵌入式项目迟早会用到QML做上位机界面建议别省这些依赖。2.3 软件源慢或失效时的处理麒麟系统有时会碰到apt update卡住或者源报404。可以先看一下sources.list里写的是哪个地址cat /etc/apt/sources.list ls /etc/apt/sources.list.d/如果发现源指向一个已失效的内网地址需要把它改成能访问的镜像地址。这里有个实际经验不少企业内网环境里运维会准备一个本地软件源更新前先问运维要正确的sources.list地址比自己在网上乱找镜像要靠谱得多。改完源执行sudo apt clean sudo apt update确认依赖包能装齐再继续下一步。3. configure参数一条条核对本地编译Qt5.12.8的实际操作拿到源码、编译、安装这阶段遇到的问题最多。我把实际执行过程拆成几步每条参数都讲清楚为什么这么写。3.1 源码下载与完整性校验源码包建议从官方镜像下载避免从不明来源获取到被改过的包wget https://download.qt.io/archive/qt/5.12/5.12.8/qt-everywhere-src-5.12.8.tar.xz下载完先校验SHA256官方页面会给出校验值例如sha256sum qt-everywhere-src-5.12.8.tar.xz这一步不是走过场。飞腾平台有时会通过网络加速设备拉文件中间层设备转发出错导致包损坏的情况我碰到过一次解压到一半报“unexpected EOF”才发现。提前校验能省半天时间。解压并进入目录tar xvf qt-everywhere-src-5.12.8.tar.xz cd qt-everywhere-src-5.12.83.2 configure阶段的关键取舍这是最核心的一步。我最终使用的配置命令如下mkdir -p /opt/Qt5.12.8 ./configure -prefix /opt/Qt5.12.8 \ -opensource -confirm-license \ -release -shared \ -nomake examples -nomake tests \ -xcb -xcb-xlib -xkbcommon \ -fontconfig -system-freetype \ -qt-libpng -qt-libjpeg \ -sql-sqlite \ -openssl-linked逐条说明背后的考量-prefix /opt/Qt5.12.8指定安装目录后续卸载就是删一个文件夹干净利落。-release -shared发布版、动态库这是源码编译Qt最常见组合。如果你需要断点进Qt源码看内部逻辑再加-debug但那会让库体积大好几倍性能也下降日常开发没必要。-nomake examples -nomake tests省下大量编译时间。examples和tests编译出来对实际开发用处不大需要看示例代码时直接去源码examples/目录里翻就行。-xcb -xcb-xlib -xkbcommon强行启用xcb平台插件这是Linux桌面Qt程序运行的基石。Qt默认会自动检测但飞腾机器上有时检测逻辑会漏掉某些XCB扩展库导致configure阶段虽然输出“xcb yes”实际生成的libqxcb.so不完整。显式指定可以让配置阶段就报错避免把问题留到运行时。-fontconfig -system-freetype使用系统的freetype和fontconfig。飞腾麒麟自带文泉驿等中文字体Qt通过fontconfig能找到它们中文渲染没问题。-qt-libpng -qt-libjpeg让Qt内部包含png/jpeg解码库。虽然也可以链接系统库但这样部署时能少依赖两个系统so文件离线拷贝到别的麒麟机器上也不容易缺库。-sql-sqlite内置SQLite驱动。大部分Qt项目会用SQLite存本地配置这个选项默认就有显式写出来是为了让configure阶段明确检测sqlite头文件如果系统缺库能及早发现。-openssl-linked链接系统的OpenSSL保证Qt Network模块能访问HTTPS。如果你确定整个生命周期都在纯内网、完全不需要HTTPS可以改成-no-openssl缩短编译时间但多数场景没必要冒险。还有一个参数我故意没加-no-opengl。飞腾自带的Mesa驱动对OpenGL ES 2.0支持还算完整保留EGL能在Qt Quick里获得基本硬件加速。如果后续运行时图形崩溃把环境变量QT_OPENGLsoftware加上就能切到软渲染等于是个双保险。执行configure后盯着输出看两处一是“Basic XCB functionality”是否显示yes二是“OpenSSL”是否显示linked。出现no先别急着重跑看最后的error summary缺哪个库就补装哪个。3.3 编译安装与时间预期配置通过后执行编译make -j4-j后面的数字通常是CPU核心数加一飞腾FT-2000/4是四核-j4比较合适如果是飞腾D2000八核可以-j8。ARM芯片的发热和功耗特性决定了编译负载不宜拉满留一个核给系统其他进程用会更稳。完整编译Qt库大概需要30到50分钟取决于机器内存和磁盘速度。8G内存的机器建议关掉浏览器再编译否则OOM Killer介入会随机杀掉编译器进程报错千奇百怪谁能想到是内存不够呢。编译完后make install装完检查一下/opt/Qt5.12.8/bin/qmake --version看到Using Qt version 5.12.8 in /opt/Qt5.12.8/lib就算成了。4. 运行时才是排雷场xcb插件、中文字体和输入法三板斧编译通过只是开始。写个小程序跑起来才是环境验证的真章。这一步我建议直接从最简单的Widgets窗口开始别一上来就搞QML#include QApplication #include QLabel int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label(飞腾麒麟Qt测试); label.show(); return app.exec(); }用/opt/Qt5.12.8/bin/qmake建工程并编译然后运行接下来可能碰到三类问题。4.1 xcb平台插件找不到的三种表现和定位第一种直接报qt.qpa.plugin: Could not find the Qt platform plugin xcb in 。原因十有八九是QT_PLUGIN_PATH没设置或者程序身边没有plugins/platforms目录。在bash里执行export QT_PLUGIN_PATH/opt/Qt5.12.8/plugins再运行程序问题大概率消失。第二种报QXcbConnection: Failed to initialize XCB connection。这是连X Server都没建立成功。先确认DISPLAY变量echo $DISPLAY如果为空export一下DISPLAY:0。如果已经有值但还是连不上看是不是当前shell不是桌面环境里的终端——很多人喜欢用SSH远程跑GUI程序就必须要X11转发支持。第三种程序启动后瞬间段错误不打印任何Qt错误。这通常是xcb插件编译时缺少openssl或xkb库导致插件内部引入的符号在运行时解析失败。可以用ldd看一下插件依赖是否完整ldd /opt/Qt5.12.8/plugins/platforms/libqxcb.so | grep not found有not found就是某个依赖库路径对不上想办法把对应软链接补齐或设置LD_LIBRARY_PATH即可。4.2 中文乱码其实不是Qt的锅程序启动后如果中文变方块通常是系统里没有合适的中文字体。麒麟桌面默认带文泉驿和Noto CJK但精简版服务器镜像可能没装。执行sudo apt install -y fonts-wqy-zenhei fonts-wqy-microhei fonts-noto-cjk装完执行fc-cache -f刷新字体缓存即可。这个坑虽然不在Qt本身但在国产系统里极其常见尤其是从x86移植过来的程序经常是字库路径写死导致乱码而Qt用fontconfig按字体名查找字体缺失时表现更隐蔽只在标点符号和小字号场景下悄悄变成豆腐块。4.3 输入法平台插件让fcitx在自编译Qt里被识别麒麟系统默认输入法框架多为fcitx4或fcitx5但自编译Qt不会自动把输入法插件编进去。表现就是窗口能打开、键盘能输入ASCII但切不到中文按CtrlSpace没反应或者fcitx状态条显示英文。解决思路是复用系统里已有的Qt输入法插件。先确认系统里有没有这个插件dpkg -L fcitx-frontend-qt5 | grep platforminputcontexts如果有输出说明插件文件已经被安装。典型路径在/usr/lib/aarch64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so把它复制到自编译Qt的对应目录sudo mkdir -p /opt/Qt5.12.8/plugins/platforminputcontexts sudo cp /usr/lib/aarch64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so \ /opt/Qt5.12.8/plugins/platforminputcontexts/同时设置环境变量export QT_IM_MODULEfcitx如果系统默认用的ibus就把上面的fcitx换成ibus插件路径也相应找ibus相关包。这个做法属于“借鸡生蛋”不用为了输入法单独编一遍Qt源码省事直接。如果你是从源码编译fcitx插件给Qt用的路线理论上更干净但在飞腾上要同时编译fcitx5-qt和qtbase两个工程版本匹配细节多收益不大我实测复制的做法完全够用。5. Qt Creator接入与部署兜底别让编译器和qmake各说各话环境变量和运行时问题都收拾利索之后就要把自编译Qt挂到Qt Creator里方便日常开发调试。5.1 手动配置Kitqmake路径和编译器要对应麒麟系统如果装了Qt Creator菜单进入工具-选项-Kits在Qt Versions页点Add选择/opt/Qt5.12.8/bin/qmakeQt Creator会自动识别版本号。在Compilers页确认GCC项填的是aarch64-linux-gnu-gcc或系统默认gcc这两个在飞腾上通常是同一个。在Kits页新建Kit编译器选GCCQt版本选刚才加进来的Qt 5.12.8CMake选系统自带的比如3.13以上版本。最常见的错误是Kit里的编译器和qmake版本不匹配——比如编译器选成了x86交叉编译链编译出来的程序自然跑不起来。飞腾本机开发全部用本机gcc即可不要再引入交叉编译器除非你是做嵌入式板卡交叉编译。5.2 两个编译提速开关麒麟系统下Qt Creator默认会开Shadow Build也就是把编译产物放到独立的build目录。这个功能建议保留但可以顺手做两个调整在Kit的CMake Configuration里增加CMAKE_BUILD_PARALLEL_LEVEL4或者qmake工程的Make Arguments写成-j4避免每次点锤子图标都单线程编译。项目里如果启用了Unity BuildQMAKE_UNITY_BUILD编译速度会有显著提升。对Qt项目来说把所有cpp合并到一个编译单元里虽然编译时间缩短但要注意某些有全局宏冲突的文件不适用。5.3 离线部署手动归纳依赖库开发调试没问题之后真正让人头大的是把程序拷到另一台没装Qt的麒麟机器上跑起来。linuxdeployqt在x86上好用但在aarch64上连官方release都很少而且它要求目标环境有dpkg工具在简化版系统上经常翻车。我的做法是一套手动的“依赖收集”脚本mkdir -p deploy/plugins deploy/lib cp ./build/app deploy/ cp -r /opt/Qt5.12.8/plugins/platforms deploy/plugins/ cp -r /opt/Qt5.12.8/plugins/platforminputcontexts deploy/plugins/ cp -r /opt/Qt5.12.8/plugins/imageformats deploy/plugins/ cp -r /opt/Qt5.12.8/plugins/styles deploy/plugins/ # 收集Qt库本身 for lib in $(ldd ./build/app | awk /\/opt\/Qt5.12.8\//{print $3}); do cp -a $lib deploy/lib/ done # 收集系统里Qt运行也需要的当前暂不存在库这一步通常不执行 # 如需完整收集可用 ldd app 逐行查并手动拷贝。然后对可执行文件设置RPATH让它在deploy/lib里找库sudo apt install -y patchelf patchelf --set-rpath $ORIGIN/lib deploy/app这样程序在目标机器上运行时会优先在自身lib目录下找Qt库不会去污染其他应用的同名库。对于Qt插件还要在启动脚本里设置QT_PLUGIN_PATH#!/bin/bash export QT_PLUGIN_PATH$PWD/plugins export QT_QPA_PLATFORM_PLUGIN_PATH$PWD/plugins/platforms export LD_LIBRARY_PATH$PWD/lib:$LD_LIBRARY_PATH ./app这个“绿色版”打法在纯内网环境里很实用不依赖目标机器软件源拷过去解压就能跑。6. 飞腾实测问题收录常见报错与根因对照最后把我在这个过程中遇到过的典型报错整理成一张对照表方便大家拿着现象找原因。报错现象根因解决动作Could not find the Qt platform plugin xcbQT_PLUGIN_PATH未设置或plugins目录缺失设置QT_PLUGIN_PATH/opt/Qt5.12.8/pluginsQXcbConnection: Failed to initialize XCB connection未连接到X Server确认DISPLAY变量、SSH转发、本地终端启动即段错误不用任何Qt报错libqxcb.so依赖库缺失ldd libqxcb.so中文显示方块系统无中文字体安装fonts-noto-cjk/wqy系列CtrlSpace无法切换中文Qt缺fcitx/ibus输入法插件复制系统platforminputcontexts插件过来configure报Could not find libxkbcommon漏装libxkbcommon-x11-dev补装后再跑configuremake编译到一半Killed内存不足加swap或减少-j并行数运行时报QXcbIntegration: Cannot create platform OpenGL contextOpenGL驱动兼容问题设置QT_OPENGLsoftware或LIBGL_ALWAYS_SOFTWARE16.1 一张图分辨是Qt问题还是系统问题很多新手在Qt环境报错时第一反应就是重装Qt。我的排查顺序是固定的先用纯GTK程序或者系统自带GUI工具验证桌面环境是否正常。如果系统自带的文本编辑器能正常打开说明X Server、显卡驱动、字体基础是好的再跑刚写的Qt测试程序根据报错定位是平台插件还是OpenGL上下文的问题。如果整个桌面都花屏了那先解决系统图形栈再来怀疑Qt不迟。6.2 一个百试百灵的自我检测程序测试环境是否健全我习惯写一个极小的Qt应用同时测试三件事窗口显示、中文渲染、QML场景能否创建cat envtest.pro EOF QT widgets quick CONFIG console TARGET envtest SOURCES main.cpp EOF cat main.cpp EOF #include QApplication #include QLabel #include QQuickView int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label(中文环境OK); label.show(); QQuickView view; view.setSource(QUrl(qrc:/main.qml)); view.show(); return app.exec(); } EOF加上最简main.qml文件编译运行。窗口能出、中文能显、QML场景不崩环境基本就稳了。以后移植别的Qt项目先用这个程序在目标机器上验一遍能省掉大量误判。另外一个小提醒麒麟V10 SP1有些版本默认开了SELinux如果程序部署到目标机器上双击启动没反应tail -f /var/log/messages里能看到avc: denied字样这时候要临时放宽对该文件的权限策略而不是怀疑库没拷全。总的来说飞腾加麒麟的组合目前已经能稳定承载Qt应用开发只是搭建过程里的细节比x86多一些。我这套流程自测后也交付给团队里其他人复用同事反馈最值钱的就是“先把依赖装全”、“再谈configure”、“最后管运行时”按这个顺序走半天内肯定能把环境拉起来。如果你在实操中遇到我这里没覆盖到的新报错按第六节的排查链路来定位多半能找出根因。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进