简介:本资源为在Windows平台下基于msys2与MinGW32方式编译完成的GDAL 1.11.5开发库,面向使用Qt(MinGW)进行地理空间数据处理开发的程序员,可省去自行编译的繁琐过程。解压后只需将bin目录加入系统环境变量,并在.pro文件中配置GDAL路径即可直接调用,适用于遥感影像读取、矢量数据转换、坐标投影等GIS开发场景。压缩包共149个文件,约74.73MB,包含63个C/C++头文件、22个可执行工具、28个CSV坐标与基准数据、若干WKT、XSD、XML等投影与模式定义文件,以及静态库、动态库和gdal-config配置脚本,覆盖开发与运行所需的核心组件。目前已有779人学习下载。资源附带常见程序异常结束的排查思路指引,帮助开发者快速定位环境配置问题,降低入门与调试成本。
1. GDAL 1.11.5 配 mingw32:老版本工具链为什么还有人死磕
如果你手头有一个 2015 年前后启动的 GIS 桌面项目,或者维护着一套跑在 Windows XP/7 工控机上的地图切片工具,那你大概率绕不开 GDAL 1.11.5 这个版本。它发布于 GDAL 1.11 系列末期,是最后一个对 mingw32 支持相对完整、且不强制依赖 C++11 的稳定版本。很多老项目的构建脚本里写死了gdal111的库名,升级到 2.x 之后 API 断裂、依赖链爆炸,于是“用 mingw32 重新编一个 1.11.5”成了每年都要翻出来折腾一次的任务。
这篇文章不讲 GDAL 是什么,也不讲 GIS 基础。我假设你已经有一个必须在 32 位 Windows 上跑、必须用 mingw32 工具链、且必须链接 GDAL 1.11.5 的场景。我会把从环境准备、configure 参数、编译排错到产物验证的完整路径拆开,重点放在那些官方文档不会写、但实际编译时一定会撞上的坑。如果你只是想找个现成的 DLL 用,gisinternals 这类站点确实提供过编译好的包,但版本和编译器匹配问题会让你在链接阶段付出代价——自己编一次,反而更省时间。
2. mingw32 工具链选型与 GDAL 1.11.5 源码准备
2.1 为什么是 mingw32 而不是 mingw-w64
标题里写的是 mingw32,不是 mingw-w64。这两个东西经常被混为一谈,但在 GDAL 1.11.5 这个年代,它们的行为差异很大。mingw32 通常指 32 位目标、使用 msvcrt.dll 作为 C 运行时的老式 MinGW 工具链,典型代表是 MinGW.org 的 GCC 4.8.x 系列。mingw-w64 则是另一套项目,支持 32/64 位目标,运行时可以选择 msvcrt 或 ucrt。
GDAL 1.11.5 的源码里大量使用了#ifdef __MINGW32__这样的宏判断,这些判断最初是针对 MinGW.org 工具链写的。如果你用 mingw-w64 的 32 位模式去编,宏定义虽然也能命中,但某些头文件路径和库命名规则不一致,会在 configure 阶段就报错。我一般会直接锁定 MinGW.org 的 GCC 4.8.1 或 4.9.3,这两个版本在 SourceForge 上还能找到完整的 32 位安装包。
安装时注意勾选mingw32-base、mingw32-gcc-g++、msys-base这三项。msys 提供 bash 环境和 make,没有它你没法跑 configure 脚本。装完之后把C:\MinGW\bin和C:\MinGW\msys\1.0\bin都加进 PATH,但要注意顺序:msys 的 bin 放在前面,否则你会用到 Windows 自带的 find.exe 而不是 msys 的 find,configure 脚本会莫名其妙失败。
2.2 源码包获取与依赖库清单
GDAL 1.11.5 的源码可以从 OSGeo 的下载归档里找到,文件名通常是gdal-1.11.5.tar.gz。解压到一个不含空格和中文的路径,比如C:\build\gdal-1.11.5。不要放在C:\Program Files下面,configure 脚本对空格路径的处理一直有问题。
GDAL 本身依赖几个第三方库,但 1.11.5 对它们的依赖是可选式的。最小可编译配置只需要 zlib 和 libtiff,如果你要读写 PNG 或 JPEG,再加 libpng 和 libjpeg。这些库在 mingw32 下有两种获取方式:一是用 msys 的 pacman 装预编译包,二是自己从源码编。我建议 zlib 和 libtiff 自己编,因为预编译包的路径和 GDAL configure 的默认搜索路径经常对不上。
自己编 zlib 的流程很简单:解压后进目录,执行make -f win32/Makefile.gcc,然后把zlib1.dll、libz.a、zlib.h、zconf.h分别拷到 MinGW 的 bin、lib、include 目录。libtiff 稍微麻烦一点,它依赖 zlib 和 libjpeg,configure 的时候要显式指定--with-zlib-include-dir和--with-jpeg-include-dir。如果你暂时不需要 TIFF 支持,可以在 GDAL 的 configure 里加--without-libtiff,先编一个最小版本跑通流程。
提示:所有依赖库都编成静态库(.a)比动态库省事,因为最终链接时不用操心 DLL 的搜索路径。但如果你要生成一个供其他程序调用的 GDAL DLL,那就得把依赖也编成 DLL,否则符号冲突会让你调很久。
3. configure 参数逐项拆解与编译命令
3.1 最小可编译的 configure 命令
进入 msys 终端,cd 到 GDAL 源码目录,执行下面这条命令。这是我反复验证过的最小配置,能编出一个支持 GeoTIFF、PNG、JPEG 的 32 位 GDAL 1.11.5。
./configure \ --host=i686-pc-mingw32 \ --prefix=/c/gdal-build \ --with-threads \ --without-libtool \ --with-png=internal \ --with-jpeg=internal \ --with-libtiff=internal \ --with-geotiff=internal \ --without-python \ --without-curl \ --without-sqlite3 \ --without-expat \ CFLAGS="-O2 -m32" \ CXXFLAGS="-O2 -m32" \ LDFLAGS="-m32"逐项说明:--host=i686-pc-mingw32告诉 configure 目标平台是 32 位 Windows,这个三元组必须写对,否则生成的 Makefile 会用错误的库命名规则。--prefix指定安装路径,用 msys 风格的/c/gdal-build而不是C:\gdal-build。--with-threads启用多线程支持,GDAL 的某些驱动在单线程下会退化成阻塞模式。
--without-libtool是个关键参数。libtool 在 mingw32 下经常生成错误的 .la 文件,导致链接阶段找不到依赖。关掉它之后,GDAL 会直接用 gcc 生成 DLL 和导入库,反而更干净。--with-png=internal表示使用 GDAL 源码树里自带的 libpng 副本,而不是外部库。1.11.5 的 internal 版本虽然老,但胜在路径可控,不会出现头文件版本不匹配的问题。同理,jpeg、libtiff、geotiff 都用 internal。
--without-python必须加。GDAL 1.11.5 的 Python 绑定在 mingw32 下几乎编不过,swig 生成的代码和 Python 头文件的兼容性很差。如果你确实需要 Python 绑定,建议单独用 pip 装一个对应版本的 GDAL wheel,不要在这个编译流程里折腾。
3.2 编译与安装命令
configure 跑完之后,检查输出末尾有没有GDAL is now configured for i686-pc-mingw32这行字。如果有,就可以开始编译了。
make -j4 make install-j4是并行编译的核数,根据你机器的 CPU 调整。GDAL 1.11.5 的代码量不小,单线程编可能要二十分钟以上。编译过程中最常见的错误是某个 internal 库的头文件找不到,比如png.h或tiffio.h。这通常是因为 configure 阶段没有正确识别 internal 库的路径。解决办法是手动在 CFLAGS 里加上-I./frmts/png/libpng这样的路径,具体路径根据报错信息里的文件名去源码树里找。
make install会把gdal111.dll、libgdal.a、头文件和工具程序拷到/c/gdal-build下面。检查一下bin目录里有没有gdalinfo.exe,lib目录里有没有libgdal.a和gdal111.lib(如果你需要 MSVC 兼容的导入库)。如果没有.lib文件,可以用dlltool从.def文件生成,命令是dlltool -d gdal111.def -l gdal111.lib。
注意:
make install之后不要急着删源码目录。后续如果你要调试某个驱动的行为,或者需要重新生成 .def 文件,源码目录里的中间产物还有用。
4. 编译期与链接期的避坑排查
4.1 现象:configure 报错 “C compiler cannot create executables”
原因:msys 的 PATH 顺序不对,或者 MinGW 的 gcc 没有正确安装。有时候是因为TMP或TEMP环境变量指向了一个不存在的目录,configure 在测试编译时无法写临时文件。
解决:在 msys 终端里执行which gcc,确认输出是/c/MinGW/bin/gcc而不是 msys 自带的某个版本。然后检查echo $TEMP,如果是空或者指向不存在的路径,手动设成/tmp。再跑一次 configure,基本就能过。
4.2 现象:编译到 ogr 目录时报 “undefined reference to__imp_WSAGetLastError”
原因:GDAL 1.11.5 的 OGR 部分用到了 Winsock 的 API,但 Makefile 里没有自动链接-lws2_32。这在 mingw32 下是常见问题,因为 msvcrt 不会隐式带入 Winsock 库。
解决:在 configure 的 LDFLAGS 里加上-lws2_32,或者在 make 的时候手动指定LIBS="-lws2_32"。如果已经 configure 过了,可以直接编辑GDALmake.opt文件,找到LIBS那一行,把-lws2_32追加进去,然后重新 make。
4.3 现象:生成的 gdal111.dll 在目标机器上加载失败,报 “找不到 msvcr100.dll”
原因:你的 mingw32 工具链链接了 msvcr100.dll(Visual Studio 2010 的运行时),而不是 msvcrt.dll。这通常是因为你用的 MinGW 发行版自带了某个版本的 msvcr 导入库。
解决:用 Dependency Walker 或objdump -p gdal111.dll | findstr "DLL Name"查看实际依赖。如果确实依赖 msvcr100.dll,要么在目标机器上装对应的 VC 运行时,要么换一个纯 msvcrt 的 MinGW 工具链重新编译。我一般会在 configure 时加LDFLAGS="-static-libgcc -static-libstdc++",把 GCC 的运行时也静态链进去,减少对目标机器环境的依赖。
4.4 现象:gdalinfo --version输出正常,但打开 GeoTIFF 时报 “not recognized as a supported file format”
原因:GeoTIFF 驱动没有正确注册。GDAL 1.11.5 的驱动注册是静态的,如果 configure 时--with-geotiff=internal没有生效,编译出来的 DLL 里就不会包含 GeoTIFF 驱动。
解决:检查 configure 输出里有没有GeoTIFF support: yes。如果没有,说明 internal geotiff 的路径没被识别。手动在frmts/gtiff/libtiff和frmts/gtiff/geotiff目录下确认源码文件存在,然后在GDALmake.opt里把GDAL_FORMATS那一行的gtiff加回去,重新 make。
4.5 现象:链接自己的程序时提示 “cannot find -lgdal111”
原因:库文件名不对。mingw32 下 GDAL 生成的导入库通常叫libgdal.a或gdal111.lib,而不是libgdal111.a。-lgdal111会让链接器去找libgdal111.a,自然找不到。
解决:用-lgdal代替-lgdal111,或者直接把libgdal.a的完整路径写进链接命令。如果你用的是 MSVC 风格的.lib文件,那就在链接器选项里写gdal111.lib的完整路径,不要用-l前缀。
5. 产物验证与在 mingw32 项目中的集成方式
编完之后第一件事是验证 DLL 能不能正常工作。在 msys 终端里执行:
/c/gdal-build/bin/gdalinfo.exe --version /c/gdal-build/bin/gdalinfo.exe --formats第一条命令应该输出GDAL 1.11.5, released 2015/09/16之类的版本信息。第二条命令会列出所有已编译进去的驱动格式,检查一下 GeoTIFF、PNG、JPEG 是否在列表里。如果格式列表是空的,说明驱动注册有问题,回到 4.4 节排查。
接下来用一个真实的 GeoTIFF 文件测试读写:
/c/gdal-build/bin/gdalinfo.exe test.tif如果能看到坐标系、波段数、尺寸等信息,说明核心功能正常。再试一下格式转换:
/c/gdal-build/bin/gdal_translate.exe -of PNG test.tif test.png这一步会同时调用 GeoTIFF 读取和 PNG 写入两个驱动,能过就说明驱动链没问题。
在自己的 mingw32 项目里集成时,Makefile 里需要加三个东西:头文件路径-I/c/gdal-build/include,库路径-L/c/gdal-build/lib,以及链接选项-lgdal -lws2_32。如果你的项目是 C++ 的,还要加-lstdc++。运行时把gdal111.dll和它的依赖 DLL(比如zlib1.dll、libtiff.dll)放到 exe 同目录,或者加到 PATH 里。
提示:如果你要把 GDAL 静态链进自己的程序,用
libgdal.a而不是 DLL。但静态链接时要注意符号冲突,特别是 zlib 和 libtiff 的符号,如果和你项目里已有的库重名,链接器会报重复定义。解决办法是在链接选项里加-Wl,--allow-multiple-definition,但这是最后手段,优先考虑用动态库。
6. 用 gdal-config 脚本简化跨项目引用
编完 GDAL 之后,make install会在bin目录下生成一个gdal-config脚本。这个脚本在 Linux 下很常用,但在 mingw32 环境里经常被忽略。它可以根据参数输出编译和链接所需的标志,省去你手动拼路径的麻烦。
/c/gdal-build/bin/gdal-config --cflags /c/gdal-build/bin/gdal-config --libs /c/gdal-build/bin/gdal-config --version第一条输出-I/c/gdal-build/include,第二条输出-L/c/gdal-build/lib -lgdal,第三条输出1.11.5。你可以在 Makefile 里这样用:
GDAL_CFLAGS := $(shell /c/gdal-build/bin/gdal-config --cflags) GDAL_LIBS := $(shell /c/gdal-build/bin/gdal-config --libs) myapp.exe: myapp.o i686-pc-mingw32-g++ -o $@ $^ $(GDAL_LIBS) -lws2_32这样写的好处是,如果以后你换了 GDAL 的安装路径,只需要改gdal-config的位置,不用动 Makefile 里的每一处路径。但要注意,mingw32 下的gdal-config脚本是用 sh 写的,在 msys 终端里能跑,在 Windows 的 cmd 里跑不了。如果你的构建系统是 cmd 批处理,那就得手动解析这个脚本的输出,或者干脆把路径写死。
还有一个技巧:如果你需要把 GDAL 的头文件路径暴露给一个用 CMake 构建的项目,可以在 CMakeLists.txt 里用execute_process调用gdal-config,把输出赋给变量。这样 CMake 和 Makefile 两套构建系统就能共享同一个 GDAL 安装。
我自己的习惯是,每次编完 GDAL 之后,先把gdal-config --cflags和--libs的输出记在一个文本文件里,放在项目根目录。下次再编的时候,直接对照这个文件检查 configure 参数有没有漏。这个习惯帮我省了很多次“明明上次能编过,这次怎么不行”的排查时间。希望帮到你。
本文还有配套的精品资源,点击获取