国产Linux下Qt 5.12.12源码编译实战:从configure到部署

发布时间:2026/10/20 16:26:44
国产Linux下Qt 5.12.12源码编译实战:从configure到部署 如果你现在手里正好有一台某国产Linux发行版V4的机器想把Qt升级到5.12.12翻了一圈发现系统源里只有一个版本很老、而且明显不是为开发准备的Qt包Qt官方在线安装器在这套系统上又跑不起来那么你大概率也会走到我上个月走过的路下载源码包自己动手编译。这篇东西就是完整的操作记录。从最开始的“为什么要自己编”到环境摸底、configure参数选择、make过程的意外处理再到装完之后的部署和发布配置每一步我都把当时的思路、踩到的坑和最终的处理方式写清楚了。目标读者是那些需要在国产Linux环境里做桌面或嵌入式开发的人尤其是第一次在这种系统上碰Qt源码编译、又不太想走弯路的同学。1. 为什么某系统V4上需要自己编译Qt源码而不是等源里的现成包1.1 系统源里的Qt包往往不是给开发者准备的某系统V4这类国产Linux发行版本身的定位是稳定的基础环境所以自带软件源里的Qt包更多是给系统组件自己用的。我在那台机器上搜包的时候源里确实有Qt5相关的东西但要么版本偏低要么拆得七零八落缺了开发头文件更别提QML、WebEngine这类功能模块。就算勉强把缺的包一个个补齐版本之间还可能互相打架。某系统V4的包仓库和上游开源生态不是完全同步的某些库的版本被锁死在固定版本上你没法用一个明确的Qt小版本来保证API行为一致。对于要做长期维护的项目来说这种“不确定版本”本身就是风险。自己编译源码至少能拿到一个完全可控的Qt环境版本固定、模块按需裁剪、编译参数自己指定。后面不管是产线部署还是开发机迁移只要把同一个部署目录拷过去环境就能复现。1.2 为什么选5.12.12而不是5.15或6.x关于版本选择我需要多说两句。某系统V4上常见的编译器是GCC 7到9之间的版本如果直接上Qt 6它会要求C17并且整套构建体系换成了CMake依赖链也变长在这类平台的兼容性风险其实挺大。5.15虽然仍在支持期但它的小版本发布节奏和补丁分支在国产平台上适配程度不一我也见过有人在某系统上编5.15出现xcb插件问题的案例。5.12.12是5.12这个系列的最后一个小版本整个5.12分支以稳定著称而且对老编译器、老系统库的容忍度很高。它的源码包编译方式仍然是熟悉的qmake那套不要求CMake很多内网环境里没有额外工具链也能编。对我这个场景来说5.12.12是“最能一次编过”的选项这句话在国产系统上权重很高。1.3 动态编译为主静态编译先放一边这里先交代一个选型结论我用的是动态编译。Qt在Linux平台下默认就是动态库方式configure不加特殊参数就会生成一大堆so文件应用程序运行时通过rpath和LD_LIBRARY_PATH找到它们。我之所以没有考虑静态Qt是因为静态编译要求所有依赖库都有静态版本某系统V4上X11、xkbcommon、icu这些库不一定都带.a文件就算带了还要处理许可证和打包体积的问题。动态编译配合部署目录拷贝反而是国产系统发布软件最常用的方式。2. 动手前先摸清这台机器的家底2.1 工具链版本核查gcc、make、glibc编译Qt之前我建议你先花半小时把系统基础环境搞清楚省得configure跑到一半才发现编译器太老或者某个系统库根本不对。在终端里依次执行gcc --version g --version make --version ldd --version | head -1 cmake --version某系统V4自带的gcc版本如果是7.x或8.x编Qt 5.12.12完全没有压力5.12官方要求C11这个门槛很低。真正需要关心的是glibc版本因为Qt编译出来的二进制运行时会动态链接glibc如果部署目标机器比开发机的glibc还老会有兼容性问题。我的原则是开发机和发布目标机尽量保持同一套某系统V4的小版本别跨大版本发布。还要确认make版本别太老4.x都行老版本可能出现并行编译时文件依赖解析不完整的问题。2.2 磁盘、内存和swap的硬性预算Qt源码包解压后大概2GB到3GB完整编译5.12全家桶的话中间产物加上最终部署目录轻轻松松超过15GB。我还见过有人只编译基础模块加qtwebengine最后磁盘占用超过35GB的情况。所以第一件事就是检查磁盘剩余空间df -h /home free -h如果可用空间低于30GB我劝你先清垃圾或者换大分区不要在这个环节省事。内存方面编译Qt的链接阶段特别吃内存8GB勉强够用但会卡16GB算是舒适。如果机器只有8GB内存建议编译前手动加swap别让系统在链接QtWebEngine或者QML模块时直接OOM内存耗尽。临时swap的加法和清理方式sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile编译完了如果不需要直接sudo swapoff /swapfile再删文件就行。2.3 最容易漏的依赖包清单xcb、xkbcommon、fontconfig、icu这是整个编译过程中最值得花時間的一步。Qt在Linux上跑图形界面靠的是XCB插件而XCB插件编译时又依赖一大堆xcb-*库。configure会检测这些依赖检测失败并不会直接终止它只是默默把当前系统的xcb特性关掉最后你make install完一运行程序Qt告诉你“could not find the Qt platform plugin xcb”——那时候排查起来才真要命。我在某系统V4上提前安装的依赖包大概包括这些直接用系统的包管理工具装上sudo apt install -y build-essential perl python3 git sudo apt install -y libgl1-mesa-dev libglu1-mesa-dev sudo apt install -y libxcb1-dev libxcb-icccm4-dev libxcb-image0-dev sudo apt install -y libxcb-keysyms1-dev libxcb-render-util0-dev sudo apt install -y libxcb-shm0-dev libxcb-xinerama0-dev sudo apt install -y libxcb-cursor0-dev sudo apt install -y libxkbcommon-dev libxkbcommon-x11-dev sudo apt install -y libfontconfig1-dev libfreetype6-dev sudo apt install -y libicu-dev libudev-dev libts-dev如果你是直接面对一台安装阶段没接图形界面的机器建议把上面的包一次性装齐。许多教程会漏掉libxkbcommon-x11-dev和libxcb-cursor0-dev这两个不装configure阶段报错不太明显但会在make阶段卡在xcb相关源文件的编译上。关于包管理器的说明某系统V4不同细分版本用的包管理工具不一样有的是apt系有的是rpm系。我上面写的是apt命令如果是rpm系环境包名大多数类似libxcb-devel、libxkbcommon-devel这种带-devel后缀的形式对应关系一目了然。2.4 OpenGL和GPU现状评估这决定了后面图形平台插件的走向某系统V4常见的是集成显卡或者老一代独立显卡驱动情况参差不齐。所以编译前一定要确认OpenGL到底可不可用。我当时的判断方式分三步看内核加载的显卡驱动lsmod | grep -E nouveau|i915|amdgpu确认Mesa开发库已装dpkg -l | grep libgl1-mesa-dev简单跑一个glxinfo或者glxgears测试图形环境是否正常。如果这些命令一个都不存在或者系统根本没有图形界面那就得考虑Qt能不能在无GPU环境里跑。解决办法是configure时加-no-opengl或者-opengl es2然后依赖linuxfb或者eglfs这类平台插件。我在实际项目里用的是带xcb加桌面OpenGL的方式因为某系统V4多数情况还是当作桌面工作站来用接显示器跑Qt客户端程序xcb是最稳妥的窗口系统插件。如果你是要在无显示器的工控盒子上跑那就走-linuxfb的路线两者不要弄混。3. configure配置环节别全要按需打开3.1 基础配置授权、版本和安装路径源码解压完成后进入目录先看一眼顶层哪个目录下面有configure文件。Qt 5.12.12的源码包通常叫qt-everywhere-src-5.12.12.tar.xz解压命令tar -xf qt-everywhere-src-5.12.12.tar.xz cd qt-everywhere-src-5.12.12configure是编译的第一步它会把接下来所有模块的Makefile生成好。最基础、也最关键的三件事是授权确认、构建模式、安装前缀。./configure -prefix /opt/qt-5.12.12 -opensource -confirm-license -release-prefix决定了最终make install的部署目录。我强烈建议放在/opt/qt-5.12.12这种固定的、不带版本大跨度变动的路径而不是默认的/usr/local。这样以后想删掉整套Qt直接删这个目录不会污染系统其他软件。-opensource加-confirm-license是提前把开源协议确认这件事做掉免得configure过程中弹交互提示在某些无人值守环境里卡住。-release表示编Release版本如果要调试Qt自身再去考虑-debug一般开发不需要。3.2 图形平台插件xcb、xkbcommon、linuxfb选哪个这个阶段的图形插件选择决定了编译出来的Qt能跑在什么显示环境里。如果你要跑带窗体的桌面程序必须启用xcb基础支持。configure参数里会有对应的特性开关我用了-xcb -xkbcommon-xcb是启用X Window System下的Qt平台插件。-xkbcommon则是键盘输入管理Qt 5.0之后的版本基本都依赖它没这个库会导致按键事件错乱或者xcb插件直接加载失败。如果你的目标环境没有显示器或者只有一块没有X服务的开发板那就需要加上-linuxfb。linuxfb是直接操作Linux framebuffer设备的平台插件不需要X11但代价是输入设备得自己处理窗口管理功能也几乎没有。我更建议的条件是拿不准环境有没有X服务、显卡驱动能否正常工作时全部编进去。Qt的configure允许你同时启用多个平台插件运行时通过-platform参数选择这样一套部署包走到哪儿都能用-xcb -xkbcommon -linuxfb -eglfs3.3 模块裁剪把qtwebengine这类重货排除掉Qt 5.12.12整个仓库包含的模块很多qtwebengine基于Chromium的那套浏览器内核、qtwebview、qtcharts这些模块各有各的重型依赖。我在某系统V4上编译时直接跳过qtwebengine。原因很简单第一Chromium的编译需要额外的Python、Ninja以及大量内存在国产老机器上很容易失败第二我的应用场景根本不需要内嵌浏览器。为了一个用不到的模块把整个编译拖垮不值得。模块裁剪的参数是-skip可以重复指定多个模块-skip qtwebengine \ -skip qtwebview \ -skip qtcharts \ -skip qtdatavis3d \ -skip qtgamepadqtcharts、qtdatavis3d这类可视化模块如果项目里的图表需求没有也可以减掉。这样configure阶段生成的Makefile少make阶段也省时间。关于-ICU这个特性我建议别图省事直接-no-icu。Qt的文字处理、本地化有些环节需要ICU某系统V4上缺icu库时configure也能过但部分QPA插件和Qt GUI功能会被削弱。所以前面依赖包里我专门列了libicu-dev这种情况下默认的icu检测会直接通过不需要额外加参数。3.4 一份可以直接抄走的configure命令综合上面的考虑我在那台某系统V4机器上最终执行的配置命令是这样./configure -prefix /opt/qt-5.12.12 \ -opensource -confirm-license \ -release \ -xcb -xkbcommon -linuxfb \ -fontconfig \ -skip qtwebengine \ -skip qtwebview \ -skip qtcharts \ -skip qtdatavis3d \ -nomake examples \ -nomake tests \ -no-feature-vnc \ -recheck-all-nomake examples和-nomake tests是避免make阶段把示例和测试代码全部编译一遍既能省时间又能减少磁盘占用。如果不是为了跑Qt自带的demo这两项建议都关掉。-recheck-all是我兜底用的它会强制重新执行所有依赖检测避免之前某次失败的检测结果被缓存影响后续判断。configure执行完屏幕上会列出一大堆feature开关的状态我专门关注这几行的输出xcb ........................ yes xkbcommon .................. yes xcb-xlib ................... yes fontconfig ................. yes icu ........................ yes只要这些是yes就说明系统依赖基本齐了。如果哪个显示no回到第2.3节去装对应包然后重跑configure不要硬着头皮make。4. make阶段耗时、资源与现场排障4.1 并行编译到底开几路configure通过之后make阶段就是漫长的等待。很多人习惯无脑make -j$(nproc)把CPU核心数全部压上去这在内存充足的机器上是没问题的但在某系统V4这种老平台上很容易把内存打爆。我当时那台机器是16核但内存只有16GB一开始直接make -j16跑到一半系统卡顿明显后来换成make -j6才稳定。现在的经验是内存小于等于16GB最多-j4或者-j632GB内存可以考虑-j8再多核心就别指望并行度拯救了链接阶段依然是瓶颈。稳妥的命令是make -j4如果机器确实能扛再加到-j8观察负载和内存占用后再决定。编译Qt这种体积的代码一次生产环境构建磨一两个小时很正常中间不需要一直盯着但最好在终端里开着htop或者free -h看内存是否吃紧。4.2 configure阶段的假成功和真实错误我这次编译过程中最让人头疼的不是make报错而是configure阶段一切正常make阶段才炸出来一堆“缺头文件”的问题。原因就是我前面提到过的configure对部分非核心特性采用“检测不到就禁用”的宽容策略不会直接报错终止。举个例子某次我重新换了一台某系统V4机器configure输出里xcb是yes但make时编译qxcbxkbcommon.cpp直接报xkbcommon/xkbcommon.h: No such file or directory。我回头一看那台机器只装了libxkbcommon-dev没有装libxkbcommon-x11-devconfigure因为x11相关的子检测没跑全就误判了。所以make报错时别急着恍惚先读错误里的文件名。凡是xxx.h: No such file或者cannot find -lxxx这种错误都是依赖缺失的问题定位到对应的开发包安装即可。4.3 cc1plus被Killed之后怎么办链接大模块时最容易看到这样一条错误尤其是编译QML模块或者GCC插件相关代码时cc1plus: fatal error: Killed signal terminated program cc1plus这个错误基本等同于内存耗尽。系统把正在编译的cc1plus进程干掉了不是你代码问题也不是Qt源码问题就是没内存了。处理方案有两个要么调低并行度把make -j4换成make -j2要么按第2.2节的方式加swap。我当时是两者一起做先加上8GB swap再把并行度降到4问题消失。另外注意一个细节make -j的并行度要基于链接阶段的内存占用而不是编译阶段。编译阶段每个编译器进程占几百MB但链接QtGui、QtWebEngine这类超大二进制时单个链接器进程能占到2GB以上所以最保险的做法是make时不离开盯着内存曲线掉头就跑不下去时立刻降到-j2。4.4 make进程跑到一半被人为中断的处理如果编译途中你按了CtrlC或者机器意外断电不需要重新解压源码包。Qt的构建系统是基于Makefile的中断后重新执行同样的make命令它会自动跳过已经完成的目标从断点继续。但有一个前提configure生成的Makefile缓存不能删。不要手贱去清空源码目录或者删.qmake.stash这类文件。我当时有一次为了“干净重来”把整个build目录删了重跑configure白白浪费一个多小时。如果只是想重新配置就执行make distclean ./configure ...这才是正规的“重新来过”流程。5. make install做完并不意味着收工5.1 设置PATH和LD_LIBRARY_PATH的正确姿势make阶段结束后执行安装sudo make install装完之后Qt被放到了/opt/qt-5.12.12。此时你输入qmake -v大概率还是找不到命令因为系统PATH里没有这个目录。我建议在/etc/profile.d/下面创建一个qt5.12.12.sh文件写入export QTDIR/opt/qt-5.12.12 export PATH$QTDIR/bin:$PATH export LD_LIBRARY_PATH$QTDIR/lib:$LD_LIBRARY_PATH export QT_PLUGIN_PATH$QTDIR/plugins然后source /etc/profile.d/qt5.12.12.sh重新加载这时候qmake -v就能正常输出版本号。这里有一个容易踩的坑如果你同时用着系统自带的Qt库LD_LIBRARY_PATH这么一放会把所有程序的Qt库都指向我们刚编译的5.12.12。某个系统组件如果依赖旧Qt可能会因此出问题。我在实际使用中就是直接接受这个影响因为这台机器是专用的开发机不跑其他图形业务程序。如果你的机器有更多用途建议把环境变量放在项目级脚本里而不是全局生效。5.2 用Qt Creator接入自编译Qt工具链某系统V4上经常有人直接安装Qt Creator但它自带的Qt版本和工具链可能不是你编译的这套。打开Qt Creator后菜单路径是“工具”-“选项”-“Kits”-“Qt Versions”点击新增按钮选择/opt/qt-5.12.12/bin/qmake编译器选择系统自带的gcc。接着在“Kits”标签页新建或修改默认套件把Qt Version指向刚添加的版本。这样新建项目时构建和运行都会走你自己编译的Qt环境。我见过有人在Qt Creator外面改了一堆环境变量结果Creator内部一直找不到qmake搞得晕头转向。正确顺序是先确认终端里qmake -v正常再在Creator里配置因为Creator本质上也是调用qmake和make它在哪个环境下能跑配置界面就会给你相同的结果。5.3 qmake自检与最小Demo验证编完Qt的第一个问题永远是真的能用吗我自己习惯写一个最小的Qt Widgets程序能跑起来才算数。建一个临时目录里面两个文件test.pro:QT widgets SOURCES main.cpp TARGET qtcheckmain.cpp:#include QApplication #include QLabel int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label(Qt 5.12.12 build ok); label.show(); return app.exec(); }然后执行/opt/qt-5.12.12/bin/qmake test.pro make ./qtcheck如果弹出一个窗口说明xcb插件、OpenGL检测、系统字体环境全部正常。如果窗口没弹出来终端提示could not load platform plugin xcb那就是第6.2节要讲的问题先把库路径排查一遍。5.4 发布程序时要带走的Qt运行文件很多人编完Qt后第一个程序确实能跑了但它是在开发机上跑的因为依赖了/opt/qt-5.12.12/lib下面的动态库。部署到另一台某系统V4机器上时要么装一遍同样的Qt要么把运行文件带过去。我惯用的发布方式是打一个运行目录。假设可执行文件叫myapp目录结构长这样myapp/ ├── myapp └── lib/ ├── libQt5Core.so.5 ├── libQt5Gui.so.5 ├── libQt5Widgets.so.5 ├── libQt5XcbQpa.so.5 ├── libQt5DBus.so.5 └── platforms/ └── libqxcb.soplatforms目录至关重要Qt通过插件机制加载窗口平台它不会自动去/opt/qt-5.12.12/plugins/platforms找除非设置了QT_PLUGIN_PATH。所以发布时一定要把整个plugins/platforms目录拷到程序旁边。运行脚本里显式设置库路径#!/bin/sh export LD_LIBRARY_PATH/opt/myapp/lib:$LD_LIBRARY_PATH export QT_QPA_PLATFORM_PLUGIN_PATH/opt/myapp/lib/platforms ./myappQT_QPA_PLATFORM_PLUGIN_PATH是Qt查找平台插件的第一优先级位置显式指定后不会找错。6. 那些重复出现的坑我最后是怎么规避的6.1 写一个一键编译脚本把configure记录固化下来编译Qt这种流程如果只在终端里敲一遍下次换台机器就得从头回忆参数非常痛苦。我在第一次编译成功后就把整个流程固化成脚本放在源码目录外面#!/bin/bash export QTDIR/opt/qt-5.12.12 export PATH$QTDIR/bin:$PATH export LD_LIBRARY_PATH$QTDIR/lib:$LD_LIBRARY_PATH cd qt-everywhere-src-5.12.12 ./configure -prefix /opt/qt-5.12.12 \ -opensource -confirm-license \ -release \ -xcb -xkbcommon -linuxfb \ -fontconfig \ -skip qtwebengine \ -skip qtwebview \ -skip qtcharts \ -skip qtdatavis3d \ -nomake examples \ -nomake tests \ -recheck-all make -j4 sudo make install以后换机器脚本改一改路径无脑执行。另外configure完成后生成的config.log和config.summary不要删除里面记录了完整的检测结果排查问题时比看Makefile图谱高效得多。6.2 xcb库版本冲突导致的“could not load platform plugin xcb”这是国产系统上出现频率最高的Qt运行时报错即使在编译阶段全部通过运行阶段也可能炸出来。我遇到的具体现象是程序启动时提示This application failed to start because no Qt platform plugin could be initialized. Available platform plugins are: eglfs, linuxfb, minimal, offscreen, xcb.排查链路分三步确认platforms/libqxcb.so存在不在就别谈用ldd libqxcb.so | grep not found检查它依赖的动态库是否有缺失用LD_DEBUGlibs ./myapp查看程序启动时实际加载了哪些Qt库路径确认是不是混进了系统自带的Qt库版本。xcb插件加载失败十有八九是第3步出了问题程序先加载了系统里旧版本的libQt5Core或者libxcb跟/opt/qt-5.12.12下刚编译的库冲突了。这种情况下的方案是把LD_LIBRARY_PATH清空让程序通过rpath走自己的目录或者在启动脚本里调整库搜索顺序把自己编译的目录放在最前面。6.3 关于这套Qt的生命周期维护心得最后说点编译之外的体会。自己编译Qt源码这件事看起来是个一次性工作实际上等于给自己维护了一条“软件供应链”。某系统V4的仓库里可能不会同步更新Qt补丁但只要源码包还在后续打补丁、改编译参数、更换架构重编都在可控范围内。我后来在另一个项目里要适配不同CPU平台重新编译同一套5.12.12源码只需要把configure参数里的相关架构选项调整一下其他流程基本照搬。这种可控性比从第三方源装二进制包踏实得多。如果你恰好也在类似场景里从今天开始自己编译Qt把关键步骤记下来你大概率会发现这条路走一次之后以后所有环境适配问题都不再是问题。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询