☰
Windows源码编译QGIS 3.34.10:从CMake到Ninja的完整实践
2026/10/2 9:10:42 网站建设 项目流程

1. 为什么要自己动手编译一次 QGIS 3.34.10

在 Windows 10 上把 QGIS 3.34.10 从源码编译出来,这事做之前看起来简单,做的时候才发现坑全在细节里。绝大多数人日常用 QGIS,都是去官网下载一个 exe,双击装完直接开用,没必要碰源码。但如果你开始关注插件开发、C++ 二次开发,或者想要长期依赖一个不被别人编译参数左右、自己能完全把控的版本,那源码编译就是绕不开的一步。

QGIS 3.34 属于长期支持版(LTR),意味着官方维护周期更长、发布更克制,适合企业级项目和生产环境。3.34.10 是这一系列里的一个补丁版本,修复了不少稳定性问题。其实官方也提供 OSGeo4W 这种包管理器,勾选安装之后同样能拿到相对完整的开发环境,但“能用”和“自己能完整编译一遍”是两回事。自己编译一次,至少能确定几件事:依赖栈是怎么串起来的、哪些第三方库参与了构建、CMake 配置里每个开关到底影响什么,以及出了问题能否从源码层面定位。

我自己的感受是,Windows 平台编译 QGIS 比 Linux 麻烦,但远没有想象中那么可怕。核心难点不在 C++ 编译本身,而是在于依赖的版本匹配和工具链一致性。只要把这三件事理顺:MSVC 编译器、OSGeo4W 依赖栈、CMake 配置,整个流程就能跑通。不夸张地说,这才是了解 QGIS 架构的“最短路”。

这篇记录面向的读者有两类:一类是想给 QGIS 扩展自定义模块,需要从源码构建开发环境的开发者;另一类是刚接触地理信息软件的运维或测试人员,想验证官方 LTR 版本的源码可靠性。文中会把我在实际构建过程中的完整步骤、参数选择、报错排查都写出来,尽量让第一次接触的人也能顺着路径复现。

2. 环境准备与工具链选型

2.1 编译器选择:尽量别混用 MinGW 和 MSVC

QGIS 在 Windows 上官方推荐的构建方式是 MSVC 配合 OSGeo4W 依赖库,不建议混用不同编译器的产物。原因是 C++ 的 ABI 在不同编译器之间不兼容,OSGeo4W 里的第三方库大多是按 MSVC 或 MinGW 分别发布的,混着链接会出现形形色色的链接错误,比如找不到符号、运行时崩溃、内存布局不一致。

所以我的建议是:直接用 Visual Studio 2019 或 2022 的 MSVC 编译器,配上 Ninja 构建系统。不用打开 Visual Studio 的完整 IDE,只需要装好“使用 C++ 的桌面开发”工作负载,让系统里有 cl.exe 和 Windows SDK 即可。QGIS 3.34 的代码基于 C++17,对编译器版本有一定要求,MSVC 2019 16.x 以上都行,我用 VS2019 实测没有问题。

如果你机器上同时装了 MinGW、MSYS2 或 Cygwin,构建前最好确认 PATH 环境变量里没有被它们先入为主。特别是 OSGeo4W 的 shell 里,某些辅助工具会依赖 Unix 命令,但交叉编译环境很容易污染 CMake 的探测结果。我在最开始就吃过这个亏,cmake 探测时找错了编译器,中途立刻停止重来,也算少走了一段弯路。

2.2 OSGeo4W 依赖栈准备

QGIS 不是一个人能轻松从头编译的纯单体软件,它依赖 GDAL、PROJ、GEOS、Qt 5、QScintilla、Expat、SQLite3、GSL 等一批地理空间和界面库。Windows 上没有各发行版的软件仓库那么方便,最可靠的办法就是安装 OSGeo4W,从它提供的包统一取依赖。

OSGeo4W 的安装器界面看起来有点老,但完全可以接受。建议选择“高级安装”,在“选择包”阶段切换到“完整”或“自定义”,然后勾选我下面列出的这些包:

