简介:这是基于MSYS2与MinGW32环境预编译的GDAL 1.11.5开发包,专为Windows下使用Qt(MinGW版)的开发者准备,解决GDAL自行编译耗时长、依赖复杂的问题。包内含编译好的动态库、静态库、头文件和坐标系统参数数据,解压后将bin目录加入系统环境变量,再在.pro文件中完成链接配置,即可直接调用GDAL接口进行栅格/矢量读写、投影转换与格式处理,省去从源码编译的漫长等待。资源共149个文件,以63个C/C++头文件、28个CSV坐标投影参数文件、22个命令行工具exe为主体,另含dll、a库及少量xml、wkt等辅助文件,压缩包约74.73MB,其中头文件提供编程接口声明,CSV文件为地图投影和坐标转换提供参数支持,结构清晰便于集成。目前已有778人学习下载,适合熟悉Qt开发但不想折腾编译链的初中级开发者。作者另附排错博客,针对程序异常结束给出具体排查思路,能帮助使用者快速解决环境配置中的常见问题。 写这篇的起因很实际——最近在Windows下折腾一套老的地理数据处理流程,项目指定要用GDAL 1.11.5 + mingw32的组合跑编译和二次开发。这套搭配放到今天听起来确实有点“上古”,但真上手后发现,老版本自有老版本的价值,而且mingw32下的编译坑是真不少,网上资料又散、又旧,很多帖子都是2014、2015年的,按图索骥踩了一路雷。我把整个从环境准备、源码编译到Python调用的一整套流程和踩坑记录整理出来,给后面需要在Windows上用mingw32编译GDAL旧版、或者想搞清楚GDAL与Python版本对应关系的朋友做个参考。
GDAL这个名字在地理信息系统和遥感领域基本绕不开。它全称是Geospatial Data Abstraction Library,专门处理栅格和矢量地理数据格式的读写与转换。大到卫星影像、数字高程模型,小到一份Shapefile、GeoJSON,底层几乎都在和GDAL打交道。Python生态里的rasterio、geopandas之所以能“优雅”地读取地理数据,底层靠的也是GDAL/OGR这套C/C++库。而mingw32则是Windows上的一套GNU编译器工具链,用来把GDAL这种以C++为主的源码在Windows下编译成原生可执行文件和动态链接库,不依赖微软的Visual Studio。
1. 为什么还折腾GDAL 1.11.5与mingw32的组合
1.1 1.11.5这个版本的特殊之处
GDAL 1.11.5发布于2015年中,属于1.x系列的晚期维护版本。这个版本最大的特点是稳定和“古董级兼容”。1.x系列和2.x、3.x在API设计上有一个明显的分水岭:2.0开始引入了统一的栅格和矢量数据模型,很多内部结构重写了,而3.0更是把C++接口翻了个底朝天。如果你负责维护的是老项目、老插件、老生产环境,代码里到处是GDAL 1.x时代的函数调用习惯,那么升级到3.x不亚于一次小规模重构。
我当时接到这个需求的核心原因就是这个——一批老算法模块基于GDAL 1.11.5的API写的,短时间不可能全部重写,只能在原有版本基础上做维护和功能扩展。这个场景在测绘、国土、农业遥感这些行业里非常常见:底层库一旦“稳定运行了很多年”,就没人敢动了。
1.2 为什么偏偏是mingw32而不是Visual Studio
Windows下编译C++项目,主流无非两条路:微软自家的MSVC,或者MinGW系列(Minimum GNU for Windows)。mingw32通常指针对32位Windows目标的GNU编译器链,而mingw-w64这个项目则同时支持32位和64位目标。GDAL 1.11.5那个年代,官方预编译的Windows安装包大多是32位+MSVC的组合,如果你要用MinGW工具链自己编译,就得自己动手。
选mingw32还有一个现实原因:某些老的第三方依赖库和插件只提供了32位MinGW编译版本,或者是老项目里约定俗成的构建方式就是“mingw32+老版本GDAL”。这套环境虽然老,但它在特定行业流程里是能跑的,贸然切换工具链,可能连依赖库都得全部重来,风险远大于收益。
说白了,在新版本层出不穷的今天,折腾GDAL 1.11.5和mingw32,不是图新鲜,而是为了在存量系统里续命。你要是遇到同样的情况,最好的心态是“理解它、编译它、扩展它”。
2. 编译环境准备:MSYS2与依赖库的版本纠缠
2.1 快速认识MSYS2与MinGW-w64
要在Windows下用MinGW工具链编译GDAL,强烈建议装MSYS2,而不是直接下载个老旧的MinGW安装包。MSYS2是一个软件发行平台和构建环境,它提供了一套类Linux的shell(基于mintty和bash),并且通过自带的pacman包管理器来安装各种开发库和编译器。好处是依赖关系自动处理,版本也比较新。
安装完MSYS2后,打开“MSYS2 MinGW 32-bit”终端(注意选择32位终端)——毕竟标题是mingw32,目标就是32位环境。先用pacman更新一下系统并安装基础编译工具链:
pacman -Syu pacman -S mingw-w64-i686-gcc mingw-w64-i686-pkg-config make这里有个关键点:mingw-w64-i686-前缀代表32位编译器工具链,如果你装成mingw-w64-x86_64开头的,默认就是64位,编译出来的GDAL没法直接当mingw32版本用。我当时第一次就栽在这里,装成了64位工具链,configure时倒是顺利,但生成dll后放到项目里直接报“bad image format”。
2.2 依赖库的版本纠缠:proj、geos与sqlite
GDAL不是个“光杆司令”,编译时依赖好几个底层库。1.11.5年代,最核心的几个依赖是:
- proj(PROJ.4):负责投影转换和坐标系定义,老版本叫proj4。
- geos:提供矢量几何操作,比如空间关系判断、缓冲区计算。
- sqlite3:OGR的SQLite/GPKG驱动需要它。
- libpng/jpeg/tiff:栅格格式的图片支持。
- curl:网络访问、WMS/WFS等在线数据源的驱动支持。
在MSYS2里安装这些库,命令很简单:
pacman -S mingw-w64-i686-proj mingw-w64-i686-geos mingw-w64-i686-sqlite3 pacman -S mingw-w64-i686-libpng mingw-w64-i686-libtiff mingw-w64-i686-libjpeg-turbo pacman -S mingw-w64-i686-curl但这里有个“版本纠缠”的大坑:MSYS2软件源里的库版本永远是最新的,而GDAL 1.11.5是2015年发布的,拿2020年之后甚至近几年的proj、geos去配老GDAL,大概率会报各种API不兼容的编译错误。例如新版本proj库头文件里的函数签名变了,老GDAL源码调用的老接口根本找不到。
我当时处理的思路是:不追求过新,也不强行找老版本号,而是看configure阶段的具体报错,缺哪个接口就针对性处理。如果不想费这个劲,你也可以在configure时直接禁用相关驱动(--without-proj那种),但那样GDAL的坐标系变换功能就废了,实用性大打折扣。如果你有确定的老业务依赖,建议用Docker/CentOS 6/7这类老系统里编译好再拷dll出来,而如果在Windows纯环境下,尽量让MSYS2的库版本“够用就行”,别刻意全升级到最新。
2.3 编译前必须确认的三件事
正式开始configure之前,我建议你花十分钟做三件事,能省下后面一大半的排查时间:
- 确认终端的类型是“MSYS2 MinGW 32-bit”,可以用
gcc -v查看gcc版本,确认是i686目标而不是x86_64。 - 确认依赖库的pkg-config文件是否可见,在bash里执行
pkg-config --list-all | grep proj之类,看看proj、geos、sqlite3是否都在。 - 确认源码包完整性,MD5校验一下GDAL 1.11.5的tar.gz,避免下载过程中文件损坏。
我当时忽略了第2点,结果configure时提示找不到proj库,折腾半天发现是PKG_CONFIG_PATH没设置好。在MSYS2的32位环境下,通常需要这样设置:
export PKG_CONFIG_PATH=/mingw32/lib/pkgconfig设置完之后,pkg-config --modversion proj能正确输出版本号,configure才能顺利找到库。
3. 源码编译GDAL 1.11.5的核心流程
3.1 configure阶段的参数选择
GDAL源码包解压后,进入根目录,经典的构建三步走:configure、make、make install。configure阶段是核心中的核心,参数直接决定最终版功能开关。
以下是我实际使用的configure命令,并附了参数解释:
./configure \ --prefix=/home/user/gdal-1.11.5-build \ --with-python \ --with-proj=/mingw32 \ --with-geos=/mingw32/bin/geos-config \ --with-sqlite3=/mingw32 \ --with-curl=/mingw32/bin/curl-config \ --with-libtiff=/mingw32 \ --with-geotiff=/mingw32 \ --with-jpeg=/mingw32 \ --with-png=/mingw32 \ --without-pg \ --without-mysql \ --without-odbc \ --without-grass \ --without-libkml几个说明:
--with-python:编译生成Python绑定模块。如果你计划用Python调用GDAL,这步要加。--prefix:指定安装目录,尽量别用系统默认的/usr/local,免得污染MSYS2环境。--without-*:按需裁掉不需要的数据库驱动和重依赖。老机器的编译时间有限,裁剪能显著提速。--with-proj指定到/mingw32:因为MSYS2安装的proj库就在这个前缀下。
configure跑完以后,看一眼输出的总结信息,重点确认proj、geos、curl都是“yes”状态,不要用“no”掩盖掉。如果某个依赖显示“no”,回去检查pkg-config路径或者对应的-dev包有没有装全。
3.2 make与安装的细节
configure通过后,直接执行:
make -j4-j参数指定并行编译任务数,如果你的机器内存足够(8GB以上),用4或8都能显著缩短编译时间。GDAL 1.11.5全量编译大概在10到20分钟,取决于机器性能和驱动开关。
编译过程中最容易出现的问题是“未定义的引用”和“头文件找不到”。前者一般是库版本API不匹配,后者一般是依赖库没装全。比如geos版本过高,GDAL 1.11.5源码里geos_c.h的某些接口调用方式不兼容,就会出现类似:
gdalwarp.cpp: undefined reference to `GEOSBuffer_r(...)'这种报错没有多少捷径,只有一个笨办法:去源码里查这个函数调用的特征,和头文件里定义的特征做对比,必要时在源码里做一个兼容层。我当时处理geos相关的两个函数时,因为只是老API改名,直接在头文件里加了宏替换,两行搞定:
#define GEOSBuffer_r(handle, geom, width, quadsegs) GEOSBuffer_r(handle, geom, width, quadsegs, 0)注意这只是示意,实际替换必须根据你安装的geos头文件版本写法来。
make结束且没有致命错误后,接着:
make install安装完成后,把安装目录下的bin文件夹加入PATH,并在系统环境变量里设置GDAL_DATA指向安装目录下的share/gdal,否则运行GDAL命令时可能因为找不到数据集定义文件而报错:
export PATH=/home/user/gdal-1.11.5-build/bin:$PATH export GDAL_DATA=/home/user/gdal-1.11.5-build/share/gdal3.3 验证编译成果:用gdalinfo说话
安装完成后的第一件事,跑一个最基础的验证命令:
gdalinfo --version正常情况下会输出类似:
GDAL 1.11.5, released 2015/06/23接着用一张tif或img影像测试一下真实读取能力:
gdalinfo sample.tif如果能看到影像的尺寸、波段数、投影信息列表,说明这套mingw32下的自编译GDAL基本是可用的。如果这里报错“Unable to open file”,优先查GDAL_DATA路径是否正确,而不是怀疑库本身。
我建议在这个阶段顺手跑一个格式转换测试,比如把一个tif转成vrt再转回tif,能验证栅格读写链路是完整的:
gdal_translate -of VRT sample.tif sample.vrt gdal_translate -of GTiff sample.vrt sample_out.tif转换成功且sample_out.tif文件大小不为0,就可以进入Python绑定的环节了。
4. 现代场景下的Python安装GDAL路径
4.1 官方wheel:从cp313到cp37的版本对应
说到Python安装GDAL,我注意到现在搜索指数最高的是“gdal 3.10.1 cp313 cp313 win_amd64.whl”这类词条。这其实是现代Python环境下安装GDAL最幸福的方式——直接用pip安装预编译好的wheel包,完全不用自己编译。
wheel文件名里的“cp313”代表CPython 3.13版本,“win_amd64”代表Windows 64位平台。GDAL的官方wheel版本和Python版本有严格的对应关系,不能乱装。比如你在Python 3.13环境里安装,就找cp313后缀的whl;Python 3.11环境,就找cp311后缀的whl。安装命令很简单:
pip install gdal==3.10.1如果当前环境的Python版本和3.13不一致,pip会自动降级或报错,这种时候就要去PyPI或者官方镜像站查一下当前Python版本对应的GDAL版本列表。
如果你是在老Python环境(比如Python 3.7、3.8),还需要安装老一点的GDAL版本,比如3.4.x、3.2.x。这里给一张常见的对应表供参考:
| GDAL版本 | 支持的主要Python版本 | 说明 |
|---|---|---|
| 3.10.1 | 3.9-3.13 | 当前较新版本,功能全面 |
| 3.6.2 | 3.7-3.11 | 兼容性较好 |
| 3.4.3 | 3.7-3.10 | 老项目常用 |
| 2.4.4 | 2.7、3.4-3.8 | 最后支持Python 2的版本之一 |
如果懒得查表,在pip安装时可以直接让pip自己解析:
pip install gdal==3.6.2如果当前Python版本没有对应的wheel,pip会尝试从源码编译,这时又会回到“地狱模式”——需要本机装好完整的编译工具链和GDAL依赖。所以我强烈建议:能用wheel就用wheel,不要主动去走编译路线。
4.2 pip安装遇到“ERROR: Failed building wheel”怎么办
尽管wheel很香,但总有极端情况:比如你用了一个很新的Python版本,而GDAL官方还没有跟进发布对应版本的wheel,或者网络源里缺失某个平台的后缀,pip就会尝试从源码构建。然后大概率会跳出这个经典报错:
ERROR: Failed building wheel for gdal这个报错翻译成人话就是:“本环境没有现成的编译产物,需要现场编译,但你的环境缺工具/依赖。”
排查顺序按优先级来:
- 先确认是不是版本不对:
pip debug --verbose查看当前Python解释器支持的wheel标签,再对照PyPI上gdal的可用文件,找一个配得上的版本。 - 检查本机是否有VS Build Tools或MinGW工具链,Python的setuptools在Windows下默认会尝试找MSVC编译器,找不到就报错。如果你不想装大几GB的VS,可以考虑用conda替代:
conda-forge上的GDAL也是预编译好的,能省去大量烦恼。conda install -c conda-forge gdal
如果一定要编译,那就得先确保本机有完整的编译环境和GDAL依赖库,这基本等于重复前面第2和第3章的流程,唯一差别是还要额外装Python开发头文件。
4.3 Python调用GDAL时的运行时dll问题
即使gdal的whl安装成功了,Python里面import也可能“翻车”:
from osgeo import gdal常见的报错是:
ImportError: DLL load failed: The specified module could not be found.这个错误十有八九是GDAL依赖的底层dll不在系统搜索路径里。你想想看,GDAL是个C++库,它运行时需要proj、geos、sqlite等动态库,但是wheel包只打包了GDAL自身的dll,底层依赖库并不会一起带上。
解决办法一:把依赖库的路径加入PATH环境变量。如果你是用conda安装的,那conda环境里的Library/bin目录下一般已经有这些dll了,手动把该目录加到PATH即可。
解决办法二:在Python代码里显式添加搜索路径。在import osgeo之前,用os.add_dll_directory()把dll所在目录注册进去(Python 3.8+支持),例如:
import os os.add_dll_directory(r"C:\Program Files\GDAL") from osgeo import gdal这条行为在Win10/11下特别重要。老教程里常见的“直接改系统PATH”也不是不能用,但需要重启终端才会生效,而add_dll_directory是即时生效的,排障效率高很多。
还有一个技巧:装完gdal whl后,用python -c "from osgeo import gdal; print(gdal.__version__)"先验证基础可用性。如果这一句能过,再跑后续代码,能避免把“安装没问题”和“业务代码问题”搅在一起。
5. 常见问题与排查技巧实录
5.1 编译期报错速查表
| 报错信息 | 原因 | 处理方式 |
|---|---|---|
| configure: error: PROJ not found | pkg-config路径不对 | 设置PKG_CONFIG_PATH=/mingw32/lib/pkgconfig |
| g++: error: unrecognized command line option '-std=c++11' | gcc版本过旧 | 升级mingw-w64-i686-gcc |
undefined reference toGEOSBuffer_r | geos新API不兼容 | 检查geos头文件,做宏兼容替换 |
| cannot find -lproj | 缺少proj库 | pacman安装proj并确认32位版 |
| gdal-config not found | make install未执行或prefix未加入PATH | 执行make install,检查PATH |
这张表看着简单,但每一条背后都是我实实在在走过的坑。尤其是PROJ not found,一开始总怀疑是依赖没装,结果根本不是缺库,就是pkg-config路径没指过去。
5.2 运行时dll不匹配的经典案例
有一次我编译完了GDAL,直接调gdalinfo测试,结果报了一个很诡异的错误:The procedure entry point ... could not be located in the dynamic link library。
这个错误的意思是:系统加载某个dll时,找不到需要的函数入口点。根源几乎都是“多个版本的dll混用”。比如你MSYS2环境里proj的版本和最终GDAL链接时用的proj版本不一致,运行时系统加载到了另一个目录下的老proj.dll,入口点找不到,直接崩。
排查思路很简单,但很考验耐心:
- 用
ldd gdalinfo.exe查看它依赖的dll列表和搜索路径。 - 用
which proj.dll或where proj.dll看你当前PATH下到底哪个proj被加载。 - 把安装目录下的bin设为PATH最前,保证优先加载自己编译时对应的那套dll。
这个案例最能解释为什么我前面强调“尽量把依赖都装在一个前缀下(/mingw32)”,因为只要依赖库来源统一,运行时冲突概率就小得多。
5.3 我的避坑心得
如果只能分享三条经验,我会说:
第一,别硬凑版本号。GDAL老版本和依赖库之间没有“一定行”的组合表,最重要的技能是看懂configure和编译报错信息,针对性地调。每次报错都是一次学习机会。
第二,能用二进制的绝不自己编译。如果只是Python调用,优先conda-forge或者pip官方wheel;只有做C++二次开发、需要自定义编译开关时,才值得走源码编译这条路。GDAL 1.11.5这种老版本之所以要自己编译,纯粹是因为那个年代没有这么好的预编译生态。
第三,环境变量是魔鬼。GDAL_DATA、PATH、PROJ_LIB,这三个变量占据了我排查GDAL问题的大半时间。每次在新环境里部署,先把这三个变量的值搞清楚再跑程序。
我个人在实际项目里总结出来的习惯是:先写一个环境检查的小脚本,把GDAL版本、PROJ版本、数据目录、dll搜索路径一口气打印出来,后面所有问题排查都先过一遍这个脚本,省掉大量重复劳动。
最后再分享一点关于后续扩展的想法——编完GDAL 1.11.5和mingw32这套环境后,如果你有权限升级依赖,可以试试在同一套MSYS2环境里把proj、geos升级到当时的次新版本,看GDAL的驱动和坐标系能力有什么变化。老版本GDAL对某些新格式支持有限,很多时候问题不在GDAL本身,而在底层依赖库版本,这一点想通了,后面的路就好走很多。
本文还有配套的精品资源,点击获取