☰
MinGW-w64编译GDAL 1.11.5实战:老版本依赖锁定与避坑指南
2026/10/15 15:36:13 网站建设 项目流程

简介:面向Windows下Qt(MinGW)开发者的GDAL 1.11.5预编译包,基于msys2+MinGW64工具链构建,省去自行搭建编译环境的成本,适合在C++工程中集成栅格/矢量读写能力的初中级开发者。压缩包共149个文件,体积约70.71MB,含63个C++头文件、静态库、动态库及编译配置脚本,均为Windows下可直接使用的编译产物;22个exe为命令行工具集,csv/wkt/gfs/xml等提供投影参数与要素样式信息。目前已有1519人学习下载。包内预置常用基准面与坐标转换数据、dxf/dgn矢量样例及svg辅助素材,便于在Qt(MinGW)环境下直接集成和验证GDAL功能。这些内容还能辅助理解投影转换与OGR驱动加载,减少二次开发中的排错成本。

1. 为什么要回头编译 GDAL 1.11.5:一个老版本兼容性的硬骨头

mingw64 编译 GDAL 1.11.5,这个组合在今天看起来像考古。GDAL 已经迭代到 3.x,新功能一大堆,为什么还有人要找 2015 年的老版本?我遇到的场景很典型:某公司一套十年前的 GIS 支撑系统还在跑,业务逻辑锁死了 GDAL 1.x 的 API 行为,升级意味着重写几百处调用;偏偏那台机器上的 MSVC 编译链早就断了,新装的系统里只有 MinGW-w64 能用。这套流程就是给这类场景准备的:用 MinGW-w64 在 Windows 上把 GDAL 1.11.5 完整编译出来,连带处理 proj、GEOS 这些老依赖的版本匹配,最后落到可执行文件能跑、能被自己的 C++ 工程链接。适合正在维护老代码,或者被旧项目绑定在特定 GDAL 版本上的开发者读。

2. 编译前的选型与准备:MinGW-w64 版本、依赖链和工作目录规划

2.1 为什么是 MinGW-w64 而不是 MSVC 或 Cygwin

先讲清楚一个前提:编译 GDAL 1.11.5 本身不难,难的是编译出来之后给谁用。如果你的下游工程是 Visual Studio 编译的,那直接去找 MSVC 版预编译包更省事;但如果下游是 Qt MinGW 构建、或者混用了 GCC 工具链的 CMake 工程,MSVC 编译的 GDAL 导入库(.lib)和运行库(.dll)在 ABI 层面就对不上。这就是很多人第一次翻车的地方——明明拿到了 GDAL 的 Windows 版,链接时却一堆 unresolved external symbol。

Cygwin 方案可以排除掉:它编译出来的可执行文件依赖 Cygwin1.dll 那一套 POSIX 模拟层,部署到没有装 Cygwin 的机器上就是一堆 DLL not found。MinGW-w64 是纯 Windows 原生工具链,编译出的 GDAL 跑在 Windows 上不依赖额外运行时,这才是老项目迁移时可接受的结果。

具体选型上,我用的是 MinGW-w64 的 GCC 8.x 系列。GDAL 1.11.5 的代码比较老,太新的 GCC(比如 13.x)会暴露更多隐式声明的严格检查错误,编译时污染会变多;GCC 8 时代对 C89/C99 的老代码容忍度好很多。架构上先确认你下游工程是 32 位还是 64 位,GDAL 两者的编译流程一致,但路径完全不通,选错了后面全部白搭。我一般先跑下面这条命令确认编译器位置:

gcc -v 2>&1 | grep "Target"

输出里会出现类似 x86_64-w64-mingw32 或 i686-w64-mingw32 的行。第一步就确认这个架构与你后续要链接的工程一致,别信 PATH 里同时装了好几个 MinGW 的默认顺序——那是个经典的隐形坑。

2.2 GDAL 1.11.5 的依赖链:哪些必须编译,哪些可以直接砍掉

GDAL 1.11.5 的依赖数量和现代版本比不算多,但每一个都涉及版本匹配。我最常踩的坑是把 proj 装成了新版本,结果 GDAL configure 阶段虽然能过,运行时一调用坐标转换函数就直接崩。

按重要程度,我把依赖分成三档:

依赖库建议版本是否必须作用
proj4.8.0 ~ 4.9.3必须坐标参考系、投影转换核心
GEOS3.4.x ~ 3.5.x强烈建议几何操作、空间关系判断
libtiff4.0.x必须TIFF 驱动底层
libpng / zlib老版本即可必须PNG 读写与压缩支撑
libjpeg9.x可选JPEG 驱动
SQLite3.x可选GPKG / VRT 等驱动依赖
curl老版本即可可选WMS / TMS 等网络驱动
xerces-c不装不建议复杂度高,除非确定需要 XML 驱动