分类包名作用
基础工具cmake, ninja, bison, flex构建系统生成和语法扫描
核心库gdal-dev, proj-dev, geos-dev空间数据读写、投影、几何运算
Qt 相关qt5-dev, qscintilla-dev, qwt-dev界面框架和控件扩展
其他库gsl-devel, expat-devel, sqlite3-devel, exiv2-dev数学计算、解析 XML、数据库、图像元数据
Pythonpython3-dev可选绑定,插件和 PyQGIS 需要

这里要特别提醒,QGIS 编译时需要的包大多是-dev或-devel结尾的开发版本,光装运行时库是不够的。如果你在 CMake 阶段发现某个依赖找不到,第一反应不是去网上到处找 DLL,而是回到 OSGeo4W 的包管理器里检查是否漏装了对应的开发包。

OSGeo4W 默认安装目录建议使用C:\OSGeo4W或C:\OSGeo4W64。越简单的路径越安全,因为源码构建过程中会有大量脚本拼接路径,目录一旦带空格或中文,很容易让某些工具解析出错。这一点在后面 CMake 配置时还会再次踩到。

2.3 源码目录与公共环境变量

QGIS 源码可以放在任意目录,但我推荐建设一个专门的工作目录,比如D:\Work\qgis-build,里面分成source和build两个子目录。source 存放源码,build 存放构建产物。好处是日后升级源码或彻底重编时,可以清楚地知道谁是谁,不会在多个build目录里迷路。

在开始所有操作前,需要确保 PATH 环境变量里能看到关键工具的入口。通常我会打开 OSGeo4W 自带的命令行外壳,因为它会替你把 Qt、GDAL、PROJ 等目录挂进环境变量。然后再手动确认:

where qmake where cmake where ninja where g++

对 Windows 上的编译来说,qmake必须指向 Qt5 版本。QGIS 3.34 系列还在使用 Qt 5.15,而不是 Qt 6。不要因为机器上装了新版 Qt 就顺手把 qmake 指向它,否则 CMake 探测 Qt 版本时会直接判定失败。

另外建议在系统环境变量里增加一条OSGEO4W_ROOT,指向你的 OSGeo4W 根目录。很多 QGIS 脚本和 CMake 模块会通过这个变量去定位依赖。虽然它不是 QGIS 编译的强制要求,但设置后可以减少自己对路径的猜测。

3. CMake 配置与构建参数

3.1 拉取源码和子模块

源码获取建议直接使用 Git,从 QGIS 官方仓库拉取对应标签。

git clone --depth 1 --branch final-3_34_10 https://github.com/qgis/QGIS.git source cd source

这里我使用 shallow clone 可以避免拉取整个历史记录,节省不少时间和磁盘空间。但有一点要注意,QGIS 仓库里包含一些需要子模块的内容,直接浅克隆可能不会把子模块一并拉下来。稳妥起见,进入source目录后再执行一次:

git submodule update --init --recursive

由于仓库已经切换到最终版本 tag,子模块也会指向对应版本的提交,基本不会出现漂移问题。如果是在国内网络环境下拉取 GitHub,可以考虑用镜像或代理把速度提上来,否则某些大文件会等得让人怀疑人生。

成功之后可以在CMakeLists.txt里看一眼PROJECT_VERSION_PATCH这类定义,确认版本是 10,避免拉错分支。这一步是廉价保险,值得养成习惯。

3.2 CMake 配置阶段最容易忽略的选项

CMake 配置是整个编译过程里最需要耐心的一步。我建议把生成的构建系统放到外置目录,也就是源码目录外的build目录,这样不会污染源码。下面给出我实际使用的配置命令:

cmake -S . -B ../build \ -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_PREFIX_PATH=C:/OSGeo4W \ -DCMAKE_INSTALL_PREFIX=C:/QGIS \ -DWITH_BINDINGS=ON \ -DWITH_3D=ON \ -DWITH_QT5=ON \ -DWITH_GUI=ON \ -DWITH_SERVER=ON \ -DWITH_QUICK=OFF

