ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

VS2017下GDAL库配置指南:三件套、编译与避坑

VS2017下GDAL库配置指南:三件套、编译与避坑 简介一份面向 Visual Studio 2017 环境的 GDAL 地理空间数据处理库专供在 Windows 平台上使用 C/C 开发 GIS 应用、遥感影像处理或空间分析任务的工程师、科研人员与在校学生解决原生开发环境下手动编译 GDAL 源码繁琐、依赖配置困难的问题。压缩包共一百零六个文件其中一百零四个为 GDAL/OGR 头文件覆盖栅格数据模型、矢量几何接口、坐标参考系统及通用工具库另附一个导入库文件和一个动态链接库文件编译产物约 5MB可直接放入 VS2017 项目进行链接省去源码构建与版本匹配的麻烦。这套库包含 GDAL 核心库和 OGR 矢量模块注册了超过 250 种地理空间数据格式驱动可调用 GDALAllRegister、GDALOpen、GDALRasterIO 等常用 API完成栅格读取、格式转换、重采样、裁剪、投影变换以及矢量要素操作适用于地形分析、影像拼接、地图制图、GIS 原型开发等场景。资源已有 306 人学习浏览压缩包内部目录简洁头文件与库文件划分清晰是搭建 GDAL 开发环境、研读 GDAL API 时颇具参考价值的配套资源。1. VS2017里折腾GDAL之前先把库的三件套搞清楚前几天有个做遥感的朋友问我“VS2017下GDAL库到底怎么整网上教程要么是老掉牙的2.2要么就是Linux编译Windows下新版根本编译不过。”这个问题我在不同场合被问过很多次。GDAL作为地理空间数据读写的事实标准遥感、GIS、测绘领域的项目几乎绕不开它但Windows下配合VS2017使用确实没有一份让人省心的现成答案。很多人一上来就搜“gdal vs2017库”然后下载一个编译好的压缩包解压以后往VS工程里塞结果编译报错、运行崩溃最后只能放弃。问题不是GDAL难用而是你没弄明白一个C库到底由哪几部分组成。GDAL库不是孤零零一个文件它由三件套构成头文件比如gdal_priv.h、gdal.h告诉编译器有哪些类、哪些函数可以用。没有头文件你的代码连编译都过不去。导入库.lib链接阶段用告诉链接器这个符号从哪个DLL里找。链接报错LNK2019这类问题八成是这里的路径没配好。动态链接库.dll程序运行阶段真正加载的二进制这里面的实现才决定功能能不能用。这三者必须“配套”。头文件版本太新、导入库版本太老、DLL版本又不一样这就是典型的“编译通过运行时起飞”。为什么特别强调VS2017因为MSVC每个大版本都有对应的运行时库。VS2017默认使用的是v141工具集也常被叫作vc15。GDAL的预编译包有的会标vc14、vc15、vc16、vc17实际上从VS2015开始微软做了一次C二进制兼容的生命线调整VS2015、2017、2019、2022编译出来的C代码可以互相链接所以VS2017也能配vc16/vc17编译的库。但这里面有个隐藏条件库的/MD动态运行时或/MT静态运行时必须跟项目一致。很多人没注意这一层全栽在运行时库不匹配上了。所以在折腾GDAL之前先记住一件事你要找的不是一个“安装包”而是一整套能够匹配你项目配置的头文件、导入库和DLL。后面所有的操作都是围绕这三个东西在做匹配。2. 想省事用预编译库先过版本匹配这一关不想自己编译的话最直接的办法是下载预编译好的GDAL库。常见的来源有GIS Internals、conda-forge和vcpkg。但预编译库不是解压就能用它有几个很容易踩的坑。先说GIS Internals。这个站的老版本GDAL包名里会带VS版本比如“release-1600-x64-gdal-3-6-3-mapserver-8-0-1”之类的但如果你下载的是比较新的版本很多已经标注成“2022”了。虽然是VS2022编译的由于MSVC2015~2022二进制兼容VS2017理论上能链接可一旦里面用了VS2017编译器不支持的C特性或者里面携带的第三方依赖库比如PROJ也是新版编译的问题就会变成“一个依赖套另一个依赖最终搞不清楚是哪个库在闹脾气”。如果你用vcpkg会简单很多。在vcpkg里执行vcpkg install gdal它会自动拉取GDAL以及PROJ、GEOS、SQLite3这些依赖并且默认配合当前VS工具链。但是vcpkg默认下载的是x86-windows版本如果你要用x64平台需要显式指定vcpkg install gdal:x64-windowsvcpkg的坑在于它可能会改变整个项目的构建方式。vcpkg会给CMake和MSBuild做集成安装完以后会在你的工程里自动加入include和lib路径。但如果你的项目还用了其他第三方库有时候vcpkg的版本会和已有库冲突排查起来很头疼。所以我的建议是如果你只是快速写个小工具验证功能预编译库够了如果你要交付项目或者要对GDAL做二次开发最好自己从头编译一遍。自己编译的另一个好处是你能控制GDAL去编译哪些驱动、跳过哪些驱动最终产出的DLL体积小得多依赖也可控。这里有一个必须注意的匹配问题预编译库通常是Release和/MD编译的你的VS项目如果开了Debug模式链接时大概率会出现LNK2038: mismatch detected for RuntimeLibrary。这是因为项目在Debug下默认用/MDd调试版运行时而库用的是/MD两者在二进制层面不互通。遇到这种情况要么把项目切到Release要么自己编译一个Debug版本的GDAL。自己去改预编译库的配置基本不现实比较理性的做法是整个开发环境统一成ReleaseMD或者统一成DebugMDd别混着用。3. 自己动手编译GDAL 3.xCMake配置是成败关键如果你决定自己编译首先要确认工具链。VS2017安装的时候要勾选“使用C的桌面开发”并且确认里面有v141工具集。GDAL 3.x从3.0开始全面切到CMake构建系统以前的nmake.opt老办法在3.0以后逐渐不被推荐所以你还得装一个CMake。建议用CMake 3.16以上太老版本对新版GDAL的CMake脚本支持不好。然后下载GDAL源码。建议从GitHub的releases页面下载对应版本的tar.gz或zip包比如GDAL 3.6.3、3.8.5等。如果你用的是GDAL 3.9、3.10这些新版本对编译器版本要求会更高VS2017不是不能用但有些代码片段可能编译不过后面细说。依赖库是个绕不开的话题。GDAL 3.x的CMake会自动探测PROJ、GEOS、SQLite3、TIFF、JPEG等库。如果系统里没有可以显式关闭cmake -S . -B build -G Visual Studio 15 2017 Win64 ^ -DCMAKE_BUILD_TYPERelease ^ -DCMAKE_INSTALL_PREFIXD:\GDAL ^ -DGDAL_USE_PROJOFF ^ -DGDAL_USE_GEOSOFF ^ -DGDAL_USE_SQLITE3OFF但关闭依赖会损失很大一部分功能。比如没有PROJGDAL的坐标系统转换基本就是残废状态没有SQLite3很多矢量驱动和GPKG格式用不了。所以遇到有依赖的第三方库我建议用vcpkg先装好vcpkg install proj:x64-windows geos:x64-windows sqlite3:x64-windows然后在CMake配置时指定vcpkg的installed目录cmake -S . -B build -G Visual Studio 15 2017 Win64 ^ -DCMAKE_BUILD_TYPERelease ^ -DCMAKE_PREFIX_PATHD:\vcpkg\installed\x64-windows ^ -DCMAKE_INSTALL_PREFIXD:\GDAL这一步是整个编译过程的成败关键。CMAKE_PREFIX_PATH指错位置CMake会找不到依赖库然后要么报错要么退化成只编译基础驱动。很多人编译到一半发现“没有PROJ支持”就是前期没配好这个路径。配置完成后构建和安装cmake --build build --config Release --target install也可以直接打开build目录下的gdal.sln用VS2017编译INSTALL项目。CMake已经把工程文件生成了选好Release、x64点生成即可。我把话放这儿这一步最折磨人的不是等编译而是看到一长串error或者warning根本不知道是哪个依赖引起的。我踩过最典型的坑是GDAL_USE_EXTERNAL_LIBS这个开关很多教程会说“用-DGDAL_USE_EXTERNAL_LIBSOFF”实际上这个开关控制得很杂关掉以后部分内置库会启用内部第三方代码反而可能带来更多问题。我现在的做法是不用这个开关而是把不想要的驱动逐个-DGDAL_USE_xxxOFF关掉比如不要NetCDF直接-DGDAL_USE_NETCDFOFF不要PDF直接-DGDAL_USE_PDFOFF。这样精细控制编译出来的GDAL功能完整度由自己说了算。4. VS2017工程接入GDAL库从属性配置到首个读取DemoGDAL编译安装完成之后D:\GDAL目录下会有include、lib、bin三个子目录。现在开始把它接入VS2017工程。打开VS2017新建一个C控制台应用注意平台选x64。然后右键工程属性翻到VC目录在“包含目录”里添加D:\GDAL\include在“库目录”里添加D:\GDAL\lib。再到“链接器-输入-附加依赖项”里填写导入库的名字我编译的GDAL 3.8默认生成的导入库是gdal_i.lib不同版本可能不一样打开D:\GDAL\lib目录看一眼就知道。写一个最简单的读取影像程序#include gdal_priv.h #include cstdio int main() { GDALAllRegister(); GDALDataset* ds (GDALDataset*)GDALOpen(test.tif, GA_ReadOnly); if (!ds) { printf(Open failed\n); return 1; } printf(Raster size: %dx%d\n, ds-GetRasterXSize(), ds-GetRasterYSize()); printf(Projection: %s\n, ds-GetProjectionRef()); GDALClose(ds); return 0; }编译的时候如果报错无法打开包括文件gdal_priv.h说明包含目录没写对如果报LNK2019无法解析的外部符号GDALAllRegister说明导入库没填对或者库目录没写对如果编译链接全通过跑起来却提示“找不到gdal.dll”那说明运行环境没配置好。运行阶段程序会按照“应用程序目录 - 系统PATH环境变量 - 系统目录”的顺序找DLL。最简单的方式是把D:\GDAL\bin\gdal.dll复制到你的exe所在目录。我不建议把GDAL的bin目录直接塞进C:\Windows\System32这样会影响其他项目使用不同版本GDAL。这一步还有一个很容易被忽略的细节如果你的项目里其他第三方库也使用了PROJ而GDAL自带的PROJ与那个库的PROJ版本不一致运行时可能直接崩溃。这种冲突在编译期完全看不出来我是怎么排查的用Dependency Walker或Dependencies工具查看exe加载的DLL路径确认到底加载了哪一个proj_*.dll。一旦发现两个PROJ同时被加载最简单的做法是把不需要的那个库的DLL从exe目录里拿掉。5. 那些让库“编译轻松、运行崩溃”的细节坑我最初以为GDAL编译好、塞进工程就能用结果被现实狠狠教育了几次。下面几个坑我觉得每个在VS2017里配GDAL的人都可能遇到。坑一LNK2038 RuntimeLibrary不匹配。这个问题在原理解析里讲过Debug和Release、/MD和/MT混用会导致链接器直接拒绝。我见过有人自己编译了Debug版GDAL但是项目设置的是Release编译出来还是报错。实际排查很简单报错信息会明确告诉你哪个库用了哪些格式比如“gdal_i.lib(gdal.obj): error LNK2038: mismatch detected for RuntimeLibrary: value MDd_DynamicRelease doesnt match value MD_DynamicRelease”。如果提示MDd就去编译一个Debug版别硬着头皮把项目释放成Release再编译那样就算你刚好绕过了这个错后面仍可能有其他坑。坑二GDAL版本号对不上程序一调用GDALAllRegister就崩溃。这种情况往往是因为运行环境的DLL和链接的.lib版本不一致。比如你链接的是gdal_i.lib它内部记录要加载gdal307.dll但你exe目录下放了一个旧版gdal306.dll这时程序跑起来不会报“找不到DLL”而是直接崩溃原因就是版本错位导致的符号地址错乱。解决办法是养成检查环境的好习惯写完代码先运行一句printf(GDALVersionInfo(RELEASE_NAME))看输出的版本号跟编译时是不是一致。坑三栅格驱动加载不上某些格式打不开。GDAL支持几十种数据格式但不是所有驱动都静态链接到gdal.dll里。有的驱动编译成插件放在plugins目录通过你设置的GDAL_DRIVER_PATH环境变量加载。如果你同时使用了多个GDAL版本插件目录配置错了就会出现“支持TIFF但不支持GeoJSON”这种诡异问题。我在代码里一般会加上CPLSetConfigOption(GDAL_DRIVER_PATH, D:\\GDAL\\lib\\gdalplugins);也可以设置系统环境变量原理一样。坑四坐标转换报PROJ相关错误。这是GDAL 3.x时代特有的坑。PROJ库从此不再只是简单的坐标转换代码它还需要外部的proj.db、proj.ini等数据文件。如果GDAL编译时开了PROJ支持运行环境里却找不到数据文件调用OGRCoordinateTransformation时动不动就返回错误。解决办法是设置环境变量PROJ_DATA指向PROJ的数据目录比如D:\vcpkg\installed\x64-windows\share\proj。VS2017的环境变量建议在Debugging里单独设置“环境”字段或者直接在系统环境变量里配我测试更稳定的是后者。这些坑的共同特征是编译期不报错运行期才暴露。我建议你在接入GDAL的初期就做一个“最小验证”新建一个空项目只包含上面那个打开影像的Demo先确认这个最简单的链路跑通再往里面加业务逻辑。直接在一个大项目里排查GDAL问题就像在大海捞针很难定位是哪一层出了问题。6. 新手最关心的延伸问题Python绑定、PROJ依赖与版本选择聊到这儿很多人会想到另一个热门话题既然Python里装GDAL那么简单为什么还要在VS2017里折腾C库先澄清一个概念。热词里提到的“gdal 3.10.1 cp313 cp313 win_amd64.whl”是Python版本为3.13、Windows 64位系统的预编译wheel包。它确实是GDAL但它是一个被包装过的Python模块内部自带了一套DLL跟你在VS2017工程里编译的C库是两个东西。如果你只想用Python处理栅格数据一条pip install GDAL3.10.1就搞定了但如果你的核心业务是用C写的还需要通过Python调用C库那必须保证两边是同一套GDAL二进制版本否则跨语言传递指针会出大问题。所以我的建议是C项目里的GDAL库优先自己编译Python这边要么用同一套源码编译Python绑定要么就干脆让C程序独立作为一个exe用Python去调用exe避免ABI层面的纠缠。关于版本选择VS2017用户别一味追新。GDAL 3.9之后对C版本的要求明显提高用了更多C17甚至C20的特性。VS2017对C17的支持只是部分支持强行编译新版本会碰到一堆语法兼容问题。我实测过GDAL 3.6.3、3.7.x、3.8.x在VS2017下编译基本没有大问题GDAL 3.10就吃力了很多新代码直接写C17的嵌套命名空间VS2017编译器会报错。如果你手头的VS2017没办法升级老老实实选3.6或3.8这种稳定版本功能上足够覆盖绝大多数项目。编译完以后建议对PROJ依赖做一个额外检查GDAL的CMake在发现PROJ时可能会自动让GDAL使用内部嵌入的PROJ数据路径但前提是PROJ的安装目录里真的包含了proj.db。用vcpkg安装的PROJ一般没问题但我遇到过用老版本源码编译PROJ时没有正确安装data目录的情况结果GDAL编译也过了运行坐标转换就报“数据库文件不存在”。这种问题很难在编译日志里发现只有在调用OGRCreateCoordinateTransformation后遇到输入坐标时才会反映出来。还有一个值得留意的点是GDAL的发布节奏。GDAL每年都会发新版本但LTS版本长期支持比较稳定。如果你要对接现有系统降级带来的兼容成本远比性能提升的收益高。别像我当年那样一看到3.10出了就想尝鲜结果在VS2017里折腾了两天编译最后还是回到3.8才把项目跑通。最后分享一个个人习惯我会在编译好的GDAL目录里写一个简单的Readme.txt把编译命令、依赖库版本、安装日期都记下来。过几个月回去维护老项目时光看目录结构能省很多时间。毕竟GDAL配置一次不容易记录下来才算真正把经验沉淀下来了。本文还有配套的精品资源点击获取
返回列表