资讯动态

源码编译GDAL 3.5.3与PROJ 6完整指南

发布时间:2026/9/9 17:01:16 来源:尧图企业网站定制
直接用系统源里的 libproj 和 libgdal 是最省事的但干 GIS 这行的人迟早会被老版本卡脖子。要么是投影转换不一致要么是 GDAL API 变了而系统包还停在几年前的版本要么干脆就是缺了某个新扩展但包管理器里没有。我这边遇到的实际需求是需要 PROJ 6 的坐标转换能力配合 GDAL 3.5.3 做栅格重投影而系统源给我的是旧版 PROJ 4.x完全没法满足。所以只能走源码编译这条路今天把这套完整流程和踩坑点都盘一遍。先说一下版本关系。GDAL 3.5.3 这个版本在构建时要求 PROJ 必须不低于 6.0也就是说 PROJ 6 是它的底线版本。很多人以为 PROJ 6 只是个中间版本实际上从 PROJ 6 开始架构发生了很大变化引入了基于 SQLite 的 PROJ 数据库并且不再以老旧方式导出传统 proj_api.h 接口。GDAL 3.5.3 与 PROJ 6 搭配完全可行而且这套组合在稳定性和功能上都很均衡比硬上最新版 PROJ 更稳妥。下面的过程我基于 Ubuntu/Debian 系统来演示RHEL/CentOS 系把对应包名换成 dnf 的即可。1. 这一组合的版本约束为什么 GDAL 3.5.3 与 PROJ 6 适配最稳很多做影像处理或空间分析的人在编译 GDAL 之前根本没意识到GDAL 对 PROJ 是有最小版本要求的。GDAL 3.5.3 的 configure 脚本会专门检测 PROJ 的版本号如果低于 6.0 就直接报错退出不会让你蒙混过关。相反如果你盲目选择了太新的 PROJ 版本比如 PROJ 9.x虽然也能编译通过但某些老旧的第三方模块在运行时可能因为 API 变更出现兼容性问题。所以标题里明确写 PROJ 6 和 GDAL 3.5.3其实是经过实践验证的组合。这里的核心约束在于两件事。第一是 ABI应用二进制接口变化PROJ 从 6.0 开始引入了新的 proj.h 头文件不再使用 proj_api.hGDAL 3.5.x 正是基于这个新 API 编译的。第二是数据文件结构PROJ 6 抛弃了传统的 epsg 文件改用 SQLite 数据库文件 proj.dbGDAL 在运行时也需要找到这个数据库才能进行坐标转换。从我的角度来说这套组合的另一个优势是编译失败率低。GDAL 3.5.3 在 configure 阶段会自动检测 PROJ 6 并启用 PROJ 相关的支持不需要额外打补丁PROJ 6 的 CMake 构建系统也相当完善不会遇到那种“编译出来却找不到头文件”的玄学问题。如果你有选择困难建议直接锁死这个版本组合。2. 开工前工具链与依赖清单少装一个都会卡配置源码编译这种事情准备工作决定了后面 80% 的顺利程度。我见过太多人在 configure 报错之后才开始逐个装包效率极低。建议先把编译工具链和基础依赖装齐再开始下载源码。2.1 编译工具链检测第一个要确认的是系统有没有完整的编译环境。执行 gcc --version、make --version、cmake --version如果提示找不到命令就需要安装。sudo apt update sudo apt install -y build-essential cmake make pkg-config这里需要注意几点。第一build-essential 这个包在 Ubuntu 上会带来 gcc、g、make 等核心工具是无论如何都绕不开的。第二pkg-config 非常重要因为 GDAL 在 configure 时需要通过它来定位 PROJ 的安装路径信息没有 pkg-config 的话即使 PROJ 装好了GDAL 也可能找不到它。第三CMake 版本不要太老。PROJ 6 要求 CMake 3.9 以上如果你用的是上古版本的系统建议先检查一下 cmake --version 的输出低于 3.9 就升级一下。可以在 CMake 官网下载新版本或者用 pip install cmake 方式安装。2.2 系统依赖库清单编译 PROJ 6 时最关键的第三方依赖是 SQLite 3这是硬性要求。PROJ 6 的 proj.db 数据库文件需要 SQLite 来读写。在 Ubuntu 上安装sudo apt install -y sqlite3 libsqlite3-dev千万别只装 sqlite3 命令行工具而漏了 libsqlite3-dev否则 CMake 配置 PROJ 时会直接报找不到 SQLite3那是非常典型的低级错误。除此之外为了让 GDAL 尽量多支持常见栅格格式建议把下面这些库也装上。注意这些不是 GDAL 的编译硬性依赖不装也能编译只是对应的驱动就不会被启用sudo apt install -y libtiff5-dev libjpeg-dev libpng-dev \ libcurl4-openssl-dev libgeos-dev libxml2-dev \ libexpat1-dev zlib1g-dev这些库分别对应 TIFF/JPEG/PNG 驱动、网络下载驱动、GEOS 几何运算能力、XML 解析等。GDAL 是插件化架构configure 时检测到哪些库就会自动启用对应的驱动所以装全一点能省去后续重编的麻烦。2.3 关于系统自带的 libproj-dev 的警告这里要特别提醒一个坑不要直接安装系统的 libproj-dev 包。因为系统自带的版本通常是旧版比如 Ubuntu 18.04 上的 PROJ 4.9一旦装了系统路径 /usr/include 和 /usr/lib 下就会出现一套旧版 PROJ 的头文件与库文件。我们后续手动编译的新版 PROJ 安装到 /usr/local 目录如果不小心GDAL 的 configure 脚本可能会优先找到系统旧版 PROJ从而出现版本冲突。如果你已经在系统里装了 libproj-dev最简单的处理方式是先卸载确保后面编译环境绝对干净sudo apt remove --purge libproj-dev proj-bin当然如果你有信心通过环境变量把新版 PROJ 路径控制好也可以不卸载。但我的建议是“源码编译时环境越干净越好”不要给自己留隐患。3. PROJ 6 的 CMake 编译流程独立前缀是关键PROJ 6 的版本号后缀很多比如 6.3.2、6.3.1、6.2.1。建议直接使用 6.3.2这个版本在整个 6.x 系列里相当稳定修复了多个坐标转换边界问题。下面是完整步骤。3.1 下载源码并解压wget https://download.osgeo.org/proj/proj-6.3.2.tar.gz tar -xzf proj-6.3.2.tar.gz cd proj-6.3.2如果 wget 网络太慢可以试试 curl -O 或者用国内镜像。这里不用纠结只要能把源码拿下来就行。3.2 配置 CMake 构建参数PROJ 从 6.0 开始推荐使用 CMake 而不是传统的 configure 脚本。我们在源码根目录下创建一个 build 目录把构建产物和源码隔离开这是 CMake 的标准做法也方便以后清理。mkdir build cd build cmake .. \ -DCMAKE_INSTALL_PREFIX/usr/local/proj63 \ -DBUILD_SHARED_LIBSON \ -DBUILD_TESTINGOFF \ -DCMAKE_BUILD_TYPERelease重点解释一下这里的核心参数CMAKE_INSTALL_PREFIX 指定安装前缀是 /usr/local/proj63。这不是默认路径而是我有意为之。独立前缀的好处是以后想卸载或者切换 PROJ 版本时直接删这个目录就行不会污染系统的 /usr 目录。而且多版本并存时也能轻松隔离。BUILD_SHARED_LIBS 设为 ON编译动态库。如果你需要静态链接可以改成 OFF但绝大多数场景下动态库更省心符合 Linux 系统习惯。BUILD_TESTING 设为 OFF跳过测试用例编译能大幅缩短编译时间。3.3 执行编译与安装make -j$(nproc) sudo make installmake -j 后面的参数是并行编译的线程数$(nproc) 会自动读取 CPU 核心数。如果你机器内存比较小比如只有 4GB建议把 -j 参数减小一点比如 make -j2否则内存可能瞬间被打满。PROJ 的编译不算太慢但在老机器上并行编译 OOM 也不是没可能。安装完成之后可以看到 /usr/local/proj63 目录下会有 bin、lib、share 等子目录。其中 share/proj 里放着 proj.db 和各类转换参数文件这些是运行时的数据文件不能缺。3.4 安装后验证 PROJ 是否正常先设置环境变量让系统能找到新版 PROJ 的可执行文件和库export PATH/usr/local/proj63/bin:$PATH export LD_LIBRARY_PATH/usr/local/proj63/lib:$LD_LIBRARY_PATH然后测试projinfo EPSG:4326如果正常输出 “PROJ.4 string: projlonglat datumWGS84 no_defs” 或类似的坐标系统信息说明 PROJ 安装成功。另外还可以执行 proj 命令查看版本或者直接查看 /usr/local/proj63/lib 下是否有 libproj.so 文件。需要注意的是这里的环境变量是临时的只在当前终端有效。等 GDAL 编译完以后我们还需要写进 ~/.bashrc 或 /etc/profile 里保证运行时也能找到。4. 正式编译 GDAL 3.5.3 前的“找 PROJ”细节这是整个编译过程中最容易出错、也最容易让人抓狂的阶段。GDAL 是 autotools 体系configure 阶段会搜索 PROJ 的安装位置。但我们把 PROJ 装在非标准路径 /usr/local/proj63configure 的默认搜索路径找不到它必须手动告诉它。4.1 设置 PKG_CONFIG_PATH 与 PATHGDAL 通过 pkg-config 来定位 PROJ所以关键的一步是把 PROJ 的 pkgconfig 文件路径加进去export PKG_CONFIG_PATH/usr/local/proj63/lib/pkgconfig:$PKG_CONFIG_PATH export PATH/usr/local/proj63/bin:$PATH这样 configure 脚本内部执行 PKG_CHECK_MODULES 或直接调用 pkg-config --exists proj 时就能找到 PROJ 6。如果你不设置 PKG_CONFIG_PATHconfigure 会在系统默认路径 /usr/lib/pkgconfig、/usr/share/pkgconfig 里找大概率找到的是旧版或不存在的 proj.pc然后报“PROJ 6.0 or later required”的错误。4.2 旧版本 PROJ 干扰的识别一个非常经典的场景系统里已经通过 apt 装了旧版 proj-bin或者 /usr/local/lib 下残留了某个旧版 libproj.so。这时候即使你设置了 PKG_CONFIG_PATHconfigure 也可能因为头文件顺序问题检测到旧版头文件。遇到这种情况可以先执行 pkg-config --modversion proj 看看输出是什么版本。如果输出的是 4.9 或 5.x说明 PKG_CONFIG_PATH 没有生效或者 /usr/local/proj63/lib/pkgconfig 下根本没有 proj.pc。检查一下 PROJ 是否真的安装到了这个目录没有就回去看第 3 节。如果 pkg-config 输出版本是 6.3.2但 configure 依然报错还有一个可能性是某些环境变量污染了编译器头文件搜索路径比如 CFLAGS 或 CPPFLAGS 里写了不合适的 -I 参数。建议用中规中矩的方式./configure --with-proj/usr/local/proj63显式指定 PROJ 路径不依赖自动搜索绕开一切环境变量干扰。4.3 控制可选功能避免无谓的编译失败GDAL 支持上百种驱动真没必要全部编译。像 Python 绑定、PostgreSQL 驱动、OpenCL、HDF5 这些如果你实际用不到完全可以关掉省时省力。特别是 Python 绑定默认如果你系统里没有 SWIG 或 numpy 开发库configure 阶段可能会报错或者生成用不了的绑定。建议明确关闭--without-python --without-java另外如果你想用的只是常见的栅格和矢量格式那么上面“系统依赖库”装好的 TIFF、JPEG、PNG、CURL、GEOS 等已经覆盖了绝大多数场景。不要追求全功能编译那是压榨自己的时间。5. GDAL 3.5.3 的 configure/make 完整流程准备工作做完下面是真正的 GDAL 编译环节。这里我给出一个比较稳妥的 configure 组合并逐项解释。5.1 configure 参数选择cd gdal-3.5.3 export PKG_CONFIG_PATH/usr/local/proj63/lib/pkgconfig:$PKG_CONFIG_PATH export PATH/usr/local/proj63/bin:$PATH ./configure \ --prefix/opt/gdal353 \ --with-proj/usr/local/proj63 \ --with-curl \ --with-libtiff \ --with-geos \ --without-python \ --without-java \ --without-ogr \ --without-hdf5参数分解如下--prefix/opt/gdal353安装到 /opt/gdal353独立目录和 PROJ 的思路一致。--with-proj/usr/local/proj63直接指定 PROJ 6 的安装目录这是最重要的一个参数。--with-curl、--with-libtiff、--with-geos启用对应的系统库编译出网络、TIFF、几何运算支持。--without-python、--without-java关闭不需要的绑定。--without-hdf5如果没装 HDF5 开发库这个参数能避免 configure 强行搜索导致报错或忽略。实际项目里如果你明确不需要直接关掉最省心。注意GDAL 3.5.3 的 configure 脚本相比早期版本更严格。如果某个依赖库缺少开发头文件configure 通常会输出一个 WARNING 然后自动禁用对应驱动这是正常现象不是错误。真正会导致中止的是像 PROJ 版本不够这类硬性条件。5.2 编译安装make -j$(nproc) sudo make installGDAL 的编译量比 PROJ 大得多。全功能编译的话在我的机器上大概要 10 到 15 分钟如果你只有两个核心时间可能翻倍。这里建议先在 make -j 之后看一眼输出有没有红色 ERROR如果只是黄色 WARNING 就可以继续等。编译完成并安装后把 GDAL 的库路径也加进环境变量export LD_LIBRARY_PATH/opt/gdal353/lib:/usr/local/proj63/lib:$LD_LIBRARY_PATH export PATH/opt/gdal353/bin:$PATH然后验证版本gdalinfo --version正常会输出GDAL 3.5.3, released 2022/10/26这就说明 GDAL 本体编译成功且已经能正常找到共享库。如果提示找不到 libgdal.so那就是 LD_LIBRARY_PATH 没生效或没设置对。5.3 检查 GDAL 是否正确启用了 PROJ这一步很多人会忽略但恰恰是最关键的。GDAL 虽然编译出来了但你无法确定它到底链接的是哪个 PROJ。执行gdalinfo --format GTiff输出的前两行通常包含Format Details: PROJ: 6.3.2注意看有没有这一行。如果 PROJ 版本显示成 4.x说明 GDAL 在编译时被系统旧版干扰了没找对 PROJ。这种情况虽然也能编译成功但最终运行时会有一堆坐标转换错误而且很难排查。另外一个更直接的验证方法是ldd /opt/gdal353/bin/gdalinfo | grep proj看输出里 libproj.so 指向的是 /usr/local/proj63/lib 还是 /usr/lib/x86_64-linux-gnu。如果指向了系统路径说明运行时加载了旧版 PROJ你得调整 LD_LIBRARY_PATH 的顺序把 /usr/local/proj63/lib 放在最前面。6. 安装后验证与动态链接排查编译安装完成不是终点真正跑业务时动态链接的问题才会暴露出来。这一节聚焦于实际运行中常见的坑。6.1 验证 GDAL 链接到哪个 PROJ用 ldd 检查是所有排查的第一步。如果 ldd 输出中 libproj.so 指向了非预期路径你有几个选择第一种修改 LD_LIBRARY_PATH 环境变量。这种方案适合当前 shell 临时使用export LD_LIBRARY_PATH/usr/local/proj63/lib:/opt/gdal353/lib:$LD_LIBRARY_PATH第二种把这两行写入 ~/.bashrc让以后每个终端都自动生效echo export LD_LIBRARY_PATH/usr/local/proj63/lib:/opt/gdal353/lib:$LD_LIBRARY_PATH ~/.bashrc source ~/.bashrc第三种如果你要部署到其他机器上建议用 ldconfig 方式写入 /etc/ld.so.conf.d/ 下的自定义文件但这会全局生效改动力度较大。多数场景下写 ~/.bashrc 就够用了。6.2 缺少 proj.db 导致的坐标转换错误PROJ 6 以前的版本使用文本文件定义坐标参数但 PROJ 6 开始改用 SQLite 数据库 proj.db。如果你在运行时移动了 PROJ 安装目录或环境变量没设置正确GDAL 调用投影函数时可能输出如下类似的错误PROJ: proj_create: Cannot find proj.db解决办法是确保环境变量 PROJ_LIB 指向 proj.db 所在的目录export PROJ_LIB/usr/local/proj63/share/proj如果是 GDAL 程序也可以设置 GDAL_DATA 指向 GDAL 的 share 目录不过对于坐标转换来说最直接的环境变量是 PROJ_LIB。这个坑我踩过一次当时以为 GDAL 编译有问题排查了半天才发现是环境变量丢了。6.3 多版本共存时的优先级问题如果你机器上同时存在系统自带的 PROJ 和新编译的 PROJ 6动态链接器会按照 LD_LIBRARY_PATH、ldconfig 缓存、默认路径的顺序去查找。LD_LIBRARY_PATH 中的目录优先级最高所以只要把 /usr/local/proj63/lib 放到最前面基本不会出问题。但如果你是通过 ldconfig 方式安装比如把 /usr/local/proj63/lib 写入了 /etc/ld.so.conf.d/proj63.conf那么 ldconfig 缓存的优先级会高于 LD_LIBRARY_PATH 吗并不会。LD_LIBRARY_PATH 的优先级实际上高于默认缓存这是很多人的误区。所以正常来说设置 LD_LIBRARY_PATH 即可。6.4 典型错误的快速定位表为了让你在报错时不慌我这里整理了一个快速定位表。现象可能原因处理办法configure 报 PROJ 6.0 or later requiredPKG_CONFIG_PATH 没设置或指向了旧版export PKG_CONFIG_PATH再用 projinfo 验证CMake 阶段找不到 SQLite3缺少 libsqlite3-dev安装 libsqlite3-dev 后重新配置gdalinfo --version 能运行但 ldd 显示旧版 libprojLD_LIBRARY_PATH 顺序错误确保 /usr/local/proj63/lib 在最前面运行时报 Cannot find proj.dbPROJ_LIB 环境变量缺失export PROJ_LIB/usr/local/proj63/share/projmake 过程中内存不足被杀并行编译线程过多改用 make -j2 或 make -j1configure 找不到 libcurl缺少 libcurl4-openssl-dev安装后重新 configure7. 一些实战心得与建议先把 .bashrc 环境变量一次性配好别等运行报错才补。我在第 5 节结尾提到的那三行 export 建议直接写进 ~/.bashrc这样以后打开终端就能用不用每次手动 export。如果你经常在多个项目间切换也可以写成独立的 env.sh 脚本需要时 source 一下。关于编译过程中遇到的 warning不要全部无视也不要全部在意。GDAL configure 阶段会有大量 “checking for … no” 的输出这是它在探测依赖正常的。真正的错误特征是 configure 在中途退出或者 make 时出现 fatal error。如果你看到 configure 最后有 warning 说禁用了某个驱动而你确实需要这个驱动那就回去装依赖再重新 configure。我的习惯是保留 configure 日志。执行 configure 时可以把输出同时写入文件./configure ... 21 | tee /tmp/gdal_configure.log这样就算后面发现问题也能回头查具体是哪个环节出了问题比自己凭记忆排查高效得多。最后一个建议如果编译出来的 GDAL 只是给自己项目用不建议使用 make install 覆盖系统默认路径。把所有文件装到独立的 /usr/local/proj63 和 /opt/gdal353 下未来想升级或回退版本时直接改环境变量切换即可这种“隔离安装”的方式在多版本并存的场景下能帮你省掉非常多的麻烦。而且就算你哪天把这个目录整个删掉也不会影响系统其他软件值得养成习惯。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价