关于 proj 版本,这里有一条重要经验:GDAL 1.11.5 的代码是按 proj 4 API 写的,而 proj 5.0 开始把数据结构从 projPJ 改成了 PJ*,坐标转换函数签名也变了。如果你系统里已经有新版 proj,GDAL 1.11.5 源码在编译期可能靠头文件兼容性蒙混过关,但链接期或者运行期出问题的概率极高。我见过一个项目因此出现 getproj 返回空指针却没有报错的现象,排查了一整天,最后发现是动态链接时的 proj DLL 版本不对。所以依赖版本锁死这一步,务必在 configure 之前完成,不要图省事用系统里已有的新版本。

2.3 工作目录与路径规划:避免中文路径、空格和权限问题

这一步看起来琐碎,实际上决定了整个编译过程能不能顺完。很多人从网上下载源码包之后直接解压到了桌面的中文文件夹里,或者解压到了带空格的 Program Files 下,然后 configure 阶段报一些莫名其妙的路径错误。MinGW 工具链在旧版本时代对非 ASCII 路径的处理非常差,GDAL 1.11.5 的构建脚本也继承了那个时代的脾气。

我的做法是固定一个纯英文无空格的目录结构:

C:\gdal_build\ src\ # 所有源码包解压后的位置 deps\ # 依赖库的源码与编译产物 install\ # 最终安装根目录(含 bin, lib, include)

我之间遇到过某开发者在 D:\工作资料\GIS项目\ 下面编译,configure 能过但 make 到一半报找不到头文件,最后把整个目录挪到 C:\gdal_build 就好了。这类问题浪费的时间,完全可以通过开始之前就把路径定好来规避。另外一个建议:把编译目录放在和 MinGW 工具链同一个盘符下,避免跨盘操作带来的一些文件路径拼接问题。

提示:确认一下你的 MinGW-w64 安装目录里没有空格。默认装在 C:\mingw-w64 没问题,但如果你装到了 C:\Program Files\mingw-w64,后续 configure 时引号处理会很折磨。

3. 依赖库先行走一遍:proj 与 GEOS 的 configure 编译要点

3.1 proj 4.9.3 的 configure 与 make:锁定 API 版本

先把 proj 编出来,因为 GDAL 的 configure 脚本会去查找 proj 的头文件和库文件,找不到就直接跳过 PROJ 支持,而你只想用却不知道它被跳过了。我一般用 4.9.3 这个版本,它是 proj 4 系列的最后一个稳定版,对 GDAL 1.11.5 的兼容性最好。

在 MSYS2 或 MinGW shell 里执行:

cd /c/gdal_build/deps/proj-4.9.3 ./configure --prefix=/c/gdal_build/install \ --disable-shared \ --enable-static make -j4 make install

这里几个参数解释一下。--prefix指定安装位置,GDAL 后续 configure 会顺着这个路径去找 proj;--disable-shared --enable-static是我个人推荐——静态链接 proj 可以避免运行时出现 proj.dll 找不到或者 DLL 版本冲突的问题,代价是编译后的 GDAL 文件体积大一些,但对老项目部署来说省心很多。

如果不想用静态链接,取消这两行参数即可。但要注意,动态链接的话,后续 GDAL 编译完一定要把 proj.dll 复制到 GDAL 的 bin 目录或者系统 PATH 里。这个问题后面避坑章节还会展开讲。

make -j4 之后要确认安装产物:

ls /c/gdal_build/install/include/proj_api.h ls /c/gdal_build/install/lib/libproj.a

如果 libproj.a 存在,说明静态库编译成功。如果这两个文件缺失,不要进入下一步,回头去看 configure 输出里的错误。常见原因是 shell 环境里没有启用必要的工具,比如 make 或 libtool。

3.2 GEOS 的静态库编译与 C++ 运行时一致性问题

GEOS 是 GDAL 几何功能的基础,很多人在 CMake 工程里开着它,结果编译完发现 GDAL 没有 GEOS 支持,原本能跑的空间相交分析全挂了。GEOS 3.5.x 是 GDAL 1.11.5 时代比较匹配的版本,3.6 以上在 Windows 上的构建脚本有点变化,没必要冒险。

cd /c/gdal_build/deps/geos-3.5.2 ./configure --prefix=/c/gdal_build/install \ --disable-shared \ --enable-static make -j4 make install