逐个解释一下这里的参数套路。

-DCMAKE_PREFIX_PATH很关键。它告诉 CMake 去哪找 Qt、GDAL、PROJ 等第三方库。OSGeo4W 的目录结构是apps/qt5、apps/gdal、lib、bin这种布局,CMake 拿到前缀之后会自动推算头文件和库文件的位置。

-DCMAKE_INSTALL_PREFIX决定最终ninja install时把 QGIS 安装到哪个目录。我习惯单独放到C:\QGIS,而不是直接写到 OSGeo4W 内部,这样卸载和切换版本都清晰。

WITH_QUICK=OFF是把 Qt Quick 相关的组件关掉。除非你要做 QGIS 移动端或嵌入式界面调试,否则初期不需要,能省掉一大串 Qt 模块依赖。WITH_3D=ON和WITH_SERVER=ON则根据自己需要处理,3D 是桌面端地图分析常用,服务端则适合后续做 GIS 服务调试。

需要注意,CMake 配置文件非常多,QGIS 自己还支持QGIS_INSTALL_DATADIR、PYPYSDK、GRASS等一百多个选项。第一次编译不要试图全开,先把核心和基本界面跑通,后面需要什么再增量开启。

3.3 生成构建系统并完成首次配置

CMake 配置成功时会打印出一大堆依赖摘要,里面会清楚显示 Qt 版本、GDAL 版本、PROJ 版本、Python 版本等。这一步请务必截图或仔细读一遍,凡是显示NOTFOUND的项目都要警惕。

如果某个依赖找不到,最常见的处理方法是回到 OSGeo4W 补装开发包,然后重新配置。很多人喜欢直接删掉整个 build 目录重来,其实 CMake 有缓存机制,重新运行刚才的命令时会复用已有结果,不会每次重头探测。真正需要删除 build 目录的情况,是我改了CMakeLists.txt或切换了编译器等重大变更时。

我遇到过一次比较隐蔽的问题:CMake 探测到了系统自带的 Python,而没有探测 OSGeo4W 的 Python,导致后续 PyQGIS 绑定阶段出现版本错配。解决办法是在配置命令里显式指定:

-DPYTHON_EXECUTABLE=C:/OSGeo4W/apps/Python312/python.exe

至于 Python 具体版本号,要用你自己环境里的实际目录。这里没有统一标准,取决于 OSGeo4W 当前仓库里提供哪个版本。

4. 开始编译:从首次执行到顺利出产

4.1 使用 Ninja 完成一次完整编译

配置通过后,进入 build 目录直接执行编译:

cd build ninja

Ninja 会根据 CMake 生成的build.ninja文件安排并行任务,默认会尽量吃满 CPU 线程。如果你的机器核心数比较多,第一次全量编译可能只需要十分钟到半小时;如果核心较少或者内存不足,则可能非常痛苦。

我在 8 核心 16 线程、32G 内存的 Windows 10 机器上,完整编译 Release 版大约花了 20 分钟。内存占用峰值接近 8G,还算温和。如果你的机器只有 16G 内存,可以限制并行度,避免编译时整机卡死:

ninja -j 8

不要一上来就ninja -j 32,Windows 下单个 C++ 文件的编译内存消耗并不算小,特别是 QGIS 里某些大型模板头文件,编译起来非常吃内存。限制并行度虽然会让耗时变长,但至少不会中途因为内存不足而出错。

编译过程中会先生成大量第三方依赖的状态检查,然后是核心库、GUI 库、分析库、Python 绑定,最后才生成可执行文件。看到qgis-bin.exe链接成功,基本就能确认大功告成了。

4.2 编译期报错:典型现象和解法

在 Windows 10 上编译 QGIS,遇到报错才是常态,关键是别慌。我整理了几类最常见的错误和解决思路,基本覆盖了大多数初次编译场景。

