find_package()的用法

作用

主要就是通过库对应的.cmake文件(由库的维护者提供,一般用不着自己写),获得第三方库的头文件以及动/静态库文件的路径,方便我们直接添加到我们自己的工程里面

  • <PackageName>_FOUND :找到了就是True,没找到就是未设定
  • <PackageName>_INCLUDE_DIR :头文件目录
  • <PackageName>_LIBRARY :库文件(只能通过该API找到静态库,动态库还是得放到Path环境变量等地方)

两种工作模式

Config模式

在该模式下,CMake会在其搜索路径下搜索<lowercasePackageName>-config.cmake 或者 <PackageName>Config.cmake这2个文件,通常这2个文件在安装时就会自动被放在了安装目录中的cmake文件夹下。也就是通常由写这个库的官方作者提供。

Module模式

在该模式下,CMake会在其搜索路径下搜索Find<PackageName>.cmake文件。一般是在官方没提供config模式的配置文件时,才用这个模式。操作系统,cmake官方都预先为我们提供了许多Module模式的.cmake文件

配置文件的搜索

搜索路径

CMake会在以下一些地方搜索.cmake文件

  • Path环境变量 如/usr/local/

当时OpenCV不需要设置搜索路径就是因为存放了它的.cmake文件的那个路径被添加到环境变量之中了。

  • CMAKE_PREFIX_PATH这个list变量里面存的地址

  • CMAKE_MODULE_PATH这个list变量里面存的地址

  • <Packname>_ROOT变量存的地址

  • <Packenmae>_DIR变量存的地址

除了CMAKE_PREFIX_PATH,其他的得输入完整地址。而CMAKE_PREFIX_PATH只需要写上CMAKE_INSTALL_PREFIX的地址就行了

因为CMake会根据传入的CMAKE_PREFIX_PATH自动创建好几个可能有.cmake文件的路径,依次在里面搜索。如果找不到的话,再把CMAKE_PREFIX_PATH改成具体的路径就行了。

1
2
3
4
5
6
7
list(APPEND CMAKE_PREFIX_PATH "E:\\ThirdPart\\YAML_CPP")
find_package(yaml-cpp REQUIRED)
list(APPEND CMAKE_PREFIX_PATH "D:\Qt\6.3.1\mingw_64")
# 添加新路径到list之中`

#命令行设置
cmake -DCMAKE_PREFIX_PATH=D:\Qt\6.3.1\mingw_64

Ubuntu注意事项

home/lrq这个地址必须用~/表示,不然就会报错

1
set(CMAKE_PREFIX_PATH "~/Desktop/YAML")

CMake的缓存机制

但凡CMake成功的find_package()了一次,他会把.cmake文件缓存到本工程中,如果在写代码的过程中,换了第三方库的位置,一定得清除CMake的缓存然后重新配置,要不然它只在之前的地方搜索头文件之类的,会一直报错。真TM的Sb

版本选择

可以通过在find_package()里添加一个版本信息,如果找不到对应版本的,他会显示当前使用.cmake文件的路径

该API支持哪些包?

理论上只要符合find_package命令的查找条件,能让该命令识别的包或者库都会被支持。在实际使用时,我们可以把这些包分成三类:

官方预定义的包
为了方便我们查找依赖包,cmake为我们包含了许多默认的依赖包,这些包是cmake发行版的一部分,也就是说可以直接在CMakeLists.txt文件中引用,不需要额外安装。它们的位置通常是在cmake安装目录的Module目录下(比如我的系统内是:/usr/share/cmake-3.17/Modules),也可以通过变量CMAKE_MODULE_PATH来指定。
cmake预支持的包可以查看cmake-modules

非官方但支持cmake的包
这一类包虽然不在cmake的预支持列表中,但是自行下载使用cmake编译安装后也能被cmake识别,使用方法与官方预定义包一致。比如glog包。

默认不支持cmake的包
最典型的是我们自己编写的库文件,这类文件既不在cmake的官方列表,安装时默认也不会被cmake搜索到,此时就需要我们自行编写相应的配置文件并放到对应的路径中去。

基本用法

我们要搜索一个名为 PackageName 的包。

1
find_package(PackageName)

因为对于项目来说,有些包是可选的。但有些是必要的。对于必要的,可以指定REQUIRED,这样找不到对应的包就会报错。

1
find_package(PackageName REQUIRED)

另外,有些包其中有许多的组件,你可以指定COMPONENTS 来只使用某些组件

1
find_package(PackageName COMPONENTS xxx)

常用库的添加方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
find_package(yaml-cpp REQUIRED)
if(yaml-cpp_FOUND)
message("yaml-cpp Package found")
message(${YAML_CPP_INCLUDE_DIR})
message(${YAML_CPP_LIBRARIES})
endif()

target_link_libraries(test
${YAML_CPP_LIBRARY_DIR}
)
#或者
target_link_libraries(test yaml-cpp)

target_include_directories(test
PRIVATE #必须加PRIVATE
${YAML_CPP_INCLUDE_DIRS}
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
配置pcl库
find_package(PCL 1.7 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (node_name source_code)
target_link_libraries(node_name ${PCL_LIBRARIES})

配置eigen库
find_package(cmake_modules REQUIRED)
find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
add_definitions(${EIGEN3_DEFINITIONS})

配置opencv库
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(node_name ${OpenCV_LIBRARIES})

配置yaml-cpp库
find_package(yaml-cpp REQUIRED)
include_directories(${YAML_CPP_INCLUDE_DIR})
target_link_libraries(node_name yaml-cpp)

配置openmp库
FIND_PACKAGE( OpenMP REQUIRED)
if(OPENMP_FOUND)
message(“OPENMP FOUND”)
set(CMAKE_C_FLAGS “${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}”)
set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}”)
set(CMAKE_EXE_LINKER_FLAGS “${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}”)
endif()