vtk编译问题踩坑-Ubuntu16.04编译切换pcl版本
问题描述:
最近试着编译一个使用vtk做图形显示的包,结果编译出现一大堆关于vtk库的问题,这种报错困扰我很长时间了,以前碰到了不知道怎么改,这次决定好好查查到底是哪里出了问题。作为一个刚入门的小白,对这些编译的问题理解不是很深刻,对于这些编译错误的解决方法也仅是停留在网上搜帖子,能找到合适的解决方法属于万幸的程度。还是老话,如果跟我的报错和情况类似,也建议您酌情采纳。
一、报错
[100%] Linking CXX executable environment
CMakeFiles/environment.dir/src/environment.cpp.o:在函数‘__static_initialization_and_destruction_0(int, int)’中:
/usr/local/include/vtk-7.1/vtkObjectFactory.h:301:对‘vtkObjectFactoryRegistryCleanup::vtkObjectFactoryRegistryCleanup()’未定义的引用
/usr/local/include/vtk-7.1/vtkObjectFactory.h:301:对‘vtkObjectFactoryRegistryCleanup::~vtkObjectFactoryRegistryCleanup()’未定义的引用
CMakeFiles/environment.dir/src/environment.cpp.o:在函数‘vtkRenderingCore_AutoInit::vtkRenderingCore_AutoInit()’中:
/usr/local/include/vtk-7.1/vtkRenderingCoreModule.h:44:对‘vtkInteractionStyle_AutoInit_Construct()’未定义的引用
/usr/local/include/vtk-7.1/vtkRenderingCoreModule.h:44:对‘vtkRenderingFreeType_AutoInit_Construct()’未定义的引用
/usr/local/include/vtk-7.1/vtkRenderingCoreModule.h:44:对‘vtkRenderingOpenGL2_AutoInit_Construct()’未定义的引用
CMakeFiles/environment.dir/src/environment.cpp.o:在函数‘vtkRenderingCore_AutoInit::~vtkRenderingCore_AutoInit()’中:
/usr/local/include/vtk-7.1/vtkRenderingCoreModule.h:44:对‘vtkInteractionStyle_AutoInit_Destruct()’未定义的引用
/usr/local/include/vtk-7.1/vtkRenderingCoreModule.h:44:对‘vtkRenderingFreeType_AutoInit_Destruct()’未定义的引用
/usr/local/include/vtk-7.1/vtkRenderingCoreModule.h:44:对‘vtkRenderingOpenGL2_AutoInit_Destruct()’未定义的引用
CMakeFiles/environment.dir/src/render/render.cpp.o:在函数‘__static_initialization_and_destruction_0(int, int)’中:
/usr/local/include/vtk-7.1/vtkObjectFactory.h:301:对‘vtkObjectFactoryRegistryCleanup::vtkObjectFactoryRegistryCleanup()’未定义的引用
/usr/local/include/vtk-7.1/vtkObjectFactory.h:301:对‘vtkObjectFactoryRegistryCleanup::~vtkObjectFactoryRegistryCleanup()’未定义的引用
CMakeFiles/environment.dir/src/render/render.cpp.o:在函数‘pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZI>::getColor(vtkSmartPointer<vtkDataArray>&) const’中:
/usr/local/include/pcl-1.8/pcl/visualization/impl/point_cloud_color_handlers.hpp:71:对‘vtkAOSDataArrayTemplate<unsigned char>::SetArray(unsigned char*, long long, int, int)’未定义的引用
CMakeFiles/environment.dir/src/render/render.cpp.o:在函数‘pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZI>::getColor(vtkSmartPointer<vtkDataArray>&) const’中:
/usr/local/include/pcl-1.8/pcl/visualization/impl/point_cloud_color_handlers.hpp:154:对‘vtkAOSDataArrayTemplate<unsigned char>::GetPointer(long long)’未定义的引用
CMakeFiles/environment.dir/src/render/render.cpp.o:在函数‘pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>::getColor(vtkSmartPointer<vtkDataArray>&) const’中:
/usr/local/include/pcl-1.8/pcl/visualization/impl/point_cloud_color_handlers.hpp:71:对‘vtkAOSDataArrayTemplate<unsigned char>::SetArray(unsigned char*, long long, int, int)’未定义的引用
CMakeFiles/environment.dir/src/render/render.cpp.o:在函数‘pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZ>::getColor(vtkSmartPointer<vtkDataArray>&) const’中:
/usr/local/include/pcl-1.8/pcl/visualization/impl/point_cloud_color_handlers.hpp:154:对‘vtkAOSDataArrayTemplate<unsigned char>::GetPointer(long long)’未定义的引用
CMakeFiles/environment.dir/src/render/render.cpp.o:在函数‘pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI>::getColor(vtkSmartPointer<vtkDataArray>&) const’中:
/usr/local/include/pcl-1.8/pcl/visualization/impl/point_cloud_color_handlers.hpp:436:对‘vtkAOSDataArrayTemplate<float>::SetArray(float*, long long, int, int)’未定义的引用
collect2: error: ld returned 1 exit status
CMakeFiles/environment.dir/build.make:212: recipe for target 'environment' failed
make[2]: *** [environment] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/environment.dir/all' failed
make[1]: *** [CMakeFiles/environment.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
二、问题分析
一般,这种编译报错为未定义的引用的原因比较常见的有两种情况:
1、版本不对应;
2、CMakeLists的target_link_libraries或者include_directories没写对。
对应情况2,如何去验证我就不写了,可以去看《cmake practice》,这本pdf很短,用不了多长时间就可以看完,适合刚入门的新手学习。接下来重点分析情况1如何解决,因为我的问题就是这种情况。
三、我的情况
一般pcl和vtk的版本是需要对应的,参考这里:
(1) pcl-1.7.2 vtk-5.10.1 / vtk-6.2.0
(2) pcl-1.8.1 vtk-7.1.1
(3) pcl-1.9.1 vtk-8.2.0
因为最开始装ROS的时候,我的电脑装的是Ubuntu16.04 + ROS kinetic,由于刚入门对这些版本安装不是很懂,后来才知道ROS kinetic自带pcl-1.7,而我后来自己使用源码编译的方式安装了pcl-1.8,由于对Linux下软件的删除不是很懂,所以导致我现在的电脑编译默认使用的是pcl-1.8,但实际上,我的pcl-1.7仍然存在,也就是说我的情况是pcl-1.7和pcl-1.8共存!
因此在我编译那个依赖vtk的包时,总是报错vtk函数未定义的引用,虽然我不知道那个包是依赖vtk-6.2还是vtk7.1,也就是pcl-1.7还是pcl-1.8,但是一个偶然的机会,我用我的另一台电脑编译这个包,能够编译过去,同时在cmake输出的编译信息里,我发现那个包是依赖pcl1.7的,因为我的另一台电脑只安装了pcl-1.7.所以现在的问题就变成了,如何在一台既有pcl-1.7,又有pcl-1.8的电脑上,且系统默认通过find_package命令使用的版本是pcl-1.8时,更改系统默认编译pcl为pcl-1.7版本的问题!!!
报错电脑cmake编译后输出的信息:
-- looking for PCL_2D
-- Found PCL_2D: /usr/local/include/pcl-1.8
-- looking for PCL_FEATURES
-- Found PCL_FEATURES: /usr/local/lib/libpcl_features.so
-- looking for PCL_GEOMETRY
-- Found PCL_GEOMETRY: /usr/local/include/pcl-1.8
//注意:下面这四行的输出需要自己在CMakeLists中加入MESSAGE命令,如何添加可以看我的上一篇帖子。
-- pcl include dir /usr/local/include/pcl-1.8/usr/include/eigen3/usr/include/usr/include/ni/usr/include/openni2/usr/local/include/vtk-7.1
-- pcl link dir /usr/local/lib
-- pcl definition dir -DEIGEN_USE_NEW_STDVECTOR-DEIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET-DFLANN_STATIC-Dqh_QHpointer
-- pcl PCL_DIR dir /usr/local/share/pcl-1.8
四、解决方法-编译指定的pcl版本
这里主要参考这个帖子.
解决方法:在CMakeLists中的find_package前加入这条语句:
set(PCL_DIR "/usr/lib/x86_64-linux-gnu/cmake/pcl")
find_package(PCL 1.7 REQUIRED)
CMakeLists的find_package命令是通过cmake文件来寻找指定的库版本和头文件路径的,这个路径一般设在了系统的环境变量里,不过本人很菜,不想那么麻烦去改环境变量,所以更省事的方法是在指定包的CMakeLists中强制指定需要版本库的cmake文件路径。
**因为pcl-1.7默认的cmake文件就放在/usr/lib/x86_64-linux-gnu/cmake/pcl路径下,在CMakeLists中指定该路径后,系统就不会去默认寻找/usr/local/share/pcl-1.8路径下pcl-1.8的cmake文件了。**你可以检查一下你电脑的这两个路径,看看是不是有pcl对应的cmake文件!
修改后cmake编译输出:
-- Found PCL_MODELER: /usr/include/pcl-1.7
-- looking for PCL_IN_HAND_SCANNER
-- Found PCL_IN_HAND_SCANNER: /usr/include/pcl-1.7
-- looking for PCL_POINT_CLOUD_EDITOR
-- Found PCL_POINT_CLOUD_EDITOR: /usr/include/pcl-1.7
-- pcl link dir /usr/lib/x86_64-linux-gnu
-- pcl definition dir -DEIGEN_USE_NEW_STDVECTOR-DEIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET-DFLANN_STATIC-Dqh_QHpointer
-- pcl PCL_DIR dir /usr/lib/x86_64-linux-gnu/cmake/pcl
注意:如果更改后还是没效果,建议把build文件夹删除后,重新执行cmake… & make,检查编译输出。