Ubuntu 20.04 x86环境下Qt 5.15.2源码编译完整指南
简介面向需要在 Ubuntu 20.04 x86 环境编译或使用 Qt 5.15.2 的 C 开发者这份资源整理了对应 Linux x86 平台源码包中的头文件集合解决了从源码树中反复查找 Qt 声明的痛点。压缩包采用 zip 格式包含 2000 个 .h 文件整体约 50.14MB预览显示覆盖 OpenGL 扩展、本地化、罗马日历、内存调试等方向同时涉及 Qt 核心、界面、网络等常用模块的接口声明目录结构保留 Qt 源码风格便于快速检索与引用可支撑源码级调试和二次开发。目前已有 99 人浏览学习适合希望快速搭建 Qt 5.15.2 开发环境或对照官方源码进行移植适配的研发人员。借助这组头文件使用者可以直接用于程序编写、编译链接与依赖校验省去逐个抽取文件的重复劳动结合 Qt 官方 configure/make 指南还能辅助定制模块编译、排查版本升级引发的头文件冲突为后续应用交付或环境重建提供较完整的文件基础也能降低项目团队在 Ubuntu 20.04 x86 下统一 Qt 版本和接口的成本。 最近又有朋友在群里问Ubuntu 20.04 下到底怎么把 Qt 5.15.2 用源码包编出来其实这个问题我之前也踩了不少坑特别是 x86 环境下的编译参数、依赖库缺失、还有编译完成之后 xcb 插件起不来这一类问题。如果直接下载离线包又动不动几个 GB而且 5.15 之后开源版本官方不再提供现成的二进制安装包自己从源码编译几乎成了唯一稳妥的路子。这篇文章就把我实际编译 Qt 5.15.2 源码包的完整过程、参数选型和避坑经验一起整理出来给同样需要在 Linux x86 环境Ubuntu 20.04下自己编译 Qt 的朋友一个能直接照着做的参考。1. 为什么选择 5.15.2 源码包自己编译1.1 版本选择的背后逻辑Qt 5.15 是 Qt 5 系列的长期支持版本LTS5.15.2 又是这个分支里比较稳定的一个补丁版本。相比 Qt 6.x5.15.2 在大量老项目和工业软件里仍然是主流很多工控、嵌入式、桌面应用的第三方库都基于这个版本做过适配。如果项目里依赖的模块还停留在 Qt 5 的 API 形态直接跳 Qt 6 往往要改不少代码所以选 5.15.2 是很务实的选择。但这里有个关键点从 Qt 5.15 开始开源版本不再提供官方预编译的二进制安装包你必须自己下载源码包在目标环境里编译。这也引出了另一个问题——为什么不用 apt 直接装Ubuntu 20.04 的官方软件源里确实有 qt5-default 和 qtbase5-dev但版本是 5.12.8和 5.15.2 差了三个小版本。如果只是写点简单 GUI 程序apt 里的 5.12 够用但如果你的项目依赖 5.15 才有的特性或者需要自己定制 Qt 的编译选项比如裁剪模块、启用特定平台插件那你只能走源码编译这条路。还有一个容易忽略的点apt 安装的 Qt 是 Ubuntu 发行版自己打的包某些补丁和配置和上游有差异偶尔会出现明明代码在 Windows 的 Qt 5.15 上正常到了 Ubuntu 的 5.12 上行为不一致的诡异问题。为了保持开发环境和生产环境一致源码编译 5.15.2 反而是省心的选择。1.2 x86 环境下的特殊考量标题里特别强调了 x86 环境这里要说明一下。通常说的 x86 在 Linux 下可能指 32 位i386也可能指 64 位x86_64/amd64大多数人实际用的是 64 位。如果你确实需要 32 位版本的 Qt 库那你要在 64 位 Ubuntu 20.04 上开启多架构支持并安装相应的 32 位依赖库这个复杂度会高不少。我的建议是除非你是在做 32 位嵌入式交叉编译或者兼容老旧硬件的开发否则统一用 64 位编译。原因很简单Ubuntu 20.04 官方源里很多开发库都已经逐步停止提供 32 位版本你折腾半天可能卡在某个依赖上。而且 Qt 5.15.2 在 64 位 x86 环境下的编译测试最充分遇到问题的概率最低。本文后面说的所有步骤都是针对 x86_64 架构。另外有些人会混淆“编译平台”和“运行平台”。源码包编译出来的 Qt 库默认是“本机运行”模式也就是在 x86_64 Ubuntu 20.04 上编译得到的也是 x86_64 的 Qt 库直接给当前系统的程序用。如果要做 ARM 平台的交叉编译那要单独配置交叉工具链那就不是本文说的范畴了。2. 编译前的依赖环境准备2.1 基础工具链安装源码编译 Qt 需要一整套完整的编译工具链很多朋友第一次编译失败就是因为在 configure 阶段缺了某个库然后报出一大堆看不懂的错误。我建议在动手前先一次性把基础依赖装好。打开终端先执行下面这条命令安装基础编译工具sudo apt update sudo apt install build-essential perl python3 git cmakebuild-essential 包含了 gcc、g、make 等核心工具这是编译 C 项目的基石。perl 是 Qt 构建系统运行脚本需要的python3 则是某些 Qt 工具模块必需的。git 和 cmake 有的场景不一定需要但建议一起装特别是后期你可能还要编译其他依赖库。这里有一个我实测过的细节Ubuntu 20.04 默认的 gcc 版本是 9.x这个版本编译 Qt 5.15.2 完全没有问题网上有些教程让你装 gcc 11 或者切换系统默认 gcc其实没有必要。反而切换 gcc 版本可能导致系统里某些软件依赖的 ABI 发生变化引发其他问题。老老实实用系统默认的 gcc 9 就好。2.2 Qt 编译必需的系统依赖库这一步是重中之重。Ubuntu 桌面环境下编译 Qt 的 GUI 模块需要一系列的底层图形和字体相关依赖。下面这个命令是我整理好的完整列表直接复制粘贴执行即可sudo apt install libgl1-mesa-dev libglu1-mesa-dev libegl1-mesa-dev \ libxkbcommon-dev libxkbcommon-x11-dev libfontconfig1-dev \ libdbus-1-dev libx11-dev libx11-xcb-dev libxext-dev \ libxfixes-dev libxi-dev libxrender-dev libxcb1-dev \ libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev \ libxcb-shm0-dev libxcb-icccm4-dev libxcb-randr0-dev \ libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev \ libxcb-xinerama0-dev libxcb-xkb-dev libxcb-cursor-dev \ libxcb-xv0-dev libxcb-xinput-dev libxcb-xrm-dev \ libxcb-render-util0-dev libxcb-util-dev libxcb-xkb-dev \ libssl-dev libfreetype6-dev libxinput2-dev libsm-dev \ libice-dev libxrandr-dev libxdamage-dev libxcomposite-dev \ libxcursor-dev libxinerama-dev libxft-dev libxss-dev这些库分别解决什么问题简单说一下libgl1-mesa-dev是 OpenGL 开发库Qt 的渲染引擎依赖它libfontconfig1-dev和libfreetype6-dev负责字体解析和渲染libxcb-*系列是 X11 的 C 绑定库Qt 的 xcb 平台插件必须要用到它们。如果这些库有缺失Qt 的 configure 检测阶段可能会自动禁用某些功能甚至直接报错退出。有一个常见误区是只在纯命令行环境无桌面环境下编译 Qt结果发现编译出来的程序无法显示界面。这是因为缺少了 X11 相关的头文件和库。即使你用的是无桌面版 Ubuntu 服务器只要目标程序需要 GUI 显示这些依赖库也一样要装。建议直接照单全收别想着“我不用这个功能就不装”省得后面来回折腾。2.3 需要额外注意的 OpenGL 相关依赖Qt 5.15 的渲染底层大量使用 OpenGL在 Ubuntu 20.04 下通常由 Mesa 提供实现。除了上面列出的 libgl1-mesa-dev你还需要确认系统里是否有可用的 OpenGL 运行库。执行下面的命令检查glxinfo | grep OpenGL version如果没有 glxinfo先安装 mesa-utilssudo apt install mesa-utils在正常的 Ubuntu 桌面环境里OpenGL 版本一般是 4.x。如果你运行的是虚拟机或者远程服务器输出可能是软件渲染llvmpipe这也不影响 Qt 编译但运行时性能会差一些。编译阶段只要头文件和开发库齐全就行OpenGL 的硬件加速能力是运行时才体现的。另外如果你后面要用 Qt WebEngine 模块比如 QWebEngineView那还需要额外装一些库包括 libnss3-dev、libxcomposite-dev、libxcursor-dev 等以及可能需要安装libxkbfile-dev和libxshmfence-dev。不过 WebEngine 模块编译耗时很长如果你只是做传统桌面应用我建议在 configure 时直接禁用 WebEngine省下大量编译时间。3. 源码获取与 configure 配置详解3.1 源码下载与目录规划Qt 官方源码包的下载地址是download.qt.io也可以在 GitHub 的 qt 仓库找到。因为我需要的是 5.15.2 完整源码包所以直接下载对应的 tar.xz 文件。我建议先把源码放到一个独立的目录里比如~/qt-src避免和系统其他文件混在一起。整个目录规划如下mkdir ~/qt-src cd ~/qt-src wget https://download.qt.io/archive/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz如果你的网络环境无法直接访问官方下载地址可以尝试用国内镜像源。下载完成后解压tar -xvf qt-everywhere-src-5.15.2.tar.xz cd qt-everywhere-src-5.15.2顺便说一句Qt 源码包解压后大概占用 3~4 GB 的磁盘空间包含 .git 信息如果下载的是 git 仓库版本会更大编译中间文件还会再占不少建议预留 15 GB 以上的磁盘余量。我之前第一次编译时没注意磁盘空间结果编译到一半报“磁盘空间不足”白白等了一个多小时。3.2 configure 参数选型与解释Qt 的构建流程是经典的三步configure、make、make install。第一步 configure 是整个编译过程中最关键也最容易出错的环节它的作用是检测系统环境、生成构建文件并决定启用或者禁用哪些 Qt 模块。对于 Ubuntu 20.04 x86_64 环境的 Qt 5.15.2我最终使用的 configure 命令是./configure -prefix /opt/Qt5.15.2 \ -release -opensource -confirm-license \ -xcb -xcb-xlib \ -qt-libpng -qt-libjpeg -qt-zlib \ -no-openssl -no-webengine \ -nomake examples -nomake tests \ -skip qtwebengine -skip qtwayland我来逐项解释这些参数的作用-prefix /opt/Qt5.15.2指定 Qt 安装的最终目录。编译完成后所有的库、头文件、工具都会安装到这个目录下。选/opt下是为了和其他软件隔离也方便后续配置环境变量。-release编译发布版本不带调试符号体积更小、运行效率更高。如果你需要调试 Qt 源码本身可以改成-debug-and-release但编译时间会翻倍。我平时的做法是先编译 release反正调试时主要调试的是自己的程序代码Qt 库用 release 也够用。-opensource -confirm-license确认使用开源协议避免 configure 过程中停下来询问。-xcb -xcb-xlib启用 xcb 平台插件。这个插件是 Qt 程序在 Linux 桌面环境下显示的桥梁少了它编译出来的 Qt 程序在大多数桌面环境根本没法启动而且大概率报could not load the xcb plugin之类的错误。-qt-libpng -qt-libjpeg -qt-zlib使用 Qt 自带的这些基础库。用自带版本的好处是避免和系统库版本冲突尤其是如果你将来要在多种发行版上部署。-no-openssl禁用 OpenSSL 支持。如果你的程序需要 HTTPS 网络请求建议去掉这个参数改为-openssl-linked并确保系统安装 libssl-dev。我这边项目不需要所以直接禁用加快编译。-no-webengine和-skip qtwebengine这两个都是为了跳过 WebEngine 模块。Qt WebEngine 编译时间巨长还特别吃内存如果不做浏览器内核相关开发建议跳过。注意-skip参数用的是模块名qtwebengine它后面没有.x后缀写错了会导致配置报错。-nomake examples -nomake tests不编译示例程序不编译测试程序这两项可以省掉不少编译时间。configure 命令执行后它会自动检测系统库并输出一份摘要告诉你哪些模块会编译、哪些会被跳过。你一定要仔细看这段输出特别是标记为no的关键模块确认是不是自己需要的。3.3 最小化配置和完整配置的选择有的朋友会问那这个 configure 参数能不能再精简一点比如直接./configure -prefix /opt/Qt5.15.2 -opensource -confirm-license行不行答案是可以但不推荐。默认配置下Qt 会尝试编译所有模块包括 WebEngine、Wayland、虚拟键盘等等不仅编译时间大幅增加可能从半小时拉到两三个小时还更容易因为某个模块缺依赖而报错。而且很多模块就算编译出来了你的项目里也根本用不到白占磁盘空间。反过来如果你过度精简比如加了-no-gui那连 Qt Widgets 都没了GUI 程序就别想写了。我的经验是先用一个较完整的配置编译一次把构建环境跑通后续如果需要新增模块再进行增量编译。Qt 的构建系统支持模块级别的增量编译不需要每次全部重来。这里还推荐一个辅助配置在 configure 时加上-verbose参数它会输出详细的检测日志遇到问题的时候方便排查。不过正式编译的时候建议去掉否则日志会非常烦人。4. 编译安装与常见报错处理4.1 多线程编译与内核参数选择configure 顺利通过之后就是漫长的 make 阶段。Qt 5.15.2 的源码量非常大单线程编译可能要四五个小时所以一定要用多线程编译。通用的做法是用-j参数指定编译线程数。make -j$(nproc)nproc命令会返回你 CPU 的逻辑核心数。比如 8 核 16 线程的 CPU就是make -j16。不过这里有一个容易忽略的坑编译 Qt 是一个非常吃内存的操作如果你的内存不足 16 GB直接用满核心数编译大概率会在某个文件编译时触发 OOM内存耗尽编译器进程被系统杀掉然后整次编译失败。我之前在一台 4 核 8 GB 内存的机器上编译就是make -j8直接干爆了内存。后来老老实实改成make -j4虽然慢了一些但稳定多了。所以建议内存小于 16 GB 的话用make -j4或者make -j2稳字当头。编译过程中屏幕上会滚动大量的编译信息这是正常的。但注意观察有没有Error字样一旦出现 error 编译会中断。如果不小心中断了不用慌重新执行make会从断点继续Qt 的构建系统会跳过已经编译好的部分。4.2 安装与环境变量配置编译完成后执行安装命令sudo make install安装到/opt/Qt5.15.2需要 root 权限所以加sudo。安装完成后验证一下/opt/Qt5.15.2/bin/qmake --version如果输出了QMake version 3.1 Using Qt version 5.15.2之类的信息说明安装成功。这时还差最后一步配置环境变量让系统能够找到 qmake 和 Qt 库。编辑用户环境变量文件vim ~/.bashrc在文件末尾追加以下内容export PATH/opt/Qt5.15.2/bin:$PATH export LD_LIBRARY_PATH/opt/Qt5.15.2/lib:$LD_LIBRARY_PATH export QT_PLUGIN_PATH/opt/Qt5.15.2/plugins export QT_XCB_GL_INTEGRATIONxcb_glx保存后执行source ~/.bashrc使配置生效。第一条 PATH 让命令行能找到 qmake第二条 LD_LIBRARY_PATH 让系统运行时能找到 Qt 的动态库第三条 QT_PLUGIN_PATH 告诉 Qt 平台插件在哪里第四条是让 xcb 插件优先使用 GLX 集成方式这在某些显卡驱动下可以避免渲染异常。关于环境变量有两点要提醒第一如果你系统里之前用 apt 装过 Qt 5.12那么新旧版本的 Qt 会在 PATH 里打架。建议/opt/Qt5.15.2/bin放在 PATH 最前面保证qmake优先指向新版。第二LD_LIBRARY_PATH 对系统全局影响比较大如果你有多套 Qt 环境更推荐在 QtCreator 的构建环境里单独设置而不是全局 export。4.3 高频报错与排查方法编译过程中我踩过的、以及周围朋友遇到过的典型问题挑几个高频的整理出来第一个是 configure 阶段报缺少 XCB 相关库错误提示类似Could not find XCB。这个几乎都是因为 xcb 系列依赖库没装全。解决方案就是回到第 2.2 节那个大命令把所有 libxcb-*-dev 都装上再重新 configure。注意重新 configure 之前最好先把之前生成的构建文件清理掉执行make clean或者干脆删除解压目录重新解压否则残留的检测结果可能导致新的依赖库仍然被忽略。第二个是编译过程中卡在某个文件上CPU 占用率掉到 0长时间没有输出。这种情况一般是编译进程被 OOM 杀了或者某个子进程死锁。可以先看下系统日志dmesg | grep -i killed process确认是不是内存不足。解决办法是降低 -j 的并行数重新 make。如果频繁在同一个文件上报错比如某个头文件找不到可以检查是不是系统头文件版本太旧考虑sudo apt upgrade先升级系统包。第三个是编译完成之后写的程序启动时报错找不到 xcb 插件This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.这个问题有几种可能一是QT_PLUGIN_PATH环境变量没设置Qt 找不到插件目录二是编译时-xcb相关参数没配好插件虽然编译了但依赖的 xcb 库缺失三是/opt/Qt5.15.2/plugins/platforms目录下没有libqxcb.so文件。排查顺序先查看 plugins/platforms 目录下有没有 libqxcb.so然后ldd libqxcb.so检查依赖的 xcb 库是否都解析成功有not found就对症补装。最后确认环境变量指向的目录正确这招我帮朋友排查过好几次基本都是这三个原因。第四个是在 build 过程中出现Cannot find -lGL之类的链接错误。这是因为系统缺少 OpenGL 库。执行sudo apt install libgl1-mesa-dev就可以解决。如果是 32 位的这个问题还需要额外安装libgl1-mesa-dev:i386。5. xcb 插件和运行环境验证5.1 编译后的快速验证程序安装配置完成后不要急着把 Qt 集成进大项目建议先创建一个小程序验证整套环境是否正常工作。用命令创建一个简单项目mkdir ~/qt-test cd ~/qt-test vim main.cpp写入最简单的 Qt Widgets 程序#include QApplication #include QLabel int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label(Hello Qt 5.15.2 on Ubuntu 20.04); label.resize(320, 120); label.show(); return app.exec(); }然后用 qmake 构建qmake -project qmake make执行./qt-test如果屏幕上弹出一个窗口显示Hello Qt 5.15.2 on Ubuntu 20.04那说明 Qt 编译和运行环境全部正常。如果没有桌面环境你也可以用QT_QPA_PLATFORMoffscreen ./qt-test在无界面模式下测试程序能否正常启动这个环境变量会强制 Qt 使用离屏渲染插件不依赖 X11 显示。一个小技巧如果你希望能显示更详细的 Qt 启动日志可以在运行时加export QT_DEBUG_PLUGINS1。这个环境变量会让 Qt 输出所有插件加载过程的信息排查问题非常有帮助。不过正式项目里不要这么设它会影响性能且日志太啰嗦。5.2 运行时依赖与部署注意事项自己编译的 Qt 有一个特点它默认是动态链接的而且依赖的 Qt 库都在/opt/Qt5.15.2/lib目录下。当你要把编译好的程序部署到另一台机器上时目标机器也必须要有 Qt 的动态库否则会报error while loading shared libraries。最简单的部署方式是把程序打包发布时用ldd找出所有 Qt 相关的 so 文件一起拷贝到目标机器并配置好LD_LIBRARY_PATH。但手动处理效率很低推荐用官方提供的linuxdeployqt工具来打包它能自动收集依赖并生成 AppImage 格式的可执行文件。有一点要特别注意如果你编译时刻意禁用了 OpenSSL比如我上面加了-no-openssl那你的程序如果用了 QSslSocket 相关功能运行时会有异常。这个跟部署无关纯粹是编译选项的限制。所以如果你的项目可能通过 HTTPS 访问网络建议 configure 时把-no-openssl改成-openssl-linked并确保系统libssl-dev已安装否则运行时会提示qt.network.ssl: QSslSocket: cannot resolve这样的错误。5.3 多版本 Qt 共存管理前面提到 Ubuntu 2004 系统里可能有 apt 装的 Qt 5.12很可能还有 Python 绑定的 PyQt5多个 Qt 版本很容易搞混。我的建议是在项目里尽量使用 CMake 而不是 qmake因为 CMake 里可以明确指定 Qt 的路径。举个例子在 CMakeLists.txt 里这样写set(CMAKE_PREFIX_PATH /opt/Qt5.15.2) find_package(Qt5 REQUIRED COMPONENTS Widgets)这样 CMake 会优先在/opt/Qt5.15.2下查找 Qt 5.15.2 的 cmake 配置文件不会和其他版本冲突。另外也可以用 QtCreator 里自带的 Kit 管理功能在 Qt Versions 页面手动添加/opt/Qt5.15.2/bin/qmake然后在构建套件里指定这样不同项目可以独立指定不同的 Qt 版本互不干扰。如果你只是临时用某个版本跑一下命令可以在终端里手动指定/opt/Qt5.15.2/bin/qmake --version这样就不需要频繁修改 PATH 环境变量了。多版本共存最忌讳的就是全局环境变量改来改去规范的做法是把环境配置下沉到项目级或者直接写入 QtCreator 的构建环境里。6. 常见问题速查与个人踩坑纪录为了便于大家快速定位问题我把编译过程中遇到频率比较高的错误汇总成一个速查表方便直接对照排查错误现象可能原因解决方案configure 报 Could not find XCBxcb 开发库缺失安装第 2.2 节全部 libxcb-*-dev 包后重新 configure编译中途进程被杀内存不足OOM降低 make -j 并行数或增加 swap 空间找不到 -lGLOpenGL 开发库缺失sudo apt install libgl1-mesa-dev运行时报 no platform pluginQT_PLUGIN_PATH 未配置或插件缺失检查 plugins/platforms/libqxcb.so 是否存在配置环境变量程序提示无法加载 xcb 插件插件依赖的 xcb 库缺失ldd /opt/Qt5.15.2/plugins/platforms/libqxcb.so查找 not found 并安装对应库HTTPS 请求报 QSslSocket 错误编译时禁用了 OpenSSL重新 configure 使用 -openssl-linkedqmake 指向系统旧版本PATH 顺序问题确认 /opt/Qt5.15.2/bin 在 PATH 最前面再说一个我自己的实际经验第一次全程编译 qtopensource 源码包时configure 阶段我少装了一个libxkbcommon-x11-dev导致编译出来的 xcb 插件虽然生成了但运行时一直报错查了整整半天才找到原因。这里有一个技巧configure 完成后在config.summary文件里能看到 xcb 插件是否被启用如果显示xcb ......... no那说明 xcb 编译被跳过了重点检查 xcb 相关的依赖库是否完整。还有一次我在编译时使用了-j16结果系统直接卡死重启后重新编译又花了一个多小时。从那以后我在编译大项目之前都会先检查内存余量用free -h看看可用内存再决定并行线程数。如果内存只有 8 GB建议加一块 swap 或者老老实实用-j4。顺便说一句编译过程中不要随意中断虽然 Qt 构建系统支持断点续编但有时候残留的中间文件反而会干扰后续编译遇到无法确定的错误时最稳妥的办法是清理整个解压目录重新来一遍。另外一个常见疑问是能否把/opt/Qt5.15.2整个目录拷贝到其他机器上直接用。答案是部分可以但前提是目标机器的系统库版本要兼容尤其是 glibc 版本不能比编译时的系统旧。最简单的判断方式就是用ldd /opt/Qt5.15.2/lib/libQt5Core.so.5看看依赖哪些系统库但要完全保证兼容性比较难所以跨机器部署建议还是在目标机器上重新编译或者用 linuxdeployqt 打包成 AppImage 格式。AppImage 把 Qt 库都打包在一起对宿主系统的依赖很少是分发 Qt 程序比较省心的方案。写在最后Qt 5.15.2 源码包编译这件事实在算不上难但它考察的是对整个构建链路的理解程度。依赖装好、configure 参数搞明白、编译并行度控制好基本就不会有太大问题。希望这篇整理能让你少走一些弯路如果你在编译过程中遇到其他奇怪的报错欢迎留言交流我看到了会尽量帮忙分析。本文还有配套的精品资源点击获取