简介:面向Qt与MinGW环境下进行三维点云开发的工程师,这套资源将PCL及Boost、Eigen、FLANN、Qhull、VTK等依赖库的头文件统一打包,解决手工编译依赖链复杂、版本匹配难的问题,使开发者能直接在Qt Creator中完成点云读取、预处理、特征提取、表面重建及可视化等工作。压缩包共2000个文件,其中hpp头文件多达1997个,覆盖了各库的核心模板与数据结构,另附1份pdf编译指南、1份txt环境配置要点和1份doc使用说明,整体大小约152.73MB,目录围绕库模块划分,便于按需检索。已有1585人浏览学习,适合有C++基础、希望快速搭建PCL开发环境的开发者。包内不仅包含如Eigen这类纯头文件库,也提供了Boost、VTK等重型库的完整头文件与相关文档,配合说明可理解MinGW工具链下各依赖库的调用方式与常见陷阱,省去逐一编译的等待,让Qt项目直接链接使用,从而更专注于点云算法与应用功能本身。
1. 为什么放着现成的PCL不用,非要在MinGW下自己编
1.1 先说清楚:MSVC和MinGW的C++ ABI不兼容
点云处理这块,Qt + MinGW 在 Windows 桌面开发里算是一个很常见的组合:你想在 Qt 里做三维点云可视化,自然会想到 PCL,可 PCL 官方 Windows 包基本都是给 Visual Studio 的 MSVC 编译器准备的。每次在 Qt Creator 里一链接,报错信息五花八门,什么“未定义的引用”“无法解析的外部符号”,折腾半天,核心原因就一句话:MSVC 编译出来的二进制文件,跟 MinGW(GCC)编译出来的代码不是一套 ABI。
ABI 是什么?你可以把它理解成编译器和运行时库之间的一份“内部合同”。C++ 里类的内存布局、虚函数表、符号命名规则、标准库对象在参数传递时的构造和析构方式,这些都受 ABI 影响。MinGW 用的是 GCC 的 libstdc++,MSVC 用的是微软的 STL,两套实现从符号修饰规则到std::string内存布局都不一样。最直接的结果就是:你用 Qt 的 MinGW 套件编出来的 exe,去链接 PCL 官方提供的.lib和 DLL,编译器根本不认识对方导出的符号。
有人会问,那我不用官方包,直接拿源码,在同一台机器上用 MSVC 编一套 PCL,再给 MinGW 用行不行?答案还是不行。只要 C++ 类在库边界上暴露,ABI 不兼容就会随时爆发,哪怕运气好过了链接,运行起来也可能在函数返回、容器析构的时候悄悄崩溃。所以,只要想走 Qt + MinGW 这条路,就必须把 PCL 和它所有带编译产物的依赖库,全都用 MinGW 从源码编一遍。
1.2 这套方案到底要编什么,值不值得
PCL 不是一个单独的库,它的依赖链条比较长。Boost 提供智能指针和线程等基础能力,Eigen 负责矩阵和向量运算,FLANN 做快速最近邻搜索,Qhull 做凸包计算,VTK 则负责可视化窗口和交互。其中 Eigen 是纯头文件库,不需要编译,剩下几个都是要动 CMake 或者运行配置脚本、然后拿到 DLL 和头文件的。
从工作量来看,这套编译流程肯定不轻松,Boost 要跑 bootstrap,VTK 全量编译在普通笔记本上可能要几个小时。但好处是,一旦编完,后面写点云相关的 Qt 程序就会非常顺,不受 Visual Studio 和 Qt 版本绑定的限制。我自己的经验是,如果项目里明确要求用 Qt Creator + MinGW 工具链,那与其到处找别人编好的 MinGW 版依赖,不如按顺序从头编一次,至少你知道每个库是从什么版本、什么选项出来的,后期出问题也更好排查。
2. 编译前准备:版本选对了,后面能少踩 80% 的坑
2.1 一个经过验证的版本组合
在开始之前,先把版本定下来非常关键。很多编译失败不是因为操作不对,而是 Qt、CMake、GCC、依赖库之间版本跨度太大。下面这组是我在 Windows 10 64 位系统上实际跑通的组合,供你参考:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| Qt | 5.15.2 MinGW 8.1.0 64-bit | Qt 官方在线安装包里自带的 MinGW 工具链 |
| CMake | 3.20 以上 | 尽量用较新的稳定版 |
| Boost | 1.72.0 | PCL 1.11 系列兼容性比较稳定 |
| Eigen | 3.3.9 | 也可以换 3.4,但 3.3.9 更保守 |
| FLANN | 1.9.1 | PCL 官方验证过的版本 |
| Qhull | 7.3.2 | 直接编译默认库即可 |
| VTK | 8.2.0 | 配 Qt 5 很成熟,PCL 1.11 也认 |
| PCL | 1.11.1 | 整个依赖链条的最终目标 |
这里要特别说明一下,PCL 1.12 以上对 VTK 9 的支持才开始变好,但 VTK 9 对 Qt 5 的接口改动比较大,如果你不是必须用新功能,用 PCL 1.11.1 + VTK 8.2.0 这套老组合最省心。Qt 版本没有特别选新,是因为 Qt 6 的点云生态支持还不算全,很多老库的 CMake 脚本对 Qt6 的适配并不好,所以 Qt 5.15.2 仍然是搭配 PCL 最安全的选项。
2.2 每个依赖库到底是干什么的
这部分帮新手把依赖理一遍,避免后面看到 CMake 报错不知道在说什么。
Boost 是 PCL 很多基础能力的来源,比如boost::shared_ptr在 PCL 里被大量使用,还有用来做线程安全的 mutex 等。PCL 会用 CMake 的find_package(Boost)来找它,所以 Boost 编译完以后要把 include 和 lib 的路径配置清楚。Eigen 虽然叫库,但主要是头文件,下载后解压,把Eigen目录拷到你的 include 搜索路径就行,CMake 能找到Eigen3Config.cmake即可。
FLANN 是点云的最近邻搜索实现,PCL 的 kdtree 就建立在它上面。Qhull 是计算几何库,PCL 的凸包、Delaunay 三角化等功能依赖它。VTK 则承担了 PCL visualizer 的底层渲染,没有 VTK,PCL 里的点云可视化窗口基本就用不了。
2.3 目录规划和环境变量:别把东西装散了
编译多个库以后,最怕的就是头文件和库文件散落各处。我的建议是建一个统一的目录,比如D:/Libs,下面分别放源码和安装文件。
D:/Libs source/ boost_1_72_0/ eigen-3.3.9/ flann-1.9.1/ qhull-7.3.2/ VTK-8.2.0/ pcl-pcl-1.11.1/ install/ boost/ eigen/ flann/ qhull/ VTK/ PCL/先安装好 Qt,记住 Qt 安装目录里 MinGW 的位置,比如C:/Qt/Tools/mingw810_64,以及对应 WebKit 套件的 bin 目录,比如C:/Qt/5.15.2/mingw81_64/bin。最好是直接使用 Qt 安装目录下提供的命令行快捷方式,名字类似“Qt 5.15.2 (MinGW 8.1.0 64-bit)”,它已经把 PATH 设置好了,打开后直接在里面执行 CMake 命令,可以省掉很多环境变量问题。
3. 逐个编译依赖库:从 Boost 到 VTK 的实操记录
3.1 Boost 编译:bootstrap 和 b2 的关键参数
Boost 编译其实不复杂,但参数一定要给对。先进入 Boost 源码目录,打开 Qt 命令行,执行:
bootstrap.bat gcc这一步会生成b2.exe和bjam.exe。然后执行编译安装:
b2.exe toolset=gcc address-model=64 link=shared threading=multi --build-type=complete --prefix=D:/Libs/install/boost install这里有三个关键点。第一,toolset=gcc是让 Boost 使用 MinGW 的 GCC 工具链,如果漏了这步,它可能默认去找 MSVC。第二,address-model=64确保生成 64 位库,否则会用默认的 32 位,后面链接的时候会出现“尝试加载 32 位库”的鬼问题。第三,--build-type=complete会把 debug/release、共享/静态都编一遍,好处是保险,缺点是慢;如果你确定只用 release 动态库,可以去掉--build-type=complete换成variant=release,速度会快很多。
Boost 编译时间大概十几分钟到半小时不等,编完以后,D:/Libs/install/boost下应该有include和lib两个目录。后面 CMake 找 Boost 时,默认就是通过BOOST_ROOT或CMAKE_PREFIX_PATH去搜这个位置。
3.2 Eigen 编译:其实是复制大法
Eigen 是我最喜欢编的库,因为它没有二进制产出,核心就是头文件。进入 Eigen 源码目录后:
cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=D:/Libs/install/eigen .. mingw32-make install这一步会执行安装规则,把signature_of_eigen3_matrix_library、Eigen等目录拷贝到安装路径里。你也可以直接手工复制Eigen、unsupported两个文件夹到 include 目录,效果一样。需要注意,CMake 在找 Eigen 的时候,通常是找eigen3/Eigen/Core或者Eigen/Core,安装前缀路径要保证解压后的目录层级正确。我个人更习惯用 CMake 安装,让它的配置脚本Eigen3Config.cmake也一起装好,后面 PCL 的find_package(Eigen3)就不容易出错。
3.3 FLANN 和 Qhull:用 CMake 快速编掉
FLANN 编译的前提是 Boost 已经装好。进入 FLANN 源码目录后,用 CMake 配置:
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="D:/Libs/install/boost;D:/Libs/install/eigen" -DBOOST_ROOT="D:/Libs/install/boost" -DBUILD_C_BINDINGS=OFF -DBUILD_MATLAB_BINDINGS=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_CUDA_LIB=OFF -DCMAKE_INSTALL_PREFIX="D:/Libs/install/flann" .. mingw32-make -j4 mingw32-make install这里把 C、MATLAB、Python、CUDA 的相关选项全部关掉,是因为 PCL 只需要 C++ 核心库,编这些额外绑定只会浪费时间。FLANN 的编译比较轻量,通常一两分钟就能完成。Qhull 更简单:
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="D:/Libs/install/qhull" -DINCLUDE_SHARED=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. mingw32-make -j4 mingw32-make installCMAKE_POSITION_INDEPENDENT_CODE选项值得注意,很多第三方库在编译时如果没有用 PIC,后续链接到 PCL 或 VTK 这种大型动态库时可能会报地址重定位相关的错误,提前打开能省不少事。
3.4 VTK 编译:全流程里最硬的一块骨头
VTK 是依赖链里体量最大、编译时间最长的库,但同时也是 PCL visualization 的刚需。进入 VTK 源码目录,执行:
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="D:/Libs/install/boost;D:/Libs/install/qhull;C:/Qt/5.15.2/mingw81_64" -DCMAKE_INSTALL_PREFIX="D:/Libs/install/VTK" -DVTK_QT_VERSION=5 -DVTK_GROUP_ENABLE_Qt=WANT -DModule_vtkGUISupportQt=ON -DModule_vtkGUISupportQtOpenGL=ON -DModule_vtkRenderingQt=ON -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=ON .. mingw32-make -j4这里我解释几个选项。VTK_QT_VERSION=5告诉 VTK 去匹配 Qt5 的 CMake 模块。VTK_GROUP_ENABLE_Qt=WANT会比较克制地启用 Qt 相关模块,避免把所有 Qt 模块都编进来。Module_vtkGUISupportQt和Module_vtkGUISupportQtOpenGL是 PCL 可视化窗口必须的,否则后面 PCL 的 visualizer 会找不到 VTK 的 Qt 窗口组件。BUILD_TESTING=OFF、BUILD_EXAMPLES=OFF一定要关,不然编译时间还要翻倍。
VTK 编译时是大型项目,-j4是相对稳妥的并行度;如果你的机器内存小于 16GB,建议用-j2,不要盲目加高并发,否则链接阶段很容易内存爆掉。编译成功后,再执行mingw32-make install,把产出的 DLL、lib、CMake 配置装到统一前缀目录。装好后D:/Libs/install/VTK/lib/cmake/vtk-8.2下会有VTKConfig.cmake,后面 PCL 的 CMake 就是靠它找到 VTK 的。
4. 重头戏:PCL 本体编译与 Qt 项目整合
4.1 PCL 编译的 CMake 配置
PCL 源码解压后,打开 Qt 命令行,进入源码目录,用 CMake 配置。为了减少干扰,建议关闭不需要的模块,只保留自己要用的功能:
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="D:/Libs/install/boost;D:/Libs/install/eigen;D:/Libs/install/flann;D:/Libs/install/qhull;D:/Libs/install/VTK;C:/Qt/5.15.2/mingw81_64" -DCMAKE_INSTALL_PREFIX="D:/Libs/install/PCL" -DBUILD_visualization=ON -DBUILD_tools=ON -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_GPU=OFF -DWITH_QT=ON -DWITH_VTK=ON -DWITH_OPENGL=ON ..如果前面几个依赖都装到了统一前缀,CMAKE_PREFIX_PATH里把每个安装目录都列上,PCL 的find_package就能依次找到所有依赖。也可以多开一个cmake-gui看变量,重点确认VTK_DIR、BOOST_ROOT、FLANN_INCLUDE_DIR等路径是不是都已经识别到了,没识别到的红色变量先解决再继续。
在配置输出里,尤其是看Found VTK,Found FLANN,Found Qhull这些行,确认都是 Yes。如果某个库没找到,不要硬着头皮往下编,回去查路径和版本。这是最容易出问题的地方,多数编译失败其实都是在这里埋下的。
4.2 编译安装与最小可运行测试
PCL 的编译同样很耗时,建议mingw32-make -j4,然后mingw32-make install。编完以后,PCL 的 CMake 配置文件会在D:/Libs/install/PCL/share/pcl-1.11下,这个路径将来在你自己的工程里就是PCL_DIR。
接着写一个最小测试程序,确认编译结果可用。先建工程目录,写一个 CMakeLists:
cmake_minimum_required(VERSION 3.16) project(TestPCL) set(CMAKE_PREFIX_PATH "D:/Libs/install/boost;D:/Libs/install/eigen;D:/Libs/install/flann;D:/Libs/install/qhull;D:/Libs/install/VTK;D:/Libs/install/PCL;C:/Qt/5.15.2/mingw81_64") find_package(PCL 1.11 REQUIRED COMPONENTS common io visualization) add_executable(TestPCL main.cpp) target_link_libraries(TestPCL ${PCL_LIBRARIES}) target_include_directories(TestPCL PRIVATE ${PCL_INCLUDE_DIRS}) add_definitions(${PCL_DEFINITIONS})main.cpp 里可以简单地生成一个随机点云:
#include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pcl/io/pcd_io.h> #include <pcl/visualization/pcl_visualizer.h> #include <iostream> int main() { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>()); cloud->width = 100; cloud->height = 1; cloud->resize(cloud->width * cloud->height); for (auto& pt : cloud->points) { pt.x = rand() % 1000 / 100.0f; pt.y = rand() % 1000 / 100.0f; pt.z = rand() % 1000 / 100.0f; } pcl::io::savePCDFileASCII("test.pcd", *cloud); std::cout << "saved" << std::endl; pcl::visualization::PCLVisualizer viewer("test"); viewer.addPointCloud(cloud, "cloud"); while (!viewer.wasStopped()) { viewer.spinOnce(); } return 0; }在 Qt Creator 里新建 CMake 工程,选择 MinGW 64-bit 套件,把这份 CMakeLists 和 main.cpp 放进去,配置CMAKE_PREFIX_PATH后构建。能编译、能弹出一个绿色点云窗口,说明这一整套 MinGW 版 PCL 已经可以正常工作了。
4.3 部署运行:DLL 拷贝和 windeployqt
好不容易编译成功,结果把 exe 拷到别的机器或者另一个干净目录,双击运行却提示缺 DLL,或者直接报No Qt platform plugin could be initialized,这个问题很常见。原因是 Qt 是动态库架构,exe 运行时要在一堆路径里找 Qt 的 DLL 以及platforms目录下的平台插件。
在 release 版本目录下打开 Qt 命令行,执行:
windeployqt TestPCL.exe它会自动把 Qt 的 DLL、翻译文件、平台插件复制到 exe 旁边。这一步做完还不够,还要把 PCL 和依赖库的 DLL 也拷过来,比如pcl_common.dll、pcl_io.dll、pcl_visualization.dll,以及 VTK 的vtkCommonCore-8.2.dll等一堆 DLL,还有 Boost、FLANN、Qhull 的 DLL。拷的时候有一个原则:千万不要把不同版本的库混在一起,最干净的做法是直接把D:/Libs/install下对应 lib/bin 目录里的 DLL 统一复制到 exe 目录,然后再用依赖查看工具确认。
5. 编译和运行中最常见的坑,以及我的排查思路
5.1 CMake 工具链选错,GCC 编译器识别失败
如果你在普通 CMD 里直接执行 CMake,它很可能会找到 Visual Studio 的编译环境,然后配置失败,或者中途切到 MSVC。解决办法很简单:不要用普通 CMD,而是用 Qt 安装菜单里自带的那个带 MinGW 的快捷方式,或者在配置时手动指定:
cmake -G "MinGW Makefiles" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ ..如果 CMake 提示gcc不是内部命令,先确认C:/Qt/Tools/mingw810_64/bin已经加入 PATH。我建议所有编译操作都固定用同一个命令行窗口,不要中途关掉环境,否则后面排查路径问题会很烦。
5.2 链接时一堆未定义引用,往往是 debug/release 混用
PCL 官方模板里经常会通过PCL_LIBRARIES返回一系列库名,按理说只要find_package(PCL)成功,链接顺序就会自动处理好。如果你在最终链接时看到一大串“未定义的引用”,先检查 CMAKE_BUILD_TYPE。MinGW 下 debug 和 release 的库命名会有区别,Boost 默认生成的 debug 库名后缀是-d,如果你用 debug 模式去链接 release 库,就可能找不到符号。最简单的做法是全程只编 release,PCL 的 EXE 也用 release 模式去构建。等整套跑通了,再去抠 debug 配置,否则调试期会非常痛苦。
5.3 编译 VTK 时内存不足或卡死
VTK 是重资源项目,常有人抱怨编到一半编译进程被杀掉。这通常不是代码问题,而是并行度太高。MinGW 的链接器在生成 VTK 的大型 DLL 时,内存峰值可能达到好几个 GB。如果你的机器只有 8GB 内存,-j8基本必挂,老老实实-j2。还有一点,不要把 VTK 的 build 目录放在机械硬盘上,有条件就放 SSD,否则光是读写源码和中间文件就能拖慢好几倍。
5.4 运行弹窗缺少 Qt 平台插件
这个错误信息很典型:This application failed to start because no Qt platform plugin could be initialized。它通常是三层原因:第一,exe 旁边没有platforms/qwindows.dll;第二,Qt 的 bin 目录不在 PATH;第三,系统里同时存在多个 Qt 版本,exe 加载了错误版本的qt5core.dll。第一次遇到时,先用windeployqt处理,再检查环境变量,最后用 Process Explorer 之类的工具看程序实际加载了哪些 DLL。很多时候就是 exe 不小心加载到了系统 PATH 里的另一个 Qt 版本,尤其是 Anaconda、第三方软件改过 PATH 的机器,特别容易踩这个雷。
6. 一点个人经验,提前给你打预防针
这套编译流程,我前后在好几台机器上跑过,每次版本组合不一样,踩的坑也略不一样。最深的感受是:临时抱佛脚去网上找“别人编好的 MinGW 版 PCL 包”看起来省事,但运气成分很大,版本对不上、模块缺失、路径混乱的问题接踵而至。真正用源码按 Boost、Eigen、FLANN、Qhull、VTK、PCL 的顺序完整编下来,整个过程虽然长,但每一步都可控,后续写业务代码时,心里是对底层库有底的。
如果你从来没有自己编过这么多 C++ 库,我的建议是第一次不要追求最优配置,就用我上面这组版本组合,照着顺序来,关闭不必要的模块,Release 模式一把梭。等顺利跑出第一个 PCL 可视化窗口,再回头去调整模块开关、尝试更新版本,那时候你已经知道该去哪里查问题,也就不会觉得这些库难伺候了。
本文还有配套的精品资源,点击获取