ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Qt MinGW环境下从源码编译PCL:从Boost到VTK全流程指南

Qt MinGW环境下从源码编译PCL:从Boost到VTK全流程指南 简介面向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 编译出来的二进制文件跟 MinGWGCC编译出来的代码不是一套 ABI。ABI 是什么你可以把它理解成编译器和运行时库之间的一份“内部合同”。C 里类的内存布局、虚函数表、符号命名规则、标准库对象在参数传递时的构造和析构方式这些都受 ABI 影响。MinGW 用的是 GCC 的 libstdcMSVC 用的是微软的 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 要跑 bootstrapVTK 全量编译在普通笔记本上可能要几个小时。但好处是一旦编完后面写点云相关的 Qt 程序就会非常顺不受 Visual Studio 和 Qt 版本绑定的限制。我自己的经验是如果项目里明确要求用 Qt Creator MinGW 工具链那与其到处找别人编好的 MinGW 版依赖不如按顺序从头编一次至少你知道每个库是从什么版本、什么选项出来的后期出问题也更好排查。2. 编译前准备版本选对了后面能少踩 80% 的坑2.1 一个经过验证的版本组合在开始之前先把版本定下来非常关键。很多编译失败不是因为操作不对而是 Qt、CMake、GCC、依赖库之间版本跨度太大。下面这组是我在 Windows 10 64 位系统上实际跑通的组合供你参考组件推荐版本说明Qt5.15.2 MinGW 8.1.0 64-bitQt 官方在线安装包里自带的 MinGW 工具链CMake3.20 以上尽量用较新的稳定版Boost1.72.0PCL 1.11 系列兼容性比较稳定Eigen3.3.9也可以换 3.4但 3.3.9 更保守FLANN1.9.1PCL 官方验证过的版本Qhull7.3.2直接编译默认库即可VTK8.2.0配 Qt 5 很成熟PCL 1.11 也认PCL1.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 的底层渲染没有 VTKPCL 里的点云可视化窗口基本就用不了。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 toolsetgcc address-model64 linkshared threadingmulti --build-typecomplete --prefixD:/Libs/install/boost install这里有三个关键点。第一toolsetgcc是让 Boost 使用 MinGW 的 GCC 工具链如果漏了这步它可能默认去找 MSVC。第二address-model64确保生成 64 位库否则会用默认的 32 位后面链接的时候会出现“尝试加载 32 位库”的鬼问题。第三--build-typecomplete会把 debug/release、共享/静态都编一遍好处是保险缺点是慢如果你确定只用 release 动态库可以去掉--build-typecomplete换成variantrelease速度会快很多。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_PREFIXD:/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_TYPERelease -DCMAKE_PREFIX_PATHD:/Libs/install/boost;D:/Libs/install/eigen -DBOOST_ROOTD:/Libs/install/boost -DBUILD_C_BINDINGSOFF -DBUILD_MATLAB_BINDINGSOFF -DBUILD_PYTHON_BINDINGSOFF -DBUILD_CUDA_LIBOFF -DCMAKE_INSTALL_PREFIXD:/Libs/install/flann .. mingw32-make -j4 mingw32-make install这里把 C、MATLAB、Python、CUDA 的相关选项全部关掉是因为 PCL 只需要 C 核心库编这些额外绑定只会浪费时间。FLANN 的编译比较轻量通常一两分钟就能完成。Qhull 更简单cmake -G MinGW Makefiles -DCMAKE_BUILD_TYPERelease -DCMAKE_INSTALL_PREFIXD:/Libs/install/qhull -DINCLUDE_SHAREDON -DCMAKE_POSITION_INDEPENDENT_CODEON .. 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_TYPERelease -DCMAKE_PREFIX_PATHD:/Libs/install/boost;D:/Libs/install/qhull;C:/Qt/5.15.2/mingw81_64 -DCMAKE_INSTALL_PREFIXD:/Libs/install/VTK -DVTK_QT_VERSION5 -DVTK_GROUP_ENABLE_QtWANT -DModule_vtkGUISupportQtON -DModule_vtkGUISupportQtOpenGLON -DModule_vtkRenderingQtON -DBUILD_TESTINGOFF -DBUILD_EXAMPLESOFF -DBUILD_SHARED_LIBSON .. mingw32-make -j4这里我解释几个选项。VTK_QT_VERSION5告诉 VTK 去匹配 Qt5 的 CMake 模块。VTK_GROUP_ENABLE_QtWANT会比较克制地启用 Qt 相关模块避免把所有 Qt 模块都编进来。Module_vtkGUISupportQt和Module_vtkGUISupportQtOpenGL是 PCL 可视化窗口必须的否则后面 PCL 的 visualizer 会找不到 VTK 的 Qt 窗口组件。BUILD_TESTINGOFF、BUILD_EXAMPLESOFF一定要关不然编译时间还要翻倍。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_TYPERelease -DCMAKE_PREFIX_PATHD:/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_PREFIXD:/Libs/install/PCL -DBUILD_visualizationON -DBUILD_toolsON -DBUILD_appsOFF -DBUILD_examplesOFF -DBUILD_GPUOFF -DWITH_QTON -DWITH_VTKON -DWITH_OPENGLON ..如果前面几个依赖都装到了统一前缀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。接着写一个最小测试程序确认编译结果可用。先建工程目录写一个 CMakeListscmake_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::PointCloudpcl::PointXYZ::Ptr cloud(new pcl::PointCloudpcl::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_COMPILERgcc -DCMAKE_CXX_COMPILERg ..如果 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 库就可能找不到符号。最简单的做法是全程只编 releasePCL 的 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 可视化窗口再回头去调整模块开关、尝试更新版本那时候你已经知道该去哪里查问题也就不会觉得这些库难伺候了。本文还有配套的精品资源点击获取
返回列表