第03章 - 安装配置与环境搭建
3.1 装之前先回答三个问题
PDAL 的安装失败,绝大多数不是命令敲错,而是装法选错。动手前先确定三件事:
- 只要命令行,还是要 C++/Python 开发能力? 只要命令行,conda 或 Docker 一条命令就能用;要写 C++ 扩展,必须装开发文件(头文件 + 库);只要 Python,
pip install pdal仍然需要底层有可用的 PDAL 库。 - 能不能连外网? 内网离线环境要用 conda 的离线包或自建镜像,源码编译要提前把依赖全备齐。
- 版本要不要固定? 生产环境必须固定。PDAL 的 minor 版本会改默认行为(见第 1 章
writers.las.minor_version的例子),跟着latest走迟早踩到。
本章以 PDAL 2.10.0 为基线,覆盖四个平台方向:conda(全平台首选)、Docker(服务化/批处理)、pip(Python)、源码编译(定制与内网)。
3.2 依赖清单:以源码为准,不要以文档为准
PDAL 的编译期依赖写在 cmake/*.cmake 里,比文档新也硬。2.10.0 的关键约束:
表 3-1 PDAL 2.10.0 的必需依赖(取自源码 cmake 脚本)
| 依赖 | 版本要求 | 出处 | 用途 |
|---|---|---|---|
| CMake | ≥ 3.13 | CMakeLists.txt 的 cmake_minimum_required |
构建系统 |
| GDAL | ≥ 3.8 | cmake/gdal.cmake 里显式 FATAL_ERROR 检查 |
坐标系、栅格/矢量驱动 |
| PROJ | ≥ 9.0 | cmake/proj.cmake:find_package(PROJ 9.0 REQUIRED CONFIG) |
坐标转换 |
| GeoTIFF | ≥ 1.7.0 | cmake/geotiff.cmake |
LAS 里 GeoKey 支持 |
| curl | 必需 | cmake/curl.cmake:find_package(CURL REQUIRED) |
远程文件(EPT/COPC/HTTP) |
| zlib / liblzma | 必需 | cmake/zlib.cmake、cmake/lzma.cmake |
压缩 |
| laz-perf | 随源码内嵌 | vendor/lazperf |
LAZ 编解码 |
这里有两处文档与源码不一致,必须按源码来:
- 官方
doc/development/compilation/unix.md写 “PDAL requires at least version 3.5 of CMake”,但顶层CMakeLists.txt实际是cmake_minimum_required(VERSION 3.13); doc/development/compilation/dependencies.md写 GeoTIFF “1.3+”,cmake/geotiff.cmake实际要求1.7.0。
照文档装低版本依赖,会在 CMake 配置阶段直接失败。这条经验对任何 C++ 项目都成立:版本下限看构建脚本,行为说明看文档。
还有一条历史坑值得写进团队 wiki:GDAL 内部会嵌入一份 libgeotiff 并剥掉 PDAL 需要的符号,所以 PDAL 不能简单链接系统 GDAL。如果你自己编译这两个库,构建 GDAL 时必须打开 “External libgeotiff”;用 conda-forge 的话这个问题已经处理好,不用管。
3.3 首选方案:conda-forge
Windows 上这是官方唯一推荐的二进制渠道(只提供 64 位),Linux/macOS 同样可用。
# 新建独立环境并装上 PDAL 命令行
conda create --yes --name pdal --channel conda-forge pdal
conda activate pdal
# 需要 Python 绑定时(会连带装上 gdal)
conda install -c conda-forge python-pdal gdal
包名要分清,官方文档写得很明确:
| 包名 | 装什么 | 适用 |
|---|---|---|
pdal |
命令行程序 和 开发文件 | C++ 开发、命令行使用 |
libpdal |
只有基础库 | 自己写程序链接 PDAL |
python-pdal |
Python 扩展(依赖 pdal) | Python 调用 |
不要把 PDAL 装进 base 环境。 官方在 quickstart 里专门用 warning 强调过这一点。base 环境里既有 Python 又有各种地理库时,conda 的 solver 很容易为了满足版本约束把 GDAL/PROJ 降级,进而破坏其他工具链。
升级与查看:
conda update pdal
conda list pdal
conda list 显示的是包版本,不一定等于 pdal --version——如果 PATH 里有另一个 PDAL(比如之前手动编译在 /usr/local/bin 的),命令行的实际行为可能来自那个。用 which pdal(Windows 用 where pdal)确认可执行文件路径。
3.4 Docker:批处理与服务化
仓库和 Docker Hub 维护两个镜像标签(doc/project/docker.md):
pdal/pdal:latest:跟随 masterpdal/pdal:<version>:跟随当前发布版
# 交互式跑一条 pipeline
docker run --rm -v "$PWD":/data -w /data pdal/pdal:2.10.0 \
pdal pipeline tin.json
# 直接在容器里执行任意 pdal 子命令
docker run --rm -v "$PWD":/data -w /data pdal/pdal:2.10.0 \
pdal info --summary /data/input.las
要点三个:
-w /data必须设,否则相对路径解析在以镜像 WORKDIR 为基准的位置,pipeline 里的相对文件名会找不到;- 用版本号标签,别用
latest。latest跟 master,行为随时会变; - 容器默认不带数据,务必用
-v挂载,别用docker cp来回搬几十 GB 的点云。
镜像里附带的环境是可复现的(依赖由镜像构建时锁定),这也是批处理平台最省事的部署形态:把 pipeline JSON 和输入挂进去,输出挂出来,剩下交给调度器。
3.5 Python 绑定:pip 与 conda 两条路
doc/python.md 说得很清楚:PDAL 的 Python 支持分两层,一层是把 Python 嵌进 pipeline(filters.python),一层是让 Python 调 PDAL(pdal 扩展)。两者都与 NumPy 强绑定——数据以 NumPy 数组进出。
conda 路线(最省心,会连带安装 PDAL):
conda create -n pdalpy -c conda-forge python-pdal
conda activate pdalpy
python -c "import pdal; print(pdal.__version__)"
pip 路线(要求系统里已有可用的 PDAL 库):
pip install PDAL
如果 import pdal 报 ImportError: libpdalcpp.so…: cannot open shared object file,说明 Python 扩展编好了但运行时找不到 PDAL 库——这是 pip 路线最典型的问题,解决方式是让动态链接器能找到库:
# Linux:把 PDAL 库目录加入搜索路径(或写进 /etc/ld.so.conf)
export LD_LIBRARY_PATH=/usr/local/lib:\$LD_LIBRARY_PATH
# macOS
export DYLD_LIBRARY_PATH=/usr/local/lib:\$DYLD_LIBRARY_PATH
Windows 上通常表现为 DLL load failed,把 pdalcpp.dll 所在目录加入 PATH 即可。这也解释了为什么 Windows 上更推荐 conda——它把 DLL 搜索路径一并配好了。
2.1 版本之后有一个变化要记住:以前 Python 相关能力分散在嵌入的 readers.numpy/filters.python 与 PyPI 扩展两处;从 PDAL 2.1 / pdal-python 2.3 起,嵌入 stage 与扩展都从 PyPI 分发。
3.6 源码编译:Unix 与 Windows
需要定制(打开特定插件、内网离线、打补丁)时才走这条路。官方 Unix 流程是 CMake + Ninja:
git clone https://github.com/PDAL/PDAL.git
cd PDAL
git checkout 2.10.0 # 生产环境钉 tag,不要跟 master
mkdir build && cd build
cmake -G Ninja ..
ninja
sudo ninja install
Unix 上依赖通常只需要先装 GDAL,其余由包管理自动带出:
# Debian / Ubuntu
sudo apt install libgdal-dev libgeotiff-dev libproj-dev libxml2-dev
# 或走 conda 依赖
conda install gdal geotiff proj curl zlib xz
Windows 上官方推荐用 conda 提供全部依赖,再调 MSVC 编译。GitHub Actions 的 scripts/ci/win 目录就是权威的依赖清单,其 conda install 一行大致是:
conda install geotiff laszip nitro curl ^
gdal pcl cmake eigen ninja libgdal ^
zstd numpy xz libxml2 laz-perf qhull ^
sqlite hdf5 tiledb conda-build ninja -y
然后:
cmake -G "NMake Makefiles" ..
nmake /f Makefile
几个 CMake 开关值得记(来自 cmake/options.cmake)。注意它们的默认值普遍是 OFF,意味着“不显式打开就没有”:
| 选项 | 默认 | 说明 |
|---|---|---|
WITH_TESTS |
ON | 是否构建单元测试 |
WITH_GCS |
ON | 谷歌云存储支持(需要 OpenSSL) |
WITH_COMPLETION |
OFF | bash 补全脚本 |
BUILD_PLUGIN_PGPOINTCLOUD |
OFF | PostgreSQL PointCloud 读写 |
BUILD_PLUGIN_E57 |
OFF | E57 读写 |
BUILD_PLUGIN_TILEDB |
OFF | TileDB 读写 |
BUILD_PLUGIN_HDF |
OFF | HDF5 读取 |
BUILD_PLUGIN_MATLAB |
OFF | .mat 读写 |
BUILD_PLUGIN_ARROW |
OFF | Arrow/Parquet 读写 |
BUILD_PLUGIN_TRAJECTORY |
OFF | 由 LAS 推算轨迹(需 Ceres) |
所以“文档里有 readers.e57,为什么我的 pdal --drivers 里没有”这个问题,答案往往就在这里——编译时没开 BUILD_PLUGIN_E57。
打开方式:
cmake -G Ninja \
-DBUILD_PLUGIN_E57=ON \
-DBUILD_PLUGIN_PGPOINTCLOUD=ON \
-DCMAKE_BUILD_TYPE=Release \
..
编译完成后的快速验证:
ls bin/pdal
bin/pdal --version
bin/pdal --drivers | head
ctest # 只想确认功能可用时跑一遍
3.7 装完必做的五项检查
装完不要急着建 pipeline,先按顺序验五件事。任何一项失败,后面都会以更难懂的形式炸出来。
# 1. 版本与构建信息
pdal --version
# pdal 2.10.0 (git-version: Release)
# 2. 可用 stage 数量与关键 stage 是否存在
pdal --drivers | wc -l
pdal --drivers | grep -E "readers.las|filters.smrf|writers.gdal"
# 3. 可用子命令
pdal --list-commands
# 4. 某个 stage 的完整选项表(比查文档快,且与当前二进制一致)
pdal --options writers.gdal
pdal --options all | head -100
# 5. 端到端冒烟测试
pdal info --summary your.las
第 4 条特别值得养成习惯:pdal --options <stage> 打印的是当前这个二进制的参数、类型与默认值。文档写的是某个版本的行为,而你的二进制可能是另一版。遇到“参数不生效”时,先用它核对参数名。
pdal --drivers 有个隐藏参数 --showjson,输出 JSON 而不是表格,每个 stage 带 name、description、link、extensions、streamable 五个字段。streamable 正好回答第 1 章留下的问题:这条 stage 能不能走流式。
pdal --drivers --showjson | python -c "
import json,sys
for d in json.load(sys.stdin):
print(d['name'], d['streamable'])
"
3.8 环境变量与路径
| 变量 | 作用 | 备注 |
|---|---|---|
PDAL_DRIVER_PATH |
追加插件搜索目录 | Linux/macOS 用 :,Windows 用 ; 分隔 |
LD_LIBRARY_PATH / DYLD_LIBRARY_PATH / PATH |
运行时库搜索 | pip 安装的 Python 扩展依赖此路径找 libpdalcpp |
PROJ_DATA(旧版 PROJ_LIB) |
PROJ 的坐标数据库目录 | 坐标系解析失败时优先查它 |
GDAL_DATA |
GDAL 数据文件目录 | 某些驱动与坐标系统依赖 |
GDAL_CACHEMAX |
GDAL 栅格缓存(MB) | readers.gdal 对缓存设置很敏感 |
最后一条来自 readers.gdal 的官方提示:这个 reader 严重依赖 GDAL 的缓存设置,读大栅格时调 GDAL_CACHEMAX 往往比换机器有效。
3.9 常见故障对照
| 现象 | 原因 | 处理 |
|---|---|---|
cmake 报 Required at least GDAL version 3.8 |
系统 GDAL 太老 | 用 conda 装 GDAL,或从源码编译 |
Could NOT find PROJ (missing: PROJ_DIR) |
PROJ 9 未安装或未走 CONFIG 模式 | conda install proj,或设 -DPROJ_DIR= |
| CMake 阶段报 GeoTIFF 版本不足 | 文档说 1.3,源码要 1.7.0 | 升 GeoTIFF;或让 GDAL 带 external libgeotiff |
pdal: command not found |
环境未激活 / 安装前缀不在 PATH | conda activate 或把 bin 加进 PATH |
pdal --drivers 缺某个 stage |
编译时插件开关为 OFF | 重新 cmake 打开 BUILD_PLUGIN_* |
ImportError: libpdalcpp.so |
运行时找不到 PDAL 库 | 设 LD_LIBRARY_PATH,或改用 conda 安装 |
DLL load failed(Windows) |
pdalcpp.dll 不在 PATH |
把 PDAL bin 加入 PATH,或用 conda |
插件加载了但 pipeline 报 Couldn't create stage |
插件版本与主库 ABI 不匹配 | 用同一工具链、同一版本重新编译插件 |
坐标转换报 proj_create: no database context specified |
PROJ_DATA 未设置或指向错误目录 |
指向 <prefix>/share/proj |
最后一条在 Python 环境里出现得不少。conda 装的 PROJ 数据在 $CONDA_PREFIX/share/proj,如果从别的 shell 或系统服务里调用 Python,这个前缀可能没生效。PDAL 官方文档里的 Python 示例就直接预置了这一步:
import os, sys
conda_env_path = os.environ.get('CONDA_PREFIX', sys.prefix)
proj_data = os.path.join(conda_env_path, 'share', 'proj')
os.environ["PROJ_DATA"] = proj_data
3.10 生产建议
镜像/环境锁到 patch 版本。 pdal/pdal:2.10.0、conda install pdal=2.10.0,而不是 latest。记录 pdal --version 的完整输出(含 git sha)到部署清单。
优先 Docker 或 conda 环境,避免系统级散装安装。 PDAL 依赖 GDAL/PROJ/GeoTIFF 三个版本敏感的库,系统包管理器一升级就可能把整条链带崩。容器或独立 conda 环境是唯一能保证“半年后还能跑出同样结果”的方案。
把 pdal --options <stage> 的输出纳入测试基线。 升级 PDAL 后 diff 一下关键 stage 的选项表,比读 release note 更可靠地发现默认值变化。
内网环境提前备好依赖。 源码编译需要 GDAL/PROJ/GeoTIFF/curl/zlib/lzma 全套开发包;离线 conda 需要 conda pack 打包整个环境。别在目标机器上第一次尝试编译。
别在同一台机器上混装多套 PDAL。 系统包、conda、源码、Docker 各来一份时,pdal 指向哪一个取决于 PATH 顺序,插件搜索路径也可能串。用容器隔离,或者至少用绝对路径调用。
3.11 小结
| 主题 | 关键事实 |
|---|---|
| 版本基线 | PDAL 2.10.0;CMake ≥ 3.13、GDAL ≥ 3.8、PROJ ≥ 9.0、GeoTIFF ≥ 1.7.0 |
| 首选安装 | conda create -n pdal -c conda-forge pdal(Windows 官方推荐 64 位 conda) |
| 包区分 | pdal(命令行+开发文件)/ libpdal(库)/ python-pdal(Python 扩展) |
| Docker | pdal/pdal:latest 跟 master,pdal/pdal:<ver> 跟发布;必须 -v 挂载与 -w 指定工作目录 |
| Python | conda 最省心;pip 需要系统 PDAL,且要配 LD_LIBRARY_PATH |
| 插件 | BUILD_PLUGIN_* 默认 OFF,没开就没有对应 stage |
| 验证 | --version、--drivers、--list-commands、--options <stage>、info --summary |
| 路径变量 | PDAL_DRIVER_PATH、LD_LIBRARY_PATH、PROJ_DATA、GDAL_CACHEMAX |