GEOS 是 C++ 写的,这里要特别注意一个约束:用它静态链接出来的 GDAL 以及后续你自己的 C++ 工程,编译器必须保持同一个来源。如果 GDAL 用 MinGW GCC 8 编,你自己的工程却用 MinGW GCC 13 或 MSVC,链接时会有非常多 C++ 标准库符号冲突。这不是 GDAL 的问题,是 C++ ABI 的问题。我之前在某跨平台系统项目里就因为这个查了很久,最后发现是工程 A 用了 GCC 11 编的 GEOS 静态库,工程 B 用 GCC 8 链接,表现是各种内存崩溃。

所以编译顺序上,我强烈建议:先确认整套工具链统一,再开始编依赖。有一个简单确认命令:

gcc --version && g++ --version && make --version

把这三个输出确认完之后,再去编依赖。不要相信 PATH 里前面的编译器,要对一下版本字符串是否一致。

3.3 确认依赖库被 GDAL configure 正确识别

这一步是很多人跳过的环节。GDAL 的 configure 如果在探测 proj 或 GEOS 时失败,不会直接报错中止,而是静默地把相关驱动标记为"不可用"。等你编译完,用 gdalinfo --formats 一看,少了 PROJ 或 GEOS 相关的能力,才意识到之前白干了。

我建议在开始 GDAL configure 之前,手动跑一下依赖库的探测命令:

# 检查 proj 头文件和库是否可被找到 echo '#include <proj_api.h>' | gcc -I/c/gdal_build/install/include -E - > /dev/null && echo "proj header OK" # 检查 GEOS 头文件和库 echo '#include <geos_c.h>' | gcc -I/c/gdal_build/install/include -E - > /dev/null && echo "geos header OK"

这两条命令如果输出 OK,说明头文件路径没问题。库文件能链接的事情,GDAL 的 configure 脚本会在之后的编译期自行验证,只要头文件能找到,configure 的探测一般都能过。如果头文件就找不到,回去检查上面安装步骤的 --prefix 是否生效。

提示:有些系统的 gcc 默认不搜索 /usr/local/include 以外的路径,MinGW 更是只搜自己安装目录。用 -I 显式指定是标准做法,别指望 configure 脚本自动能找到。

4. GDAL 1.11.5 本体 configure 与 make:关键参数与两轮编译策略

4.1 configure 的关键参数:不要贪多,只开需要的驱动

GDAL 的 configure 支持一大堆 --with-* 参数。第一次编译时我的建议是只打开你确定要用的功能,无关驱动全部 --without 或 --disable,减少编译期间翻车的概率。

下面是经过验证的最小化配置:

cd /c/gdal_build/src/gdal-1.11.5 ./configure --prefix=/c/gdal_build/install \ --with-proj=/c/gdal_build/install \ --with-geos=/c/gdal_build/install/bin/geos-config \ --with-libtiff=/c/gdal_build/install \ --with-libpng=/c/gdal_build/install \ --with-libz=/c/gdal_build/install \ --without-pam \ --without-xml2 \ --without-curl \ --without-sqlite3 \ --without-expat \ --without-xerces \ --without-openjpeg \ --without-python

参数含义逐个说:--with-proj后面跟的是 proj 安装前缀;--with-geos指向 geos-config 脚本的路径,GDAL 靠它来获取 GEOS 的编译参数,这一步经常有人只写--with-geos=yes,结果 configure 找不到 geos-config 就悄悄跳过;--with-libtiff、--with-libpng、--with-libz分别指到刚才安装依赖的前缀目录。

--without-pam关闭了 GDAL 的持久化辅助数据管理功能,这个是老版本在 Windows 上容易出问题的地方;--without-python先关掉 Python 绑定,把 C++ 核心编出来再说。剩下的逐个 disable 是为了缩短编译时间和减少翻车点。如果后面确实需要 SQLite 或者网络驱动,再回头单独打开重编也不迟,GDAL 增量编译的效率还可以。

4.2 make -j4 的并行度选择与老代码的隐式声明问题

configure 通过之后,进入编译阶段。这里有一条我个人总结的经验:第一遍编译不要用 -j4 以上的并行度。

make -j4 -k 2>&1 | tee build.log

-k参数让 make 在遇到单个文件编译错误时尽量继续编译其他文件,这样可以一次性收集全部错误。之后统一查看 build.log(tee 命令同时把输出写到文件和屏幕)。

GDAL 1.11.5 在较新的 GCC 下最容易报的一类错误是"implicit declaration of function"。比如某些源文件用到strcasecmp,但没包含对应的头文件,老 GCC 只给 warning,新 GCC 直接给 error。如果遇到这类错误,常见的改动是在报错文件里手动加一行:

#include <strings.h>

或者把 Makefile 里的 CFLAGS 加上-D_CRT_SECURE_NO_WARNINGS和-Wno-implicit-function-declaration。后者更省事,因为老 GDAL 源码里这类问题不止一处,一个个手动加太累。

make CFLAGS="-O2 -Wno-implicit-function-declaration -D_CRT_SECURE_NO_WARNINGS" -j4 -k 2>&1 | tee build2.log

注意这里要重新跑 configure 才会把 CFLAGS 固化进 Makefile,如果直接在 make 命令行覆盖,有些子目录的编译规则会不认。我对这个问题的处理办法是改 configure 生成后的 GDALmake.opt 文件,把 CFLAGS 那一行替换成带警告豁免的版本。具体路径是根目录下生成的 GDALmake.opt,打开找到 CFLAGS 行直接改。

4.3 make install 安装与输出目录整理

编译通过后,安装过程本身的坑不多,但有一个细节要注意:make install 默认把所有东西散落安装到 --prefix 下的 include、lib、bin 三个目录,而 GDAL 1.11.5 的安装逻辑会把 20 多个 DLL 全部扔进 bin 里,并不为每个驱动建子目录。这意味着部署时要么把 bin 整个加入 PATH,要么直接把需要的 DLL 复制到应用目录。

make install # 安装后确认目录结构 ls /c/gdal_build/install/bin ls /c/gdal_build/install/lib ls /c/gdal_build/install/include

安装完成后,bin 目录下应该能看到 gdalinfo.exe、gdal_translate.exe 这些工具,lib 目录下应该有 libgdal.a(如果你按上面的 configure 走的是静态库)或 gdal.dll 的导入库。include 目录下是 gdal_priv.h、gdal.h 这些头文件。

此时验证一下命令行工具能否运行:

/c/gdal_build/install/bin/gdalinfo.exe --version

如果报缺 DLL,别急,下一章专门排查这类问题。

5. 避坑与排查:从 DLL 找不到到 ABI 混用,五条实战经验

5.1 运行时报“找不到 libproj.dll”或“找不到 libgdal-1.dll”

现象:gdalinfo.exe 能编译出来,但一执行就弹窗或者命令行报 error while loading shared libraries。

原因:MinGW 编译的动态库在运行时按以下顺序找依赖 DLL:应用程序所在目录、当前工作目录、系统 PATH。GDAL 的 DLL 和 proj 的 DLL 虽然都在 /c/gdal_build/install/bin 下,但 gdalinfo.exe 所在的目录可能没被加入 PATH。

解决:把 install/bin 手动加入系统 PATH,或者把需要的 DLL 全部复制到 gdalinfo.exe 所在目录。我一般用后者,因为部署到客户机器时不应该依赖修改系统环境变量。复制清单包括 gdal 主 DLL、proj DLL(如果你没静态编译 proj)、GEOS DLL、libtiff DLL、libpng DLL。如果你按前文推荐的静态编译了 proj 和 GEOS,这里只需要 gdal 主 DLL 和 zlib、libpng、libtiff 这几个,少很多麻烦。

5.2 坐标转换结果全错:proj 版本被新库劫持

现象:程序能跑,但用 GDAL 做投影转换,输出的坐标明显不对,甚至出现极点坐标或者接近零的值,但没有任何崩溃和报错。

原因:机器上安装了新版 proj(比如 proj 6/7),它在 PATH 里的优先级比 GDAL 安装目录更高。GDAL 1.11.5 运行时按 DLL 搜索顺序找到了新版 proj.dll,而新版 proj API 的数据结构变了,GDAL 老代码按老 API 传参,结果就是解析错误。

解决:两种方案任选。一是把 GDAL 安装目录的 bin 放到 PATH 最前面,确保老版 proj DLL 先被加载;二是用 Process Explorer 或 Dependencies 工具查一下 gdalinfo.exe 实际加载的 proj DLL 路径,确认版本。方案二更稳妥,因为 PATH 顺序问题在复杂环境里很容易反复。我现在每换一次环境,都会先跑一遍 gdaltransform 做一个已知坐标点的转换验证,省得后面排错排半天。

5.3 GEOS 静态库混用 Different 编译器导致崩溃

现象:程序运行时,调用 GEOS 的空间关系函数,时而正常时而崩溃,而且崩溃点会飘,不是固定的栈。

原因:GEOS 是按 C++ 编译的,它的静态库包含 C++ 标准库符号。如果你的工程用 MSVC 或另一个 GCC 版本链接这个库,两个编译器的 std::string 内部布局不一致,函数调用时栈破坏,就会出现这种间歇性崩溃。

