cmake学习(二)引用外部库(find_package分析)

案例:lio-sam-linux项目的CMakeLists.txt

通过这个例子学习一下引用外部库的相关内容。

(貌似项目本身的构建结构不太符合规范,这个后面再修改。,。)

项目路径:

在这里插入图片描述

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(lio_sam_linux)

#set命令可以设置普通变量、缓存条目、环境变量三种变量的值。
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -g -pthread")

# 引入外部包
find_package(OpenMP REQUIRED)
find_package(PCL REQUIRED QUIET)
find_package(OpenCV REQUIRED QUIET)
find_package(GTSAM REQUIRED QUIET)


# include directories
include_directories(
  /usr/include/eigen3
	${PCL_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
	${GTSAM_INCLUDE_DIR}
)


###########
## Build ##
###########

aux_source_directory(./src/communication_LVI_SAM DIR_COMM_SRCS)
aux_source_directory(./src/pcl DIR_PCL_STRUCT_SRCS)
aux_source_directory(./src/tf DIR_TF_STRUCT_SRCS)

message("***${DIR_COMM_SRCS}***")

# Range Image Projection
add_executable(${PROJECT_NAME}_imageProjection src/imageProjection.cpp ${DIR_COMM_SRCS} ${DIR_PCL_STRUCT_SRCS} ${DIR_TF_STRUCT_SRCS})
# add_dependencies(${PROJECT_NAME}_imageProjection )
target_link_libraries(${PROJECT_NAME}_imageProjection ${PCL_LIBRARIES} ${OpenCV_LIBRARIES})

# Feature Association
add_executable(${PROJECT_NAME}_featureExtraction src/featureExtraction.cpp ${DIR_COMM_SRCS} ${DIR_PCL_STRUCT_SRCS} ${DIR_TF_STRUCT_SRCS})
# add_dependencies(${PROJECT_NAME}_featureExtraction ${PROJECT_NAME}_generate_messages_cpp)
target_link_libraries(${PROJECT_NAME}_featureExtraction ${PCL_LIBRARIES} ${OpenCV_LIBRARIES})

# Mapping Optimization
add_executable(${PROJECT_NAME}_mapOptmization src/mapOptmization.cpp ${DIR_COMM_SRCS} ${DIR_PCL_STRUCT_SRCS} ${DIR_TF_STRUCT_SRCS})
# add_dependencies(${PROJECT_NAME}_mapOptmization ${PROJECT_NAME}_generate_messages_cpp)
target_compile_options(${PROJECT_NAME}_mapOptmization PRIVATE ${OpenMP_CXX_FLAGS})
target_link_libraries(${PROJECT_NAME}_mapOptmization ${PCL_LIBRARIES} ${OpenCV_LIBRARIES} ${OpenMP_CXX_FLAGS} gtsam)

# IMU Preintegration
add_executable(${PROJECT_NAME}_imuPreintegration src/imuPreintegration.cpp ${DIR_COMM_SRCS} ${DIR_PCL_STRUCT_SRCS} ${DIR_TF_STRUCT_SRCS})
target_link_libraries(${PROJECT_NAME}_imuPreintegration ${PCL_LIBRARIES} ${OpenCV_LIBRARIES} gtsam)


# tf
add_executable(${PROJECT_NAME}_tfChangeProjection src/tfChangeProjection.cpp ${DIR_COMM_SRCS} ${DIR_PCL_STRUCT_SRCS} ${DIR_TF_STRUCT_SRCS})
target_link_libraries(${PROJECT_NAME}_tfChangeProjection ${PCL_LIBRARIES} ${OpenCV_LIBRARIES} gtsam)

这里着重一下find_package()

由于网上关于这个命令的讲解比较混杂,所以直接看官方文档

https://cmake.org/cmake/help/latest/command/find_package.html

该命令的作用:找到一个包(通常由项目外部的某个东西提供),并加载其特定于包的详细信息。

查找分为两个模式

  • Module Mode
    • 在此模式下,CMake会搜索名为**Find**的文件。
    • 首先在cmake_MODULE_PATH中列出的位置中查找,然后在CMAKE安装提供的查找模块中查找。
    • 如果找到该文件,CMake将读取并处理它。它负责找到包,检查版本,并产生任何需要的消息。一些Find模块对版本控制提供有限的支持或者不提供支持;查看查找模块的文档。 查找<包名>。cmake文件通常不由包本身提供。相反,它通常是由包外部的东西提供的,比如操作系统、CMake本身,甚至是调用find_package()命令的项目。由于是外部提供的,Find模块本质上倾向于启发性的,容易过时。他们通常搜索特定的库、文件和其他包工件。 模块模式仅受基本命令签名支持。
    • 总结一下,Module Mode基本上只用来查找一些cmake官方支持的库,一般用不到这个(我的理解)
  • Config mode
    • 在此模式下,CMake会搜索名为**< lowercasePackageName >-Config . CMake或< PackageName>Config.cmake**的文件。
    • 如果指定了版本详细信息,它还会查找< lowercasePackageName >-Config-Version . CMake或< package name > Config Version . CMake(有关如何使用这些单独的版本文件的说明,请参见配置模式版本选择)。
    • 在配置模式下,可以给命令一个名称列表,作为包名进行搜索。CMake搜索配置和版本文件的位置比模块模式要复杂得多(参见配置模式搜索过程)。 **配置和版本文件通常作为包的一部分安装,所以它们比Find模块更可靠。**它们通常包含包内容的直接知识,所以在配置或版本文件本身中不需要搜索或试探。 基本命令签名和完整命令签名都支持配置模式。
  • 命令参数决定了使用上述哪种模式。
    • 当使用基本签名(就是find_package中传入的那个标识符一样的东西)时,该命令首先以模块模式进行搜索。
    • 如果找不到包,搜索将返回到配置模式
    • 用户可以将CMAKE _ FIND _ PACKAGE _ prefere _ CONFIG变量设置为true,以反转优先级,并指示CMAKE在返回模块模式之前首先使用配置模式进行搜索。基本签名也可以通过Module关键字强制只使用模块模式。如果使用完整签名,该命令仅在配置模式下搜索。 在可能的情况下,用户代码通常应该使用基本签名来查找包,因为这允许用任何一种模式找到包。希望提供一个配置包的项目维护者应该了解更大的图景,正如完整签名和本页所有后续部分所解释的。

所以,在最基本的写法中,find_package会优先使用module mode进行查找;没找到的话使用config mode进行查找。

需要重点关注的是,在config mode下的查找中,遵循以下的查找原则:

  • CMake为包构造了一组可能的安装前缀。在每个前缀下,在几个目录中搜索配置文件。下表显示了搜索的目录。每个条目都适用于遵循Windows (W)、UNIX (U)或Apple (A)惯例的安装树:

    <prefix>/                                                       (W)
    <prefix>/(cmake|CMake)/                                         (W)
    <prefix>/<name>*/                                               (W)
    <prefix>/<name>*/(cmake|CMake)/                                 (W)
    <prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/                 (U)
    <prefix>/(lib/<arch>|lib*|share)/<name>*/                       (U)
    <prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/         (U)
    <prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/         (W/U)
    <prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/               (W/U)
    <prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (W/U)
    

除了上面一些基本内容,还有一些其他内容,这里简略记录:

  • REQUIRED和QUIET参数:如果指定了QUIET选项,那么表示:就算未找到该包的配置文件,也不会报错。 相反地,如果指定了REQUIRED选项:如果未找到文件,会报错。

  • config模式后,会自动赋值一些变量,一下举例几个常用的:

    <LibaryName>_FOUND
    
    <LibaryName>_INCLUDE_DIR or <LibaryName>_INCLUDES 
    
    <LibaryName>_LIBRARY or <LibaryName>_LIBRARIES or <LibaryName>_LIBS
    

拿本次CMakeLists.txt中的一个find_package举例:

find_package(PCL REQUIRED QUIET)

该库的PCLConfig.cmake的路径:

cislc2019@cislc2019-System-Product-Name:/usr/lib$ find -iname "PCLConfig.cmake"
./x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake

找到后,就会对一些相关的变量进行赋值,例如下面的

# include directories
include_directories(
  /usr/include/eigen3
	${PCL_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
	${GTSAM_INCLUDE_DIR}
)
target_link_libraries(${PROJECT_NAME}_featureExtraction ${PCL_LIBRARIES} ${OpenCV_LIBRARIES})

其他内容在之前的案例中已经学习过了,这里不再记录

小问题:

第18行中,手动添加了一行路径。

re:编译的时候,pcl依赖的eigen3找不到头文件路径

暂时不清楚原因,而且eigen3是一个完全由头文件组成的库,可能情况特殊?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值