ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

麒麟服务器ARM64平台Qt 5.12.8源码编译实战指南

麒麟服务器ARM64平台Qt 5.12.8源码编译实战指南 简介面向在Kylin-Server-10-SP2arm64上编译Qt 5.12.8应用的工程师这份压缩包提供了编译完成后所需的完整头文件集合共2000个.h文件包体约65.91MB全部为C头文件格式属于典型的Qt构建产物头文件目录。这些头文件不仅覆盖Qt Core、Qt GUI、Qt OpenGL等常用模块的公共接口还包含本地化数据、URL解析、OpenGL扩展等内部私有声明能够满足从基础组件引用到底层机制排查的多种开发需求。直接引用该头文件集合可省去从源码逐一收集或手动整理的时间也避免因系统自带Qt版本不一致而引发的编译错误在麒麟ARM服务器上搭建Qt开发环境或进行交叉编译时尤其顺手。对于国产化系统适配、嵌入式界面开发、模块裁剪与定制化构建等场景这份材料都能提供清晰的依赖参照配合Qt源码阅读还能帮助深入理解实现细节。目前已有245人学习下载可作为长期保留的开发参考。 Kylin-Server ARM64上亲手编译Qt 5.12.8这事我前后折腾了大概两天中间踩了不少坑但最终成果很值。先说清楚这玩意儿是干嘛的在麒麟服务器系统Kylin-Server-10-SP2-Release-Build09-20210524-arm64上从源码编译出一套完整的Qt 5.12.8开发环境让Qt程序能跑在ARM64架构的机器上。如果你在国产化替代项目里做界面开发或者需要在飞腾、鲲鹏这类ARM平台服务器上部署Qt应用这篇文章就是给你准备的实操笔记。很多人会问服务器上要界面干嘛还非得上Qt实际项目里有的是需要本地GUI配置工具、有的是跑数据可视化面板、有的是部署工业现场的上位机程序这些场景都绕不开在服务器上直接跑Qt。而系统自带的源里Qt版本老、插件不全想要完整可用的开发环境源码编译是唯一靠谱的路。下面把整个过程中的方案思路、环境准备、编译配置、问题排查完整记录下来。1. 方案选型与整体思路拆解1.1 为什么选Qt 5.12.8而不是其他版本Qt版本众多5.12、5.15、6.x各有拥趸我在这个项目里选了5.12.8原因很实际。5.12系列是LTS长期支持版本官方支持周期长、社区资料多、踩坑记录丰富——这对ARM64平台尤其重要因为x86上能直接搜到的经验换到ARM架构上往往得自己重新试。5.15虽然也是LTS但它从开源包到二进制包做了不少调整部分模块开始强制走商业授权框架离线编译的合规性不好把控。6.x版本干脆切到了CMake构建系统和传统的qmake流差异太大如果项目里有大量基于qmake的旧代码迁移成本是实打实的。另外还有一个关键指标依赖库的兼容性。5.12.8对xcb、fontconfig、mesa等图形栈的版本要求不算激进在Kylin Server的默认源范围内基本能找齐依赖不用为了某个库再单独编译一个新版可以省掉一大半的折腾时间。1.2 为什么不用apt直接安装而是源码编译如果服务器能联网直接apt install qtbase5-dev其实是最省事的方案几分钟搞定。但实际场景下这套方案往往满足不了需求。首先是版本太旧麒麟源里自带的Qt版本通常停留在5.11甚至更低缺失很多新模块特性。其次是插件不完整服务器版的Qt二进制包经常不带齐全的xcb平台插件结果程序编译出来了一运行报could not find or load the Qt platform plugin xcb直接就给你把GUI程序判了死刑。再一个是定制需求比如需要静态编译、需要裁剪到最小体积、需要接入特定的设备插件这些靠apt装是做不到的必须从源码控制。所以我一直觉得ARM64平台上编译Qt不是一道选做题而是必做题。源码编译能够百分百确认每个组件都针对当前架构生成了正确的指令集避免二进制包跨架构不兼容的隐形问题。2. 编译前的环境准备2.1 确认系统版本与架构信息动手之前一定要把环境信息看明白。系统是Kylin-Server-10-SP2-Release-Build09-20210524-arm64注意这个SP2表示第二服务包Build09是构建序号20210524是构建日期这些都是确认系统基础状态的关键信息。执行uname -m确认架构输出aarch64说明是ARM64架构。查看系统的几个常用命令uname -m cat /etc/os-release cat /etc/.productinfo lscpu | grep Architecture在ARM64平台上有些源码包需要关注大小端和页大小不过Qt的主流模块对这些问题处理得比较透明确认架构一致就可以不用过度焦虑。2.2 检查编译工具链Qt 5.12.8对编译器的基础要求是支持C11GCC版本至少4.8以上。Kylin Server 10 SP2自带的gcc一般是7.3或7.5完全够用。配置前先检查gcc --version g --version make --version perl --version这里特别提一句Perl版本不能太老Qt的构建脚本大量依赖Perl做文本处理和代码生成早期CentOS上Perl 5.10就能干活但如果你遇到莫名其妙的构建中止错误优先怀疑Perl版本太低。2.3 一次性装齐依赖库这是整个编译过程里最磨人的一步依赖缺一个编译就崩一次每个都是随机位置报错。我把Kylin Server下编译Qt 5.12.8需要的依赖整理成了一张表这是踩了N次坑换来的清单依赖包作用缺失时的典型症状libxcb1-dev libxcb-xkb-devxcb平台插件构建configure时xcb特性被置为nolibx11-dev libxkbcommon-devX11协议支持无xcb、xkb扩展libfontconfig1-dev字体渲染Qt无法识别系统中文字体libfreetype6-dev字形渲染引擎字体显示方块、乱码libgl1-mesa-devOpenGL软件实现Qt Quick内容crasheslibegl1-mesa-devEGL图形接口eglfs插件编译失败libglib2.0-dev事件循环整合某些模块无法启用gliblibdbus-1-dev进程间通信QtDBus模块缺失libssl-devOpenSSL支持QtNetwork的SSL功能不可用libicu-devUnicode与国际化中文显示和排序异常安装命令yum install -y libxcb-devel xcb-util-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-renderutil-devel xcb-util-wm-devel libX11-devel libxkbcommon-devel libxkbcommon-x11-devel fontconfig-devel freetype-devel mesa-libGL-devel mesa-libEGL-devel glib2-devel dbus-devel openssl-devel libicu-devel这里有个血泪教训configure脚本本身检查依赖时并不严格有些模块检测失败它就默默跳过不会中断编译。问题到了编译后期才爆发QtQuick模块编了一半发现EGL头文件没有整个build目录直接废掉。所以依赖检查一定要做在configure之前不要指望检测脚本帮你拦。3. configure配置与编译实操3.1 获取源码并解压源码包我用的是qt-everywhere-opensource-src-5.12.8.tar.xz这个包包含全部模块qtbase、qtdeclarative、qtquickcontrols、qtmultimedia等总计约500多MB解压后更大。下载时可以优先选国内镜像速度差距很明显。解压命令tar -xf qt-everywhere-opensource-src-5.12.8.tar.xz cd qt-everywhere-opensource-src-5.12.83.2 configure参数详解configure这步是整个编译的定盘星参数选对了后面顺风顺水选错了后面编译几十次都得推倒重来。我最终用的配置是./configure \ -prefix /usr/local/qt5.12.8 \ -opensource \ -confirm-license \ -release \ -optimized-qmake \ -nomake examples \ -nomake tests \ -no-rpath \ -qt-libpng \ -qt-libjpeg \ -qt-zlib \ -qt-pcre \ -qt-xcb \ -no-opengl \ -skip qtwebengine \ -skip qtwayland \ -skip qtscript \ -skip qtgamepad逐个解释一下几个高频参数的作用方便你按需调整。-prefix参数指定安装路径。我建议路径固定绝对路径别用默认的/usr/local因为Qt的qmake会把路径写进工具链配置里后面qmake生成Makefile时会引用这个路径跨目录移动容易出麻烦。-qt-xcb特别关键。这一项让Qt使用自带的xcb库组合构建xcb平台插件对于国产化系统里经常出现的xcb版本偏旧问题这是最稳妥的解法。-no-opengl是权衡后的选择。ARM64服务器上大多没有独立GPUOpenGL硬件加速意义不大关掉它还可以少装一堆依赖。但代价是Qt Quick的某些渲染特效会退化为软件渲染对纯业务界面来说影响不大。如果目标机器有GPU可以改成-opengl desktop然后把相关libGL-devel补齐。-skip qtwebengine必须解释一下。QtWebEngine是Chromium内核的浏览器组件体积大、依赖重、编译时间能以小时计而且在ARM64环境里经常过不了编译。绝大多数项目用不到这个组件别犹豫直接跳过。3.3 正式编译configure通过后我的经验是先用make -j4跑不要一上来就无脑-j16。ARM服务器CPU核数多的话-j12或者-j16能明显提速但内存不够就尴尬了——GCC的C编译非常吃内存Qt整个项目并发编译时的内存峰值能到8GB以上如果系统内存只有8GB并发太高直接OOM编译进程被内核干掉完事儿还不知道原因。编译命令make -j12实测下来在16核ARM64 CPU 32GB内存的环境下完整编译大概需要40到60分钟。如果配置里带了multimedia模块时间还会更长。编译过程中输出会非常密集做好心理准备。最后看到类似Qt is now configured for building和编译进度跳完100%就基本成了。安装make install3.4 环境变量配置安装完成后为了让系统找到新装的Qt要编辑/etc/profile或者用户目录的.bashrcexport QT_HOME/usr/local/qt5.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/qmlsource之后验证一下qmake -v输出显示QMake version 3.1 Using Qt version 5.12.8 in /usr/local/qt5.12.8/lib说明环境变量生效编译工作区正式可用。4. 编译期与运行期的坑问题排查实录4.1 configure阶段xcb特性检测失败这是最常见的问题configure日志里能看到xcb features disabled之类的字眼。原因就是缺libxcb相关的dev包我前面列的那张依赖表就是针对这个情况准备的。解决办法不是去configure脚本里改开关而是把依赖包补齐重新configure。检查方法./configure -verbose | grep xcb如果看到xcb后面跟着no就说明xcb插件没启用。补包之后把build目录清掉直接删掉源码目录重新解压也行别想着增量重来Qt的configure缓存很顽固重新跑一遍。4.2 编译期c internal compiler error编译过程中偶尔会出现GCC内部错误常见触发点是内存不足或者磁盘空间不足。检查方法dmesg | grep -i killed process df -h free -h如果是内存问题降低make并发数比如make -j4。如果是磁盘问题编译目录至少要预留10GB以上空间。我遇到过编译到一半/根分区被占满的情况那真是欲哭无泪只能重新解压源码包前面的编译时间全部白费。4.3 运行期QXcbConnection failed to initialize xrandr这是个高频报错第一次跑Qt程序时直接弹出来QXcbConnection: Failed to initialize XRandr Qt: XKEYBOARD extension is not present on the X server.这个报错的信息很容易让人以为是系统缺少X服务或者xrandr工具其实根因是xcb插件在连接X Server时没能正确初始化RandR扩展。尤其是当你用X11转发ssh -X跑Qt程序时远程的X Server对RandR扩展的支持不完整就会卡在这。排查方法是先在目标机器本地跑一次export QT_DEBUG_PLUGINS1 ./your_qt_app如果本地正常、远程报错基本确认是X转发的问题可以换成x11vnc之类的工具在远程桌面环境里操作或者检查X Server的扩展加载。确保系统里装了xrandr相关组件yum install -y xrandr4.4 qmake构建的项目找不到Qt模块编译完Qt后自己用qmake创建的工程make时提示找不到QtNetwork之类的头文件多半是环境变量没生效或者qmake缓存了旧的路径。执行qmake -query确认QT_INSTALL_PREFIX指向哪里如果是错误的路径检查环境变量后再重新qmake一遍。这里有个小技巧把export命令写入/etc/profile.d/qt.sh文件里重启终端就不会失效比手动source靠谱得多。4.5 xcb平台插件加载失败速查表报错特征可能原因快速定位could not find or load the Qt platform plugin xcbQT_PLUGIN_PATH不对或xcb插件缺失检查plugins/platforms目录The X11 connection brokeX Server断连权限问题检查DISPLAY变量和xhostGot empty QXcbScreenxcb插件和X Server版本不匹配用系统libxcb重新编译xcb插件libxkbcommon-x11.so.0: cannot open运行时缺少xkbcommon检查LD_LIBRARY_PATHNo fonts could be foundfontconfig配置问题安装fontconfig并执行fc-cache -f5. 部署到其他机器与交叉编译的扩展思路5.1 直接把编译产物搬到目标机器编译完成后的Qt目录可以整体打包拷贝到另一台同架构的机器上直接使用。ARM64系统之间搬移架构一致就可以不用重新编译。注意如果是只装运行环境不发开发环境可以只拷贝lib、plugins、qml三个目录bin路径下的工具可以大部分省略体积能小不少。用tar打包时要保留符号链接加上-h参数之前先想清楚不能把符号链接指向的真实文件全部打进包里否则包体积会膨胀两三倍。5.2 静态编译还是动态编译如果目标机器上有多个Qt程序要跑动态库方案最省内存共享一份.so文件就行。但国产化项目里经常遇到要拷到内网机器、不便安装依赖的场景静态编译就成了刚需。配置时加-static -static-libgcc -static-libstdc三个参数libqxcb相关依赖一定要用静态方式链接进去否则运行时报错找libxcb.so.1又得从头趟一遍坑。静态编译的坑在于部分插件比如inputmethod有依赖循环或者GPL授权问题比如QtXkbCommonSupport在静态链接时容易报undefined reference。这个问题的处理方案是编译时明确-enable-static -disable-shared同时把xcb相关依赖全部使用-devel包提供的静态库。我在ARM64平台上实测过静态编译出来的Qt程序执行文件约20MB至40MB依赖干净适合部署到无网络环境。5.3 交叉编译的扩展场景如果开发机是x86的PC目标机是ARM64服务器不想在服务器上跑编译可以搞交叉编译。用aarch64-linux-gnu-g作为编译器交叉工具链可以yum install gcc-aarch64-linux-gnuconfigure时指定-platform linux-aarch64-gnu-g。要注意的是交叉编译的Qt依赖库也必须是对应ARM架构的不能用x86的libxcb、fontconfig跨架构的二进制链接在一起必然出问题。但说实话如果不是必须我不推荐ARM64上交叉编译。直接在目标机上原生编译前期虽然慢但后期所有依赖和运行时环境都会留在目标机器上程序出错时的排查成本低非常多。交叉编译出来的程序一旦遇到运行库不兼容的问题调试难度翻倍。6. 收尾实测感受与个人经验整个流程走完后我的直观感受是Kylin Server的ARM64环境并没有想象中那么原生地支持Qt很多x86下简单忽略的问题在这个平台上都会主动找上门。但正因为如此把编译流程完整走一遍你对Qt的构建机制、依赖关系和系统底层组件的理解会深一个层次。最后再分享两个自己的使用习惯。第一每次configure之后把生成的config.summary文件保存一份里面记录了所有特性的启用情况排查问题时比看日志快得多。第二编译完成之前一定先保留好configure的原始参数——可以写进一个build.sh脚本留在源码目录里下次回来看的时候不会一头雾水。当初我为了方便复查随手在脚本开头加了一行日期注释结果这个脚本后面帮我省了至少一个小时的回忆时间。本文还有配套的精品资源点击获取
返回列表