解决:从源头避免——GEOS、GDAL、你的工程,三者必须用同一个 MinGW-w64 编译器编译。如果工程里历史遗留了 MSVC 编译的库,要么把它换成 MinGW 版本,要么让 GDAL 不启用 GEOS 支持。二选一,没有第三种方案。我见过有人在两者之间反复调内存对齐参数,把时间浪费在玄学上。

5.4 configure 静默跳过 GEOS / proj 支持

现象:编译全程无错误,但 gdalinfo --formats 列出格式时,某些需要 GEOS 或 proj 的驱动不见了。

原因:GDAL 的 configure 脚本对可选依赖的处理策略是"找不到就跳过",不警告也不报错。常见的触发点是 geos-config 脚本路径没写对,或者 proj 的头文件版本和库版本不一致。

解决:configure 之后立即检查生成的 GDALmake.opt 文件,搜索 GEOS 和 PROJ 相关行。确认:

PROJ_FLAGS = -DHAVE_PROJ GEOS_CONFIG = /c/gdal_build/install/bin/geos-config

如果这两行不是期望值,说明探测失败了。回到依赖库安装步骤,检查头文件路径,然后再重新 configure。这时候别急着 make,把 configure 输出从头到尾读一遍,看有没有 misleading 的警告。

5.5 链接时报大量未定义引用:库的链接顺序

现象:自己的 C++ 工程链接 GDAL 静态库时,报一堆未定义的符号,比如 GDALAllRegister 或 OGRRegisterAll 找不到。

原因:MinGW 的链接器对静态库的扫描顺序是线性的,而 GDAL 内部各模块之间有循环依赖。如果你在 g++ 命令行或 Makefile 里把 -lgdal 放在别的库之前,链接器扫描到 GDAL 还没解析完,等扫到后面的库时就无法回头找 GDAL 里的符号了。

解决:把 -lgdal 放在所有依赖库之后,同时补上它的完整依赖链:

g++ main.cpp -o app.exe \ -L/c/gdal_build/install/lib \ -lgdal \ -lproj -lgeos -ltiff -lpng -lz

如果还缺符号,再从 GDAL 编译日志里找它实际链接了哪些库,逐个补上。这是我在某图像处理 Demo 里踩过的坑,当时把库写成-lproj -lgeos -lgdal,链接器一直报错,反过来之后就好了。

6. 验证与后续维护:从最小测试到版本锁定的习惯

6.1 用 gdalinfo 和一张小影像做最小验证

编译完不是终点,先跑一个跨格式转换的测试,验证 proj 和 GEOS 真的生效了。准备一张任意 TIFF 影像,运行:

gdalinfo.exe test.tif gdalinfo.exe --formats | grep -i "GTiff"

看到 GTiff 驱动在列表里,说明 libtiff 工作正常。接着用一个带投影的影像测试坐标转换:

gdalwarp.exe test.tif test_4326.tif -t_srs EPSG:4326

如果这条命令能成功输出,说明 proj 的坐标转换链路完整可用。这是我最常用的一组最小验证,五个命令以内确认整套编译没有白干。

6.2 Qt / C++ 工程链接 MinGW 版 GDAL 的最小配置

老项目用 Qt 的 MinGW 构建链很常见,我的 .pro 文件里是这么写的:

INCLUDEPATH += C:/gdal_build/install/include LIBS += -LC:/gdal_build/install/lib -lgdal

关键在于 LIBS 的顺序,把 -lgdal 放最后面可以减少未定义引用的问题。同时确认 Qt 的编译器 kit 和编 GDAL 用的 GCC 版本一致,这一点前面已强调,不再重复。

6.3 记录 configure 参数与依赖版本:避免重蹈覆辙

最后提一个我自己的习惯:每次编译完,我会把用到的 configure 命令、依赖库版本、编译器版本、修改过的 GDALmake.opt 内容保存成一个 rebuild_notes.txt 放在源码目录旁边。这个东西平时没什么用,但半年后重新构建或者换机器时,能省掉半天摸索时间。GDAL 1.11.5 这套东西重新编译的成本不低,依赖链上的版本锁定一旦没记录,下次就可能因为 proj 版本漂移而翻车。

我的教训是:某次换电脑重建环境,仗着记忆重新编依赖,结果 proj 装成了 5.x,GDAL 编译时没问题,运行测试时才发现坐标转换全错,排查了几乎一整天。从那以后,所有老版本 GDAL 的编译环境我都强制要求记录版本和 configure 参数。希望这些小习惯能帮到你,让你在这条路上少走几步弯路。

本文还有配套的精品资源,点击获取

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

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

立即咨询