
1. 项目概述为什么我们需要自己动手编译一个“完整版”Qt如果你正在维护一个使用了QtWebEngine模块的桌面应用或者你的项目文档需要依赖QDoc来生成那么你很可能已经遇到了一个头疼的问题从Qt官方渠道下载的预编译二进制包无论是离线安装器还是在线安装工具默认都不包含QtWebEngine和QDoc这两个模块。这绝不是偶然的疏忽而是因为这两个模块的编译过程极其复杂、耗时漫长且对系统环境有特殊要求。官方为了提供开箱即用的轻量级体验默认就把它们“阉割”掉了。我最近就踩了这个坑。项目需要升级到Qt 5.15.17这个长期支持版本但我们的应用内嵌了一个基于WebEngine的浏览器组件用于展示一些动态图表和富文本内容。当我兴冲冲地从官网下载了安装包配置好项目后编译器无情地报错找不到QWebEngineView的头文件。那一刻我才意识到预编译的“便利”背后隐藏着功能缺失的代价。对于依赖特定模块的开发者来说自己动手从源码编译一个“完整版”的Qt从一项可选的技能变成了必须掌握的生存技能。自己编译Qt听起来很吓人尤其是涉及到Chromium内核的QtWebEngine。网上零散的教程要么年代久远要么语焉不详或者只讲了一半。我花了整整一周时间在Windows和Linux系统上反复试验踩遍了能踩的坑终于梳理出了一套稳定、可复现的完整编译流程。这篇文章就是这份经验的完整记录。它不仅会带你一步步走通编译流程更会深入解释每个步骤背后的“为什么”以及那些官方文档里不会写的“坑”在哪里。无论你是为了项目需求还是想深入学习Qt的构建系统这篇文章都能给你一个扎实的起点。2. 编译前的深度准备环境、源码与工具链的精准配置编译Qt尤其是包含QtWebEngine绝不是简单的configure make。它更像是一场精密的“外科手术”术前准备决定了手术的成败。这一步的疏忽会导致后续编译过程中出现各种光怪陆离的错误且极难排查。2.1 系统环境与依赖库的彻底清查首先我们必须为编译准备好一个“洁净”且“功能齐全”的操作系统环境。这里的“洁净”不是指新装系统而是指没有残留的、可能冲突的旧版Qt库或构建工具。“功能齐全”则意味着必须安装所有必要的编译依赖。对于Linux系统以Ubuntu 20.04/22.04为例这是编译体验相对较好的平台。你需要安装一长串的开发库。打开终端执行以下命令来安装基础编译工具和核心依赖sudo apt update sudo apt install build-essential libgl1-mesa-dev libglu1-mesa-dev -y接下来是QtWebEngine的重度依赖它基于Chromium因此需要Chromium构建所需的各种库sudo apt install bison flex gperf libnss3-dev libdbus-1-dev libfontconfig1-dev libx11-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libx11-xcb-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev -y此外还需要音频、视频、网络等多媒体支持库sudo apt install libasound2-dev libpulse-dev libssl-dev libicu-dev libavcodec-dev libavformat-dev libswscale-dev libevent-dev libminizip-dev libre2-dev libsnappy-dev libwebp-dev libopus-dev libvpx-dev libxml2-dev libxslt1-dev liblcms2-dev libopenjp2-7-dev -y注意以上列表看起来冗长但缺一不可。例如缺少libwebp-dev可能导致WebP图片支持编译失败缺少libre2-devGoogle的正则表达式库会直接导致QtWebEngine配置阶段报错。建议一次性安装完毕避免后续因依赖问题中断编译。对于Windows系统Windows下的编译环境搭建更为复杂因为缺乏统一的包管理器。官方推荐使用MSVC编译器套件。你需要安装Visual Studio 2019或2022社区版即可。安装时务必在“工作负载”中勾选“使用C的桌面开发”并在右侧的“安装详细信息”中确保选中了“MSVC v142 - VS 2019 C x64/x86 生成工具”和“Windows 10 SDK”或Windows 11 SDK。这是编译器的核心。安装PythonQt构建系统大量使用Python脚本。从Python官网安装3.7以上版本如3.9安装时务必勾选“Add Python to PATH”将Python添加到系统环境变量。安装Perl用于处理一些自动化脚本可以从Strawberry Perl或ActiveState Perl官网下载安装。安装Git用于获取子模块源码特别是QtWebEngine的Chromium代码。2.2 源码获取不仅仅是下载一个压缩包Qt的源码管理采用了Git子模块Submodule的方式这意味着主仓库只包含框架代码像QtWebEngine这样的模块其庞大的Chromium代码是以子模块形式链接的。如果你直接下载官网的.tar.xz源码包通常不包含子模块代码或者包含的是过时的快照这会导致编译失败。正确的方法是使用Gitgit clone https://code.qt.io/qt/qt5.git cd qt5 git checkout v5.15.17-lts-lgpl # 切换到5.15.17的LTS标签接下来是关键一步初始化并更新子模块。由于QtWebEngine的子模块非常庞大超过10GB直接更新会非常慢且可能失败。这里需要一个技巧使用--depth 1参数进行浅克隆只获取最新的一次提交可以极大减少下载量。perl init-repository --module-subsetqtbase,qtwebengine,qtdoc这里我使用了--module-subset参数只初始化我们关心的核心模块qtbase、目标模块qtwebengine, qtdoc及其直接依赖。这比初始化全部模块要快得多。执行此命令后脚本会自动克隆所需的子模块仓库。实操心得网络是这一步骤最大的敌人。由于需要从code.qt.io和chromium.googlesource.com等地址拉取代码国内环境可能会非常缓慢甚至超时。建议配置可靠的网络环境或者寻找包含子模块的国内镜像源码包。如果init-repository中途失败可以进入对应的子模块目录如qtwebengine/src/3rdparty手动执行git fetch和git checkout来补救。2.3 编译目录的规划构建与源码分离这是一个重要的最佳实践不要在源码目录内直接进行编译in-source build。应该创建一个独立的构建目录out-of-source build。这样做的好处是保持源码目录的纯净你可以随时删除构建目录重新开始或者针对不同的配置如Debug/Release不同编译器创建多个构建目录而互不干扰。假设你的源码目录是/home/user/qt-src你可以这样操作mkdir /home/user/qt-build cd /home/user/qt-build后续所有的配置configure和编译make命令都在这个qt-build目录下执行而configure脚本则指向源码目录的路径。3. 配置阶段详解理解每一个参数的意义进入我们创建的构建目录现在开始最关键的一步配置。configure脚本会根据你的参数生成适合你平台的Makefile。参数的选择直接影响编译的模块、功能以及最终库的形态。一个针对Linux系统包含QtWebEngine和QDoc的典型配置命令如下../qt-src/configure -prefix /opt/Qt5.15.17-full \ -opensource \ -confirm-license \ -release \ -optimize-size \ -nomake examples \ -nomake tests \ -skip qtvirtualkeyboard \ -webengine-proprietary-codecs \ -webengine-icu \ -webengine-ffmpeg \ -ssl \ -opengl desktop让我们拆解每一个参数-prefix /opt/Qt5.15.17-full指定编译后Qt的安装路径。编译完成后执行make install会将所有库、头文件、工具安装到这个目录。请确保你有该目录的写入权限通常需要sudo或者换成一个你有权限的路径如$HOME/Qt5.15.17。-opensource和-confirm-license声明使用开源协议并自动确认许可。-release编译发布版本。如果你需要调试符号可以换成-debug或-debug-and-release但这会显著增加编译时间和磁盘占用尤其是对于庞大的QtWebEngine。-optimize-size进行尺寸优化。对于发布版本是个好选择。-nomake examples和-nomake tests不编译示例和测试程序。这能节省大量时间。除非你需要参考示例否则建议加上。-skip qtvirtualkeyboard跳过虚拟键盘模块。这是一个可选模块如果你不需要可以跳过以加快编译。-webengine-proprietary-codecs关键参数。启用对H.264、AAC等专利编解码器的支持。没有这个参数你的QtWebEngine将无法播放绝大多数在线视频如MP4格式。启用它可能需要你自行承担潜在的专利许可风险在商业应用中需注意。-webengine-icu和-webengine-ffmpeg启用ICUUnicode支持和FFmpeg多媒体处理支持。对于完整的Web功能是必须的。-ssl启用SSL/TLS支持使网络访问和WebEngine能打开HTTPS网站。-opengl desktop使用系统原生的OpenGL库。在Linux上通常这样指定。对于Windows平台在x64 Native Tools Command Prompt for VS 2019/2022中运行配置命令类似但有一些平台特定项..\qt-src\configure -prefix C:\Qt\5.15.17-full ^ -opensource ^ -confirm-license ^ -release ^ -platform win32-msvc ^ -mp ^ -nomake examples ^ -nomake tests ^ -skip qtvirtualkeyboard ^ -webengine-proprietary-codecs ^ -webengine-icu ^ -webengine-ffmpeg ^ -ssl ^ -opengl desktop区别在于-platform win32-msvc指定使用MSVC平台工具链。-mp启用多进程编译充分利用多核CPU。执行configure脚本后它会花几分钟时间检测你的系统环境、检查依赖并最终输出一个配置摘要。请务必仔细阅读这个摘要它会明确告诉你哪些特性被启用yes哪些被禁用no原因是什么。重点关注以下几行Qt WebEngine .......................... yesQt WebEngine Proprietary Codecs ........ yes(如果你指定了)Qt Documentation Tools (QDoc) .......... yes如果这里显示no说明配置失败你需要根据上面的提示信息通常是缺少某个开发库去解决依赖问题然后重新运行configure。4. 编译与安装一场对耐心和硬件的考验配置成功后就可以开始编译了。这将是整个过程中最耗时的一步尤其是QtWebEngine模块。4.1 核心编译流程与资源管理在构建目录下执行编译命令。强烈建议使用-j参数来指定并行编译的作业数这能极大缩短时间。作业数通常设置为你的CPU核心数或核心数1。对于Linuxmake -j$(nproc)$(nproc)命令会自动获取你的CPU核心数。对于Windows在刚才的命令行中nmakeMSVC的nmake本身不支持-j参数但我们在configure时已经加了-mp它内部会进行并行优化。编译过程可能持续数小时具体取决于你的CPU性能、内存大小和磁盘速度尤其是IO性能。QtWebEngine的编译会占用大量内存建议16GB以上和磁盘空间整个构建目录可能膨胀到30-40GB。注意事项编译过程中请确保系统有足够的剩余内存和磁盘空间。如果内存不足编译进程可能会被系统杀死出现Killed或exit code 137错误。如果磁盘空间不足编译会失败并报错。建议在开始前至少保证有50GB的可用磁盘空间。4.2 安装与环境配置编译成功后没有报错地结束就可以进行安装了# Linux 下可能需要sudo取决于-prefix路径 sudo make install # Windows 下 nmake install安装过程会将编译好的所有库、可执行文件如qmake、QDoc、头文件、插件等复制到configure时指定的-prefix目录下。安装完成后你需要配置你的开发环境来使用这个新编译的Qt版本。配置Qt Creator打开Qt Creator进入工具-选项-Kits-Qt Versions点击“添加”然后浏览到你的安装目录如/opt/Qt5.15.17-full或C:\Qt\5.15.17-full选择其中的bin/qmake可执行文件。添加成功后在Kits标签页中为你已有的Kit选择这个新添加的Qt版本即可。命令行使用如果你想在命令行中使用这个Qt需要设置环境变量。在Linux的~/.bashrc或Windows的系统环境变量中将QTDIR设置为你的安装路径并将$QTDIR/binLinux或%QTDIR%\binWindows添加到PATH环境变量中。4.3 验证编译成果安装和配置完成后必须进行验证。验证QtWebEngine创建一个最简单的测试程序// main.cpp #include QApplication #include QWebEngineView int main(int argc, char *argv[]) { QApplication app(argc, argv); QWebEngineView view; view.setUrl(QUrl(https://www.qt.io)); view.show(); return app.exec(); }用你新编译的Qt Kit来编译运行这个程序。如果能看到Qt官网页面正常加载说明QtWebEngine编译成功且工作正常。验证QDocQDoc是用于从源码注释生成文档的工具。安装后它位于安装目录/bin/qdoc。你可以在命令行中运行qdoc --version来检查是否可用。更进一步的验证可以尝试用它编译一个简单的.qdocconf配置文件来为你的项目生成文档。5. 疑难杂症与深度排错指南自己编译Qt尤其是包含QtWebEngine遇到问题是常态。下面是我在多次编译中遇到的典型问题及其解决方案。5.1 编译过程中的常见错误与解决问题一编译QtWebEngine时卡在“Running ninja...”或“Submodule ‘src/3rdparty’ is outdated”现象编译进程长时间无响应或直接报错子模块过时。原因QtWebEngine的Chromium代码子模块没有正确初始化或更新。解决确保之前用init-repository正确初始化了子模块。进入qtwebengine源码目录手动同步子模块cd /path/to/qt-src/qtwebengine git submodule sync git submodule update --init --recursive --depth 1如果网络问题严重可以考虑寻找包含完整子模块的国内镜像源码包。问题二编译时报错提示缺少libxxx-dev或xxx.h: No such file or directory现象编译中断错误信息明确指出缺少某个头文件或库。原因系统缺少必要的开发依赖包。解决这是Linux编译中最常见的问题。根据错误信息中的库名或头文件名使用apt search或apt-file search命令查找对应的开发包并安装。例如错误提示libwebp/libwebp.h找不到那就安装libwebp-dev。这就是为什么在准备阶段强调要安装全依赖。问题三内存不足OOM Killer导致编译进程被杀死现象编译过程中终端突然显示Killed或者make进程以错误代码137退出。原因系统物理内存和交换空间swap不足Linux内核的OOM Killer终止了最耗内存的进程通常是编译QtWebEngine的clang或链接器。解决临时方案减少并行编译作业数。将make -j$(nproc)改为make -j2或make -j1虽然慢但能大幅降低内存峰值。根本方案增加交换空间。如果是在虚拟机或云服务器上编译务必分配足够的内存建议16GB和交换空间8GB-16GB。# 创建一个8GB的交换文件 sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 使其永久生效编辑/etc/fstab添加/swapfile none swap sw 0 0问题四Windows下编译QtWebEngine时ninja报错“unsupported GNU version! gcc versions later than 8 are not supported!”现象在Windows上使用MSVC编译但QtWebEngine的Chromium部分在调用某些工具时遇到了系统中安装的MinGW或Cygwin的gcc版本过高。原因Chromium的某些工具链脚本对GCC版本有特定限制而你PATH环境变量中可能存在新版的GCC例如如果你安装了MinGW-w64或Cygwin。解决临时从PATH中移除包含高版本GCC的路径如MinGW、Cygwin的bin目录。或者尝试安装一个较旧版本的GCC如7.x或8.x并将其路径放在PATH的前面。但这在Windows上比较麻烦。更推荐的方法使用“x64 Native Tools Command Prompt for VS”进行编译这个环境默认配置了纯净的MSVC工具链不会混入GCC。确保在这个命令行中where gcc命令找不到任何结果。5.2 配置参数导致的特性缺失问题编译出的程序无法播放MP4视频原因在configure时没有添加-webengine-proprietary-codecs参数。解决没有补救办法必须重新配置和编译。这就是为什么在配置阶段要反复确认摘要信息。如果你不确定是否需要某个功能特别是-webengine-proprietary-codecs和-webengine-ffmpeg建议先加上。重新编译的代价是巨大的。5.3 安装后运行时的问题问题程序运行时找不到QtWebEngine相关的插件或资源现象程序能启动但Web页面空白或控制台输出找不到qtwebengine_resources.pak等文件。原因Qt的插件和资源文件没有被正确部署。make install有时可能不会复制所有必要的运行时文件或者你的程序没有在正确的路径下寻找它们。解决检查安装目录下是否存在plugins/platforms,plugins/printsupport,resources等目录及其中的文件。对于开发阶段在Qt Creator中运行环境通常会自动设置好。对于独立发布的应用你需要使用windeployqtWindows或类似的部署工具来收集所有依赖库和资源文件。确保部署工具调用的是你新编译的Qt版本对应的那个。手动将安装目录下的libQt5WebEngineCore.so.5Linux或Qt5WebEngineCore.dllWindows及其依赖、以及resources目录复制到你的可执行文件同级目录下。6. 编译后的优化与定制思考成功编译并验证后你获得的是一个完全符合你需求的Qt SDK。但这并不是终点这里还有一些进阶的思考方向。1. 调试符号与发布版本的权衡我们之前用的是-release配置。如果你需要调试Qt框架本身的代码比如追踪一个QtWebEngine的内部崩溃你需要编译一个带有调试符号的版本。可以使用-debug或-debug-and-release。但请注意带有调试信息的QtWebEngine库文件大小会膨胀数倍编译时间也会更长。一个折中的方案是只编译你关心的模块如qtbase和qtwebengine的调试版本其他模块用发布版本。这需要对Qt的模块化编译有更深的理解可以通过在configure后单独进入qtbase和qtwebengine目录进行make sub-src仅编译该模块来实现但模块间的依赖需要妥善处理对新手不友好。2. 模块化裁剪Qt是一个庞大的框架你的项目可能只用到了其中一小部分。通过configure的-skip参数你可以跳过那些你永远用不到的模块如Qt3D, QtBluetooth, QtNfc等这能显著减少编译时间和最终安装包的大小。研究一下configure -help的输出了解所有可用的模块根据你的项目需求进行精细化的裁剪。3. 交叉编译本文主要聚焦于本地编译为当前使用的机器编译。但在嵌入式开发中你需要为ARM等不同架构的硬件编译Qt。这就需要配置交叉编译工具链通过-xplatform参数指定。交叉编译QtWebEngine是另一个层次的挑战因为它涉及为目标架构编译整个Chromium对工具链和环境的要求极为苛刻。通常嵌入式平台会使用更轻量级的浏览器引擎如基于WebKit的QtWebKit但Qt 5.15后官方已不维护或者直接使用系统提供的Web视图。4. 持续集成CI自动化对于团队项目将Qt的编译流程脚本化并集成到CI/CD管道中如GitLab CI, Jenkins可以确保所有开发者使用完全一致的Qt环境避免“在我机器上是好的”这类问题。你需要将环境准备、源码获取、配置、编译、安装打包等一系列步骤写成脚本。关键是要处理好依赖安装和缓存如编译好的第三方库以缩短CI的运行时间。我个人在实际操作中的体会是第一次完整编译Qt5.15.17 with WebEngine更像是一次“洗礼”。它迫使你去理解构建系统的运作、去解决复杂的依赖、去耐心等待漫长的编译过程。但一旦成功你获得的不仅仅是一个可用的Qt库更是一种对底层构建链的掌控感和解决问题的信心。以后遇到任何与Qt环境相关的问题你都不会再感到畏惧因为你知道如何从源码开始构建一个完全属于自己的、稳固的基础。