错误现象可能原因处理方式
Could not find Qt5qmake 路径不对或 CMAKE_PREFIX_PATH 没指到 OSGeo4W检查 Qt 5 的 qmake 位置,重新配置 CMake
Could NOT find PROJOSGeo4W 里缺少 proj-dev 包回到 OSGeo4W 安装 proj-dev
XXX.lib not found链接时找不到第三方库确认对应 dev 包是否安装完整
unresolved external symbol编译器不匹配或 x64/x86 混乱保证用的是 64 位 MSVC 工具链
LNK1104 cannot open file杀毒软件锁定可执行文件关闭实时防护或把构建目录加入白名单
编译内存不足并行任务过多调低ninja -j并行数

有一个特别容易被忽略的问题是杀毒软件。Windows Defender 会在编译时实时扫描临时目录里的 DLL 和 exe,导致链接器写入文件失败,报出莫名的LNK1104或文件占用错误。这是我掉了好多次坑才意识到的,把build目录加入 Windows Defender 的排除目录后,编译速度甚至都有肉眼可见的提升。

另外一个经典问题是磁盘空间。QGIS 编译产物和依赖文件都很大,源文件加构建目录通常要预留 20GB 以上。如果系统盘空间紧张,我建议把source和build都放在剩余空间多的非系统盘。

4.3 两次编译之间如何正确增量更新

如果你拿到了更新一点的 3.34.x 版本,想在已有 build 目录上增量编译,需要注意几件事。

首先,在源码目录执行git pull时,要确认有没有子模块变动。如果有,需要重新git submodule update --init --recursive。其次,增量编译前不一定需要重新配置 CMake,直接ninja会自动检测变化的文件和重新生成构建设置。只有当 CMakeLists.txt 或源码结构发生重大变化时,才需要手动重新运行一次 CMake 配置。

我建议在每次编译后把关键信息记录到一个简单备忘里,包括:用到的 CMake 参数、OSGeo4W 包的版本号、编译成功的时间点。这样万一某天编译失败,可以对着记录判断是依赖更新导致还是源码变更导致,排查效率能高很多。

5. 安装部署与启动验证

5.1 安装到指定目录

编译完成之后,使用安装目标把所有产物复制到CMAKE_INSTALL_PREFIX指定的目录:

ninja install

这步会把qgis-bin.exe、相关 DLL、插件目录、Python 绑定、资源文件等全部部署到C:\QGIS。你可以直接把这个目录当作一个便携版 QGIS 使用,也可以把整个目录套上新的名字用于不同版本并存。

有一点必须强调:不要直接拷贝单个qgis-bin.exe到其他机器使用。QGIS 运行依赖一堆第三方 DLL,安装目标里虽然复制了大部分,但仍有一部分依赖在 OSGeo4W 的环境目录中。便携化部署可以之后再做,前提是把依赖关系理清楚,否则会变成 DLL 地狱。

5.2 启动脚本与外部依赖处理

安装完成后,直接双击qgis-bin.exe可能会白屏或提示缺少 DLL,原因在于它需要运行时找到 Qt5 的插件目录和 OSGeo4W 的 Python 环境。

最省事的做法是创建一个批处理启动脚本start-qgis.bat:

@echo off set OSGEO4W_ROOT=C:\OSGeo4W call "%OSGEO4W_ROOT%\bin\o4w_env.bat" set PATH=C:\QGIS;%PATH% C:\QGIS\bin\qgis-bin.exe

o4w_env.bat是 OSGeo4W 自带的环境初始化脚本,能把 Qt、GDAL、Python 的路径挂到当前进程里。这样做的好处是干净,只影响这个脚本所在的命令行窗口,不会污染系统环境变量。

如果你的 QGIS 安装目录里的bin下能找到大部分 DLL,但还是提示找不到某个特定文件,可以直接到OSGeo4W\bin目录下去找同名 DLL,复制到 QGIS 的bin目录即可。但在复制之前要确认这个 DLL 是 64 位版本,否则架构不匹配会导致加载失败。

5.3 快速验证自编译版本

