ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

PostGIS 3.3.6 源码编译全指南:从依赖配置到扩展注册

PostGIS 3.3.6 源码编译全指南:从依赖配置到扩展注册 简介PostGIS 3.3.6 源码包是面向 PostgreSQL 数据库用户与 GIS 开发者的空间扩展安装包作为 PostgreSQL 最著名的开源空间扩展它遵循 OpenGIS 规范为数据库增加地理对象存储、空间索引与空间分析能力适合处理位置数据与 WebGIS 项目。压缩包共包含 2000 个文件以 C 源码、头文件、SQL 扩展脚本、多语言翻译文件及回归测试的 expected/wkt 结果为主同时含 shp2pgsql、pgsql2shp 等工具源码与文档包体约 16.98MB便于在已有 PostgreSQL 环境上按需编译部署。这些文件按模块组织便于查看扩展实现与测试用例。资源目前已有 66 人浏览学习。借助该安装包开发者可获得完整的三维空间类型、R 树索引、GeoJSON/Shapefile 导入导出函数及空间关系查询接口并能结合源码级示例排查扩展编译与经纬度投影转换中的常见问题是搭建空间数据库内核、进行 GIS 功能二次开发的重要基底。1. 为什么还要从 PostGIS 3.3.6 源码包手动编译面对一个已经在跑的 PostgreSQL 实例想让它具备查询经纬度、计算面积、做空间索引的能力最常见的选择是apt install postgis或者用 Docker 起一个带 PostGIS 的镜像。但这两条路在真实环境里都有明显短板系统源里的 PostGIS 版本往往和当前 PostgreSQL 的扩展版本不匹配Docker 镜像则无法覆盖已有集群。postgis-3.3.6.tar.gz 正是用来解决这类问题的——PostGIS 3.3.6 是 3.3.x 系列的一个维护版本对空间索引的稳定性、栅格驱动加载机制都有针对性修复同时又能兼容 PostgreSQL 12 到 16 的常见部署。手动编译这套源码包并不是因为源码安装更高级而是它能把 PostGIS 精确装进你已有的 PG 实例里不受发行版仓库版本滞后的限制。本文从依赖确认、configure 参数、make 安装到扩展注册把这条链路完整走一遍重点讲清楚每一步该看什么、错了怎么看。2. 编译 PostGIS 3.3.6 之前先确认依赖矩阵与版本兼容性PostGIS 不是一个独立运行的程序它是一组编译成共享库、挂载在 PostgreSQL 进程内的扩展。这意味着它的编译过程必须与正在使用的 PostgreSQL 版本保持二进制级别的匹配同时还依赖 GEOS、PROJ、GDAL 三个 GIS 基础库。这三个库分别负责几何算法、坐标参考系转换和栅格读写任何一个版本过低都会导致功能缺失或运行期崩溃。2.1 PostGIS 3.3.6 对 PostgreSQL 与 GIS 库的最低版本要求在解压之前我一般会先对照下面的依赖表逐项检查服务器上已有的库版本。PostGIS 3.3.x 系列的依赖底线是清晰的GEOS 不能低于 3.6PROJ 不能低于 4.9GDAL 不能低于 2.0JSON-C 不能低于 0.9。注意这些是最低要求实际使用中如果 GEOS 只有 3.6拓扑相关的ST_Node这类操作的性能会明显弱于 GEOS 3.10 以上的构建。依赖库最低版本主要作用检查命令PostgreSQL12宿主数据库提供扩展机制pg_config --versionGEOS3.6几何计算核心空间关系运算geos-config --versionPROJ4.9坐标系统转换 APIproj 21 | grep -i proj或projinfo --versionGDAL2.0栅格数据格式读写gdal-config --versionJSON-C0.9GeoJSON 解析pkg-config --modversion json-cLibXML22.5KML/GML 解析xml2-config --version一个容易踩的坑PostgreSQL 的版本探测依赖pg_config但这个命令只存在于postgresql-server-dev-*或postgresql-dev这类开发包中。如果你只装了 PostgreSQL 服务端pg_config可能根本不在 PATH 里。这时即使你把 postgis-3.3.6.tar.gz 解压出来configure 也会在第一步报错退出。2.2 用 pkg-config 和 ldconfig 快速摸清环境先跑一段快速检查脚本把上述依赖一次性打出来。这部分我习惯放在解压 tar 包之前因为一旦发现缺库用包管理器补齐比在 configure 报错后四处排查要快得多。echo PostGIS 依赖环境检查 echo PG: $(pg_config --version 2/dev/null || echo MISSING) echo GEOS: $(geos-config --version 2/dev/null || echo MISSING) echo GDAL: $(gdal-config --version 2/dev/null || echo MISSING) echo PROJ: $(proj 21 | grep -oE Rel\.[0-9.] || echo MISSING) echo JSON-C: $(pkg-config --modversion json-c 2/dev/null || echo MISSING) # 检查 GEOS 库是否真的能被动态链接器找到 ldconfig -p | grep libgeos_c.so || echo libgeos_c so not found每一行命令的含义并不复杂前四个是各自库的版本命令ldconfig -p则是确认 GEOS 的 C 接口库libgeos_c.so是否已经注册到系统动态链接库缓存里。如果你发现geos-config有输出但ldconfig找不到libgeos_c.so说明你机器的库安装路径没有写入/etc/ld.so.conf.d/后续编译能通过但启动 PostgreSQL 加载 PostGIS 时会报找不到libgeos_c.so.1。这种情况需要手动编辑 ld.so.conf 并把目录加入缓存。2.3 configure 选项中 5 个直接影响成败的路径参数PostGIS 3.3.6 的 configure 脚本支持一组--with-*config参数核心目的是让编译系统定位到正确的头文件和库文件。在标准安装路径下这些参数可以不写configure 会自己找但一旦 PostgreSQL 不是从系统包管理器安装的比如用 PostgreSQL 官方二进制或者编译到了/opt/pgsql就必须显式指定。tar -zxvf postgis-3.3.6.tar.gz cd postgis-3.3.6 ./configure \ --with-pgconfig/usr/lib/postgresql/15/bin/pg_config \ --with-geosconfig/usr/bin/geos-config \ --with-gdalconfig/usr/bin/gdal-config \ --with-projdir/usr \ --without-sfcgal--with-pgconfig指定 PostgreSQL 配置程序的绝对路径它决定后续编译时链接哪个版本的 PostgreSQL 头文件和库文件这个路径必须指向你实际要运行 PostGIS 的那套 PG而不是 PATH 里碰巧出现的另一个版本。--with-geosconfig和--with-gdalconfig同理分别指定 GEOS 和 GDAL 的配置工具。--with-projdir是 PROJ 的安装前缀如果你的 PROJ 装在/opt/proj就要改成--with-projdir/opt/proj。最后的--without-sfcgal表示不启用 SFCGAL 引擎这是可选的它提供更丰富的 3D 空间分析函数但会引入 Boost 依赖非必需场景可以不加。configure 结束后建议随手看一下输出末尾的摘要。它会列出哪些功能被启用、哪些被禁用比如Raster support: enabled、Topology support: enabled。如果这里显示 disabled后面对应功能不可用需要回到依赖层面解决。提示configure 只检查开发头文件是否存在不会验证运行时的动态库版本。编译安装完成后建议用ldd $(pg_config --pkglibdir)/postgis-3.so检查实际链接到的 GEOS/PROJ 对应文件路径。3. 动手编译 postgis-3.3.6.tar.gzmake 与安装configure 通过后接下来就是标准的 make 流程。这个阶段最容易出问题的地方反而不是 C 代码编译错误而是头文件目录冲突和并行编译时的资源不足。PostGIS 3.3.6 的代码量不小完整编译在普通服务器上需要两三分钟如果在编译过程中报错先不要急着改代码绝大多数错误都能从环境问题里找到答案。3.1 make 的全过程与关键输出执行编译安装时我常用的形式是并行编译加安装两步分离make -j$(nproc) sudo make installmake -j$(nproc)中的-j参数控制同时运行的编译任务数$(nproc)自动获取 CPU 核心数。这一步把源码编译成共享库文件。之后sudo make install会执行安装常见做法是把编译产物复制到 PostgreSQL 的扩展目录中包括postgis-3.so、控制文件postgis.control以及一系列 SQL 脚本。整个 install 过程通常只有几秒钟末尾会列出安装到了哪些目录值得看一眼路径是否符合预期。如果 make 输出中出现fatal error: geos_c.h: No such file or directory说明 GEOS 的开发头文件不在默认搜索路径中还可以通过设置CPPFLAGS补充查找范围make clean CPPFLAGS-I/opt/geos/include ./configure \ --with-pgconfig/usr/lib/postgresql/15/bin/pg_config \ --with-geosconfig/opt/geos/bin/geos-config make -j$(nproc)这里的CPPFLAGS作用等效于给 C 预处理器指定额外的头文件搜索路径-I/opt/geos/include对应 GEOS 头文件所在目录。注意需要用make clean先清掉上一次 configure 留下的缓存对象否则新旧参数混在一起会生成莫名其妙的链接错误。3.2 用 make check 跑回归测试安装完成后先别急着进数据库我建议在同一源码目录跑一遍 PostGIS 自带的回归测试确认当前环境下的空间函数行为正确make check这一步会启动一个临时的 PostgreSQL 实例加载刚刚编译出来的 PostGIS然后执行数千条空间查询断言。跑完会在regress/目录下生成测试报告只需关心最后的结果行。如果大量测试用例因为版本依赖失败基本可以断定是编译时和运行时库版本不一致最常见的就是 configure 时候 GEOS 是 3.8运行时候动态库被替换成了 3.6这种不一致会让ST_Intersects这类函数输出异常。make check需要当前用户有权限运行 PostgreSQL 服务如果没配好常见的报错是could not open relation或者权限拒绝。这时可以把检查交给 superuser 执行也可以在 configure 时指定--with-pgconfig所对应数据库实例的端口和 socket 目录通过环境变量传给 make checkPGPORT5432 PGHOST/var/run/postgresql make check3.3 install 之后立刻检查文件落位情况安装成功的标志不是make install退出码为 0而是这些文件确实出现在 PostgreSQL 扩展目录中。PostGIS 的常规扩展机制依赖$(pg_config --sharedir)/extension/下的.control文件和 SQL 脚本以及$(pg_config --pkglibdir)下的动态库。快速验证方式如下ls -la $(pg_config --pkglibdir)/postgis-3.so ls $(pg_config --sharedir)/extension/postgis*.controlpostgis-3.so是 PostGIS 的主体动态库postgis.control是扩展控制文件它声明了扩展名、默认版本、依赖关系等信息。动态库存在但控制文件缺失说明 install 过程被中断多半是没有用 root 权限执行make install或者 PostgreSQL 的路径配置自定义过。4. 在 PostgreSQL 中注册 PostGIS 扩展并验证空间能力编译安装只是第一步PostGIS 要真正工作还需要在目标数据库中执行CREATE EXTENSION。这一步把 SQL 函数声明、系统表和元数据写入数据库让 PostgreSQL 知道如何调用编译好的动态库。4.1 创建空间数据库并加载 postgis 扩展在 PostgreSQL 中扩展是按数据库粒度加载的。你需要为空间库建独立的 database然后加载扩展sudo -u postgres psql -c CREATE DATABASE gisdb; sudo -u postgres psql -d gisdb -c CREATE EXTENSION postgis;CREATE DATABASE gisdb创建新的空间数据库隔离业务数据与空间对象。CREATE EXTENSION postgis从postgis.control中读取扩展配置执行对应的 SQL 脚本postgis--3.3.6.sql脚本内容会创建spatial_ref_sys元数据表、几百个ST_开头的函数和类型转换规则。如果报错could not open extension control file说明make install没有把控制文件放到$(pg_config --sharedir)/extension下需要重新检查第 3.3 小节的安装路径。如果报错提示version 3.3.6 not found则说明扩展目录下没有对应版本的 SQL 脚本文件。更细致一点加载完主扩展后还可以选择性地加载配套扩展CREATE EXTENSION IF NOT EXISTS postgis_raster;postgis_raster在 3.3.x 里已经拆分为独立扩展如果需要处理栅格影像如遥感 TIFF 数据的入库和渲染需要单独启用。加载它和postgis的区别在于它注册的是栅格类型raster及其操作函数而postgis只覆盖矢量几何类型geometry。4.2 用版本函数和真实空间数据双重验证扩展加载成功后第一件事是确认版本其次是做一次真实的空间计算确认 GEOS、PROJ 运行期状态良好SELECT postgis_full_version();这条命令会输出 PostgreSQL 版本号、PostGIS 版本号、GEOS 版本、GDAL 版本、PROJ 版本以及它的编译选项。写出来的效果大致是POSTGIS3.3.6 [EXTENSION] PGSQL150 GEOS3.11.2 PROJ8.2.1 GDAL3.4.1 LIBXML2.9.13。看到 GEOS/PROJ 都能正常打印版本说明动态库链接完整。然后做一个最常见的坐标转换测试把火星坐标系的模拟点位转成 Web 墨卡托SELECT ST_AsText( ST_Transform( ST_SetSRID(ST_MakePoint(116.3913, 39.9075), 4326), 3857 ) );ST_MakePoint(116.3913, 39.9075)构造一个经度和纬度点ST_SetSRID(..., 4326)把该点指定为 WGS84 经纬度坐标系ST_Transform(..., 3857)转到 Web 墨卡托投影。ST_AsText把内部二进制几何输出为 WKT 字符串。如果这段能返回一组较大的投影坐标比如接近POINT(12958178.5 4825932.7)说明从几何构造到坐标转换的完整链路都正常。再验证空间索引是否可用用EXPLAIN看一眼查询计划EXPLAIN SELECT * FROM roads WHERE ST_DWithin(geom, ST_MakePoint(116.4, 39.9), 1000);查询计划里如果出现Bitmap Index Scan on roads_geom_idx说明GIST空间索引被正常使用了如果显示Seq Scan说明表上还没有建立空间索引需要先用CREATE INDEX roads_geom_idx ON roads USING GIST(geom);补上。提示PostGIS 加载完成后spatial_ref_sys表中已经预置了 8000 多种坐标参考系的定义不需要手动往里面插数据。实际生产库中如需新增自定义 SRIDINSERT 前要注意先检查srid是否冲突否则可能破坏坐标系查找。5. PostGIS 3.3.6 安装后的 3 个关键运行参数与排错技巧PostGIS 运行期的很多问题不是编译错误而是扩展加载后没有设置对应的 GUC 参数。下面三个点是我每次部署完必调的同时也是排查线上故障时优先查看的方向。5.1 postgis.gdal_enabled_drivers 与栅格驱动PostGIS 默认不启用任何 GDAL 驱动如果没有配置postgis.gdal_enabled_drivers所有栅格读写操作会直接报错。常见做法是在postgresql.conf中统一指定允许的驱动白名单postgis.gdal_enabled_drivers GTiff PNG JPEGGTiff对应 GeoTIFFPNG对应 PNG 图片JPEG对应 JPEG。启用后还需要切到数据库设置权限GRANT ALL ON FUNCTION ST_GDALDrivers() TO user;。有一个容易忽略的坑修改postgresql.conf后需要pg_reload_conf()生效这个参数是reload级别不需要重启实例。5.2 运行时报告 lib 版本不匹配的排查思路如果 PostgreSQL 日志中出现ERROR: could not load library ... libgeos_c.so.1: cannot open shared object file说明动态链接器没有在默认路径找到 GEOS。先执行ldconfig -p | grep geos确认 GEOS 在不在缓存中不在则执行echo /usr/lib/x86_64-linux-gnu /etc/ld.so.conf.d/geos.conf ldconfig如果ldconfig里已有 GEOS但仍报同样的错优先检查是否安装了多个版本——geos-config --version给出的版本只代表默认 PATH 里那个而 PostGIS 运行时看的是ldconfig缓存里libgeos_c.so.1符号链接指向的版本。解决方式是把目标 GEOS 库路径写进ld.so.conf.d/并放在靠前的位置然后重新加载缓存。5.3 从旧版本升级时使用 postgis_extensions_upgrade如果 PostgreSQL 中已经存在旧版 PostGIS例如 3.1.x不卸载旧扩展直接用新的动态库覆盖会引发版本错乱。标准做法是ALTER EXTENSION postgis UPDATE TO 3.3.6; SELECT postgis_extensions_upgrade();ALTER EXTENSION postgis UPDATE TO把扩展元数据指向新版本postgis_extensions_upgrade()会完成实际的数据字典迁移包括升级spatial_ref_sys和新函数的注册。升级前建议备份整个数据库特别是包含大量空间数据的库这个函数耗时随表数量增长大库上不要在生产高峰期执行。本文还有配套的精品资源点击获取
返回列表