简介:在Windows下借助Qt与MinGW工具链进行点云开发的C++工程师,常受困于PCL及其依赖库的编译配置与版本匹配问题。这份整合包直接提供PCL与boost、eigen、flann、qhull、VTK的MinGW编译成果,省去逐一下载源码、手动编译和排查兼容性错误的繁琐过程。资源共2000个文件,压缩包约151.31MB,其中以1997个hpp头文件为主,完整覆盖各库的声明与模板实现,另附txt、pdf、doc格式的说明文档,便于查阅配置要点与使用细节。目前已有34人学习下载,适合中高级点云开发者作为环境搭建参考。包内各依赖库分工明确:Eigen负责矩阵运算、FLANN提供近邻搜索、Qhull处理凸包与三角剖分、VTK完成三维可视化,结合PCL本身可快速构建从数据读取到可视化的完整点云处理流程,对理解库间协作与后续二次开发均有直接帮助。
1. 在 Windows 上让 Qt、MinGW 和 PCL 共存的现实解法
点云库里 PCL 的大多数 Windows 编译教程都默认你使用 Visual Studio 和 MSVC 编译器,这导致很多 Qt 开发者陷入一个尴尬境地:明明用 Qt 写界面,却为了编译 PCL 不得不跨到 msvc 工具链,最后在 QWidget 与 VTK 渲染窗口之间来回折腾。更麻烦的是,Qt 从 5.15 开始不再提供离线安装包,新用户只能通过在线安装器勾选 Qt 版本与编译器套件,想要凑齐一套能用的 Qt + MinGW 环境,本身就是第一步门槛。
本文要解决的是:如何用 Qt 自带的 MinGW 编译器,从 boost 开始一路手写编译 PCL 及其全链路依赖库。这条路线看起来绕远,但当你真正面对某些国产 OS 的适配、内网离线部署或者需要定制编译器选项时,手写编译会是你在 msvc 方案之外唯一的救命稻草。整个流程我会按依赖顺序讲,标注每个库的编译参数、CMake 选项和最容易出错的环节,能直接照着敲,也能让你明白每个参数的含义,下面是全文的编译路线图。
2. 编译链选型:MinGW 与 Qt 的版本匹配逻辑
2.1 为什么放弃 MSVC 转而使用 MinGW
MSVC 和 MinGW 的区别不止是编译器厂商不同,它影响的是链接器、运行库和调试信息格式。PCL 官方仓库对 Windows 的支持部分面向 MSVC,但 VTK 的 Qt 渲染模块对 MinGW 是友好的,前提是你的 Qt 版本是 MinGW 套件编译的,且 VTK 源码的 Qt 插件模块能识别到 qmake 的路径。另外,许多工业现场的上位机程序仍然依赖 Qt 5.15.x MinGW 版本,比如带触摸屏的工控机场景,项目批量部署后没法要求客户安装 VC++ Redistributable,此时 MinGW 自带的 libgcc、libstdc++ 共享库只需和 exe 放在同一目录即可运行。
选择 MinGW 还有一层考虑是编译产物的跨机器稳定性。MSVC 编译的 PCL 动态库默认依赖 /MD 运行库,如果部署机器缺少对应版本的 Universal CRT,运行时会直接报缺失 msvcp140.dll。而 MinGW 的二进制只要带上 libstdc++-6.dll 和 libgcc_s_seh-1.dll 即可。对于长时间在野外运行的点云采集设备,这一特性非常实际。
2.2 工具链版本组合建议
MinGW 编译器版本、Qt 版本和 CMake 版本三者的搭配直接决定后续编译能否顺利通过。根据社区常见实践经验,推荐下列组合:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| Qt | 5.15.2 MinGW 8.1.0 64-bit | 在线安装器可选,自带编译器套件 |
| MinGW | Qt 自带 8.1.0 SEH | 注意 Qt 安装目录下的 mingw81_64 文件夹 |
| CMake | 3.20 及以上 | 低于 3.16 不支持 PCL 的部分 target 语法 |
| PCL | 1.12.1 | 对 VTK 9 支持较完善,若用 VTK 8.2 则选 1.11 |
| VTK | 9.0.3 或 9.2.6 | 9.0.3 与 Qt 5.15 的兼容性最稳 |
提示:PCL 1.13 以上版本要求 CMake 3.17+,同时 Eigen 最小版本提到 3.3,编译时留意日志中的版本检查输出。
2.3 编译顺序与依赖关系梳理
PCL 的依赖库之间不是完全独立的,编译顺序错了会导致 CMake 找不到 find_package 的配置文件。推荐顺序为:eigen → boost → flann → qhull → VTK → PCL。eigen 是 header-only,只需把头文件拷贝到指定目录并设置环境变量;boost 编译时间最长,放到第一步编译可以让后续工作更轻松;VTK 最复杂,放在 PCL 之前最后一个编译,能保证 CMake 的缓存文件指向正确的 vtk 版本。在实际操作中,你可以使用-DCMAKE_PREFIX_PATH参数显式指定所有第三方库的安装前缀,避免 CMake 因为系统 PATH 中存在旧版本而误选,这是最常见的坑之一。
3. 逐步编译:从 boost 到 flann 的完整命令行方案
3.1 编译 boost:b2 参数详解
boost 不需要 CMake,它使用自己的 b2 构建系统。进入 boost 源码目录后,先执行 bootstrap.bat 生成 b2.exe,然后执行如下命令:
b2 toolset=gcc address-model=64 architecture=x86 --prefix=D:/dev/boost_install --build-dir=D:/dev/boost_build -j 8 --layout=system variant=release link=static runtime-link=static threading=multi install上面命令的每个参数都有明确作用:toolset=gcc告诉 boost 使用 MinGW 的 gcc 编译器,而不是系统默认的 MSVC;address-model=64与目标平台位数一致,如果这里设错了,后续链接 PCL 时会报architecture mismatch的错误。--layout=system代表生成不带版本号的库文件(例如 libboost_system.a),否则会生成 libboost_system-mgw81-mt-x64-1_75.a 这种长名字文件,会对 CMake 的 find_package 查找逻辑造成困扰。runtime-link=static表示链接器运行时采用静态方式,这在之后配合 PCL 编译时会简化 DLL 拷贝工作。
等待编译完成后,将D:/dev/boost_install加入系统环境变量或 CMake 的CMAKE_PREFIX_PATH。验证 boost 是否编译成功,可以执行以下命令:
ls D:/dev/boost_install/lib/libboost_system.a如果没有生成该文件,检查 boost 编译日志中的error: could not find a Boost installation字样,多半是--prefix路径写错或权限不足。需要提醒的是 boost 编译耗时较长,在 8 核机器上大约 20 分钟,期间不要打开其他高负载程序,避免编译中断导致部分目标文件损坏。
3.2 eigen:header-only 库的极简处理方式
eigen 是所有依赖里唯一不需要编译的库,它不需要生成 .a 或 .dll。从官方仓库下载源码后,整个unsupported和Eigen两个文件夹需要保留。推荐做法是将其解压后拷贝到D:/dev/eigen,然后设置 CMake 变量:
set(EIGEN_INCLUDE_DIR "D:/dev/eigen") set(EIGEN_INCLUDE_DIRS "D:/dev/eigen")之所以要显式规定,是因为 eigen 的版本检查依赖signature_of_eigen3_matrix_library文件,如果 CMake 在不同路径下找到了其他版本的 eigen,编译时会出现EIGEN_VERSION_MISMATCH的错误。另一个问题是,PCL 的pcl_common模块对 eigen 的版本有硬性检查,要求最低版本 3.2,推荐直接用最新稳定版 3.4。处理完这一步,可以写一个临时 CMakeLists.txt 调用find_package(Eigen3 REQUIRED)验证是否成功,过程中注意输出中EIGEN3_VERSION是否为期望值。
3.3 flann:编译时最容易被忽略的依赖细节
flann 的源码使用 CMake 构建系统,但它在 Windows 下有个特殊之处:无法直接将 MinGW 作为生成器使用,需要在 CMake 图形界面中指定生成器为MinGW Makefiles,同时把 C 和 C++ 编译器路径指向 Qt 的 MinGW bin 目录。如果不指定,CMake 默认会去查找微软的 cl.exe,导致生成失败。
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=D:/dev/qt/5.15.2/mingw81_64 -DBUILD_MATLAB_BINDINGS=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_CUDA_LIB=OFF -DCMAKE_INSTALL_PREFIX=D:/dev/flann_install .. mingw32-make -j 8 mingw32-make install参数-DBUILD_MATLAB_BINDINGS=OFF是必须的,因为 flann 的 MATLAB 绑定需要 VC++ 的 mex 编译器,MinGW 环境下即使设为 ON 也不会成功,只会拖慢速度。-DBUILD_CUDA_LIB=OFF同理,除非你的机器上有完整 CUDA 工具链。编译完成后,检查D:/dev/flann_install/lib/libflann.dll和libflann_s.a是否存在。静态库.a文件在后续链接 PCL 时会被优先选择,但如果你计划把 PCL 作为动态库使用,需要保留.dll文件。
3.4 qhull:容易被版本迷惑的数学库
qhull 是一个用于计算凸包的 C 库,PCL 的凸包模块和部分滤波算法依赖它。编译命令如下:
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=D:/dev/qhull_install -DQHULL_USE_MANUAL_PRECOMPILED_HEADERS=OFF .. mingw32-make -j 8 mingw32-make installqhull 的 CMake 配置中有个常见陷阱:它默认会生成一个qhull_r的动态库,同时也会生成静态库libqhullstatic_r.a,这两个库的存在会让 CMake 的 find_package 同时发现多个目标。建议在编译后删除不需要的静态库,或保留动态库即可,因为 PCL 编译时会通过QHULL_LIBRARY变量查找。如果后面 PCL 配置出现Could NOT find Qhull的错误,检查 qhull 安装目录下是否存在qhull/libqhull_r/pch目录,如果存在但 CMake 仍找不到,手动指定-DQHULL_INCLUDE_DIR和-DQHULL_LIBRARY两个变量。
4. VTK 编译:与 Qt 集成的核心矛盾点
4.1 VTK 9 还是 VTK 8.2:如何决策
VTK 的选择直接影响 PCL 的渲染模块能不能正常用。VTK 8.2 对 Qt4 的支持较为完备,但使用 Qt5 时会有部分宏冲突;VTK 9 系列则全面转向 Qt5/Qt6 的适配,模块化体系更清晰。结合 Qt 5.15 的现状,推荐选择 VTK 9.0.3。它的 CMake 参数相对稳定,且 PCL 1.12 版本能直接识别 VTK 9 的组件名称。如果选择更高版本如 9.2.6,在编译 PCL 时可能遇到vtkAVIWriter等模块被移除而导致的 CMake 报错。
VTK 编译的关键在于打开 Qt 相关的模块,同时关闭测试和示例以节省时间。命令行参考如下:
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=D:/dev/qt/5.15.2/mingw81_64 -DVTK_GROUP_ENABLE_Qt=YES -DVTK_QT_VERSION=5 -DQT_QMAKE_EXECUTABLE=D:/dev/qt/5.15.2/mingw81_64/bin/qmake.exe -DVTK_GROUP_ENABLE_Rendering=YES -DVTK_GROUP_ENABLE_Imaging=YES -DVTK_GROUP_ENABLE_Views=YES -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=D:/dev/vtk_install ..-DQT_QMAKE_EXECUTABLE这行参数特别关键,它告诉 VTK 的编译脚本直接使用 Qt 自带的 qmake,避免从 PATH 中寻找其他版本,这是很多教程都没写清楚的地方。-DVTK_GROUP_ENABLE_Qt=YES则显式激活 VTK 的两个 Qt 相关模块 QVTKWidgetPlugin 和 QVTKOpenGLNativeWidget,这两个模块是后续在 QWidget 中嵌入 PCL 可视化窗体的底层依赖。编译涉及模块较多,建议先直接编译全部目标再等待错误,VTK 9.0.3 使用 MinGW 在 8 核处理器上编译时间约 30 分钟。
mingw32-make -j 8 mingw32-make install4.2 Qt 版本与 VTK 的命名空间冲突
编译 VTK 过程中最容易出现的问题是QVTKWidget与 Qt 自身的QWidget在继承关系上的冲突,表现为报错含有error: undefined reference to vtkGUISupportQt::vtkEventQtSlotConnect::connect。此问题的出现通常是因为 VTK 在编译时没有找到 Qt 的 moc 工具,或者 VTK_QT_VERSION 参数与 qmake 的实际版本不一致。
解决该问题的正确手段是:先确认 CMake 缓存中存在Qt5Core_DIR等变量,并指向 Qt 安装目录的lib/cmake/Qt5Core路径。若不存在,则再次调用 cmake 命令追加-DQt5_DIR=D:/dev/qt/5.15.2/mingw81_64/lib/cmake/Qt5,然后mingw32-make clean后重新编译。另一个常见现象是error: cannot find -lQt5::Core,这主要是因为 Qt 的 CMake 导出文件里的库名格式与 MinGW 的生成器不匹配,将CMAKE_PREFIX_PATH同时加入 Qt 和 VTK 安装目录可解决。
4.3 编译 VTK 时的表格化资源清单
| 模块组 | 启用选项 | 用途 | 是否必须 |
|---|---|---|---|
| Qt 支持 | VTK_GROUP_ENABLE_Qt=YES | QVTKOpenGLNativeWidget 嵌入 | 必须 |
| 渲染 | VTK_GROUP_ENABLE_Rendering=YES | 点云三维渲染 | 必须 |
| 成像 | VTK_GROUP_ENABLE_Imaging=YES | 深度图转换与滤波 | 视需求 |
| 视图 | VTK_GROUP_ENABLE_Views=YES | 多视图交互 | 推荐 |
| 测试 | BUILD_TESTING=OFF | 跳过编译测试程序 | 必须关闭 |
| 示例 | BUILD_EXAMPLES=OFF | 跳过编译示例 | 必须关闭 |
VTK 编译成功后,并且你需要把D:/dev/vtk_install/lib下所有 dll 文件拷贝到 Qt 的mingw81_64/bin目录下,或者添加到 PATH 环境变量的最前面。这一步若不执行,后续运行任何依赖 VTK 的程序都会提示找不到vtkCommonCore-9.0.dll。我一般会额外建立一个D:/dev/all_dll目录,把所有第三方库的 dll 统一放到其中,配合 Qt 的windeployqt工具一起使用,便于维护部署包。
5. 编译 PCL 主工程:CMake 参数全局编排
5.1 一层 CMake 命令打通所有依赖
PCL 的主源码体积大,且 CMake 选项极多,但 Windows 下真正需要手动指定的只有依赖库路径与少数模块开关。以下命令可以在 MinGW 环境下一次性配置完成:
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="D:/dev/boost_install;D:/dev/eigen;D:/dev/flann_install;D:/dev/qhull_install;D:/dev/vtk_install;D:/dev/qt/5.15.2/mingw81_64" -DWITH_VTK=ON -DWITH_QT=ON -DWITH_OPENMP=ON -DWITH_PCAP=OFF -DWITH_PNG=OFF -DWITH_LAS=OFF -DBUILD_apps=OFF -DBUILD_examples=OFF -DCMAKE_INSTALL_PREFIX=D:/dev/pcl_install ..WITH_QT的开关在部分新闻版本中会被忽略,因为 PCL 对 Qt 的依赖是通过 VTK 间接引入的,但你显式加上没有坏处。WITH_PCAP、WITH_PNG和WITH_LAS若非实际需要,尽量设为 OFF,否则 CMake 会尝试查找 libpcap、libpng、LASlib 等额外依赖,增加不确定性。BUILD_apps=OFF跳过 PCL 自带的工具集编译,可以在首次编译时节省 10 分钟以上。
5.2 处理 CMake 找不到库的问题
PCL 的 CMake 脚本通过find_package(Boost)、find_package(FLANN)、find_package(Qhull)等宏来搜索依赖。这些宏不会去系统 PATH 找,只会在CMAKE_PREFIX_PATH指定的目录中搜索。因此每次编译失败,先检查你的CMAKE_PREFIX_PATH是否包含所有依赖的安装根目录,且目录结构是否为<root>/include、<root>/lib的标准布局。如果某个库安装在非标准位置,可以单独加一个-DXXX_DIR变量:
-DBOOST_ROOT=D:/dev/boost_install -DFLANN_ROOT=D:/dev/flann_install -DQHULL_ROOT=D:/dev/qhull_install编译 PCL 时也可能遇到Could NOT find Qt5的报错,这与你前面 VTK 编译时是否成功找到 Qt 无直接关系,必须在 PCL 的 CMake 命令中再次显式指定如下环境变量:
set Qt5_DIR=D:/dev/qt/5.15.2/mingw81_64/lib/cmake/Qt55.3 编译完成后验证全部依赖的 QT 集成情况
生成后的安装物包括PCLConfig.cmake和PCLConfigVersion.cmake,它们存放在D:/dev/pcl_install/share/pcl-1.12目录下。为了确保安装没有问题,在编译自己的 Qt 工程前,先执行以下命令行验证库可被正常链接:
cmake --find-package -DNAME=PCL -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST如果输出-- Found PCL则说明 CMake 认知正常。接着创建一个测试目录,里面写一个 5 行的 CMakeLists.txt:
cmake_minimum_required(VERSION 3.10) project(pcl_test) find_package(PCL REQUIRED COMPONENTS common io) include_directories(${PCL_INCLUDE_DIRS}) add_executable(${PROJECT_NAME} main.cpp) target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES})在main.cpp中调用任意一个 PCL API 头文件并构建链接,若链接过程没有缺少符号,说明所有静态库和 DLL 依赖已经闭合。这一步会暴露 boost 的 layout 问题,如果你发现libboost_system-mgw81-mt-x64-1_75.a这种文件名出现,说明 boost 编译时 layout 参数未生效,返回去用--layout=system重编 boost 就很明确了。
5.4 使用 Qt 工程调用 PCL 的 CMake 最低模板
将 PCL 集成到 Qt 的 QWidget 工程中,需要让 CMake 同时找到 Qt 和 PCL。模板文件如下:
cmake_minimum_required(VERSION 3.20) project(pointcloud_viewer) set(CMAKE_CXX_STANDARD 14) set(CMAKE_AUTOMOC ON) find_package(Qt5 REQUIRED COMPONENTS Widgets) find_package(PCL REQUIRED COMPONENTS common io visualization) add_executable(${PROJECT_NAME} main.cpp viewer.cpp) target_link_libraries(${PROJECT_NAME} Qt5::Widgets ${PCL_LIBRARIES})其中CMAKE_AUTOMOC ON会让 CMake 自动处理 Qt 的 Q_OBJECT 宏,无需手动运行 moc。如果可视化模块无法编译,如找不到vtkAutoInit.h,在find_package(PCL ...)前添加一行include_directories(D:/dev/vtk_install/include/vtk-9.0),同时检查你的 VTK 库文件名是否包含vtkGUISupportQt-9.0模块。PCL 的 visualization 组件编译时,CMake 会自动通过 VTK 的 target 处理宏定义,不需要再手动添加VTK_USE_QVTK之类的定义,但前提是 VTK 编译时开启了 Qt 组模块,否则这里会链接失败。
6. 部署时一次拿全的 DLL 清单与运行时排错技巧
6.1 用 windeployqt 配合第三方路径完成收集
编译好的点云程序在部署机器上需要 Qt 运行库和 PCL/VTK 的第三方 DLL,windeployqt 只能收集 Qt 自身的依赖,不会处理 PCL 的。常见做法是先执行 windeployqt 收集 Qt 相关文件:
D:/dev/qt/5.15.2/mingw81_64/bin/windeployqt.exe --release --no-translations --no-system-d3d-compiler --no-opengl-sw D:/build/pointcloud_viewer.exe执行完后,在 exe 目录中会出现 Qt5Core.dll、Qt5Widgets.dll、platforms/qwindows.dll 等必要文件。之后再从D:/dev/vtk_install/bin和D:/dev/pcl_install/bin手动拷贝带lib前缀的 DLL 到同一目录。
| DLL 名称 | 来源库 | 是否必选 |
|---|---|---|
| libboost_system.dll | boost | 必须 |
| libpcl_common.dll | PCL | 必须 |
| libpcl_io.dll | PCL | 必须 |
| libflann.dll | flann | 必须 |
| libqhull_r.dll | qhull | 推荐 |
| vtkCommonCore-9.0.dll | VTK | 必须 |
| vtkRenderingQt-9.0.dll | VTK | 必须 |
| libgcc_s_seh-1.dll | MinGW | 必须 |
拷贝时建议使用下述命令逐一确认依赖,比肉眼扫描更可靠:
D:/dev/mingw/bin/objdump.exe -p D:/build/pointcloud_viewer.exe | grep "DLL Name"该命令会列出可执行文件所有依赖的 DLL 名称,然后逐个核对是否存在于 exe 同级目录。其中容易被忽略的是libstdc++-6.dll,它是 MinGW 特有的 C++ 标准库实现,若缺失程序启动时不会给出中文提示,只会静默退出。
6.2 运行时崩溃的快速定位手段
程序启动后如果窗口无法显示,多半是 Qt 平台插件路径错误,报错信息形如This application failed to start because no Qt platform plugin could be initialized。这是因为 QWidget 程序找不到platforms目录,请检查 windeployqt 是否生成了对应文件夹。若生成但仍报错,将平台插件目录完整拷贝到部署目录后再测试一次。
另一类高频问题是 PCL 的visualization模块打开一个空窗口后便闪退,常见原因与 VTK 的 OpenGL 渲染有关。先运行 Windows 自带的dxdiag确认 GPU 驱动支持 OpenGL 3.2 以上,如果使用虚拟机则修改 VTK 渲染设备为软件渲染,在代码中增加:
vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(0);6.3 二次复用第三方目录的维护技巧
整个编译流程完成后,我把D:/dev下所有安装目录统一维护为一个目录树,三级结构为include、lib与bin。下次新开 Qt 工程时,只需要在系统环境变量中加入CMAKE_PREFIX_PATH,CMake 的 find_package 就能一次性找到所有依赖,不需要为每个工程手动指定-D参数。这一步看似简单,但在多个工程、多分支开发时能省下大量时间,每次升级依赖库版本时也可以直接从 dev 目录替换lib文件后再重编译,不会影响已存在的工程配置。
本文还有配套的精品资源,点击获取