验证编译结果最直接的方式是进入 QGIS 主界面,打开“帮助”菜单,点击“关于”,查看版本号是否显示 3.34.10。更好玩的是,源码编译版在关于信息里通常会包含构建时间、编译器、C++ 配置等元数据,和官方安装包相比多了不少说明信息。

如果想进一步验证核心库是否正常,可以打开 Python 控制台,尝试:

import qgis.core from qgis.core import QgsApplication, QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem("EPSG:4326") print(crs.description())

如果能正常输出 WGS84 描述文本,说明核心库、Python 绑定和坐标参考框架初始化都没有问题。这一步比单纯看启动画面靠谱得多。

随后可以打开一个矢量或栅格数据做基本的加载测试。我习惯随手打开一两个行政区划 Shapefile 和一张遥感影像,分别做一次简单缩放漫游,再用“属性表”打开统计字段。如果这几个操作都不卡不崩溃,说明 GUI 和渲染主链路基本正常。

6. 编译完成之后还能做什么

6.1 基于源码版本做二次开发

自编译版本最大的优势在于二次开发。你可以新建一个 C++ 插件项目,链接到编译产物里的qgis_core.lib和qgis_gui.lib,然后在 CMake 里把自己的项目指到 QGIS 安装目录。写插件时,用实际编译出来的头文件和库文件,能最大程度避免“官方 SDK 和自己代码版本不一致”带来的诡异崩溃。

如果你更感兴趣 Python 插件,源码构建后的 PyQGIS 模块可以直接被外部解释器调用。只要环境变量里能正确挂载C:\QGIS\apps\qgis\python路径,你就不必非要依赖 QGIS 内置控制台,可以用自己熟悉的 IDE 做单步调试。

6.2 调试版本与性能分析的建议

日常使用建议编译 Release 版本,启动速度和内存占用都更友好。但如果是定位崩溃问题或排查渲染 bug,可以考虑再单独配置一个 Debug 或 RelWithDebInfo 构建目录。只要把-DCMAKE_BUILD_TYPE=Debug替换上去,重新走一遍编译即可。

Debug 版本编译时间会明显变长,运行速度也慢不少,不建议当作默认工作版本。我自己的做法是:Release 目录长期保留作为日常使用,Debug 目录只在使用调试器追踪具体问题时才编译。

另外,如果机器内存比较宽裕,可以开启WITH_SERVER=ON和WITH_3D=ON,编译一个完整版,之后就能在本地起一个 QGIS Server 实例,用 WMS/WFS 接口做内网地图服务联调。这样既能验证桌面端,又能覆盖服务端场景,一套源码吃满两个方向。

7. 给后来者的一些心里话

把 Windows 10 上编译 QGIS 3.34.10 的整个过程复盘下来,我发现最容易让人半途放弃的并不是编译代码本身,而是“工具链一致性”这个概念。Windows 平台上缺包、版本错、架构混用,都会产生让你摸不着头脑的错误。但只要能把 OSGeo4W、MSVC、Qt 5 三者锁定在同一套环境下,剩下的问题基本都能按图索骥查出来。

我踩过最大的坑,就是一开始图省事,直接用 Visual Studio 的 CMake 配置生成 MSBuild 工程。结果项目文件巨大,整体编译资源管理很差,还经常出现莫名其妙的源文件依赖顺序问题。后来换成 Ninja 作为生成器,速度和自动化程度都提高了一个档次,所以强烈建议新手直接走 Ninja 路线。

另一点心得是,不要害怕删build目录。很多时候你改了某个 CMake 选项,但缓存里还留着旧值,后果比删掉重来更糟。与其在缓存里找问题,不如保留源码、重新生成构建,成功概率反而更高。

以后再做与 QGIS 相关的环境测试,我会直接把这套完整构建过程固化成一个脚本。先让机器自动初始化 OSGeo4W 依赖,再通过 CMake 脚本生成配置,最后用 Ninja 完成构建。只要依赖版本不变,整个流程是可以做到一键化的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询