链接

比较详细教程

参数

作用

查找系统上安装的包所在的路径,执行这个包的配置文件(eg:OpenCVConfig.cmake,OpenCVModule.cmake),在项目中定义一些变量,配置这个包的库文件,头文件等的路径,使得编译项目时,可以找到库文件和头文件,完成项目正确编译。

本质上并不是找包的路径,而是找包的配置文件.cmake文件;

找到包的cmake文件------配置包的头文件和库文件变量----引用头文件和库文件变量构建项目;

两种搜索模式

链接

模块模式(Module mode

在该模式下,Cmake会搜索一个名为Find<PackageName>.cmake的文件,其中<PackageName>为待搜索包的名称。

搜索路径的顺序依次是:

从变量CMAKE_MODULE_PATH指定的路径中进行查找
从Cmake安装路径中查找。Cmake会在其安装路径下提供很多.cmake文件,例如/XXX/cmake/Modules/目录下(不同的系统安装目录可能不一致)
如果找到文件Find<PackageName>.cmake,Cmake会读取并处理该文件,简而言之,它负责检查一些条件(如版本号是否满足等)是否满足,并在找到包后,返回给调用者一些变量,用以获取包的详细信息。

使用

所以,当我们要找一些FindPackage_name.cmake模块时,需要配置和使用的方式是:

#将模块所在的路径添加到模块的寻找路径(CMAKE_MODULE_PATH)中
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
#指定find_package的搜索模式为模块(Findxxx.cmake)模式
find_package(my_test MODULE REQUIRED)
#利用寻找之后的变量
if(NOT my_test_FOUND)
    message("error: connot found my_test moudle")
else()
    message(STATUS "found my_test moudle")
endif()

配置模式

该模式下,CMake会搜索<lowercasePackageName>-config.cmake文件或<PackageName>Config.cmake文件。如果find_package命令中指定了具体的版本,也会搜索<lowercasePackageName>-config-version.cmake或<PackageName>ConfigVersion.cmake文件,因此配置模式下通常会提供配置文件和版本文件(注意形式上要保持一致),并且作为包的一部分一起提供给使用者。

使用

1,安装在系统目录下(一般是通过sudo apt install下载的包)不需要指定寻找路径,直接寻找即可:

find_package(Eigen3 REQUIRED)

2,需要指定查询路径的:

#设置包配置文件的寻找路径  
set(yaml-cpp_DIR "${path_to_third_party}/yaml_cpp-1.12/lib/cmake/yaml-cpp")
#指定不适用默认的配置文件查询路径,而使用自定义的路径
find_package(yaml-cpp 1.12 REQUIRED NO_DEFAULT_PATH)

默认的搜索模式

从报错可以看出,默认先使用模块模式寻找,找不到的话,在通过配置模式寻找。

什么是包

软件包(Package),也称为程序包或模块包,是一种将程序、相关文件和配置信息打包到一起的格式化文件集合,通常包括可执行文件、库文件、文档、示例代码等。

只是查找并获取包和库所在路径还是加载这个包或者库

找到包或者库所在的路径,并加载包或者库中的cmake模块,其中有包或者库的路径变量,我们可以引用这些变量引用这些库或者包。

find_package需不需要指定查找路径

find_package只会在cmake定义的两个变量指定的路径下查找,所以,如果不在两个变量指定的路径下,就需要给这两个变量之一加上指定路径。

链接

find_package需不需要定义变量来获取查找到的路径

不需要,只需要指定包的名称和其他参数。

找到包之后,怎么引用包

find_package会找到指定包中的cmake模块,然后我们可以引用模块中的变量,一般有三个变量:

包名_DIR,包名_INCLUDE_DIRS,包名_LIBRARIES。

包名_DIR,包名_INCLUDE_DIRS,包名_LIBRARIES

链接

DIR:配置文件.cmake所在路径;

INCLUDE_DIR:包的头文件所在路径;

LIBRARIES:包的库文件所在路径;

eg:

find_package(rclcpp REQUIRED)
if(NOT rclcpp_FOUND)
  message("Not found rclcpp pakcges.")
else()
  message(STATUS "cmake path: ${rclcpp_DIR}")
  message(STATUS "include path: ${rclcpp_INCLUDE_DIRS}")
  message(STATUS "libraries path: ${rclcpp_LIBRARIES}")
endif()

如果这三个变量没有值输出,则:

find_package会到哪个变量指定的路径中寻找

链接

配置包的查找路径

设置变量:package_DIR;

find_package()不适用默认路径即可;

set(path_to_third_party "${CMAKE_SOURCE_DIR}/third_party")
set(PCL_DIR "${path_to_third_party}/pcl-1.10/share/pcl-1.10")
find_package(PCL 1.10 REQUIRED NO_DEFAULT_PATH)

包名_FOUND

bool变量,用于判断包是否找到;

if(protobuf_FOUND)---endif()

if(NOT protobuf_FOUND)---endif()

包名区分大小写吗

大小写很关键,一个字母不同,得出的结果也不同:

eg:

find_package(protobuf REQUIRED)
if(NOT protobuf_FOUND)
  message("Not found protobuf pakcges.")
else()
  message(STATUS "-----cmake path: ${protobuf_DIR}")
  message(STATUS "-----include path: ${protobuf_INCLUDE_DIRS}")
  message(STATUS "-----libraries path: ${protobuf_LIBRARIES}")
endif()

find_package(Protobuf REQUIRED)
if(NOT Protobuf_FOUND)
  message("Not found Protobuf pakcges.")
else()
  message(STATUS "-----Protobuf cmake path: ${Protobuf_DIR}")
  message(STATUS "-----protobuf cmake path: ${protobuf_DIR}")
  message(STATUS "-----include path: ${Protobuf_INCLUDE_DIRS}")
  message(STATUS "-----libraries path: ${Protobuf_LIBRARIES}")
endif()

结论:

1,find_package()中指定包名不区分大小写;

只要包名对都可以找到cmake文件;

2,变量名是区分大小写的;

find_package找的是动态库还是静态库

find_package设置的是库的路径,不管库的类型,也就是.cmake中配置的路径中是动态库,找的就是动态库,路径中配置的静态库找到就是静态库。

参数

version:待查找包的版本号要求;

  • REQUIRED:当未找到满足条件的包(例如版本号不匹配,或指定组件未找到等),会终止CMake的执行过程,并输出一条错误信息。如果未指定该选项,即使未找到满足条件的包,CMake的执行过程也会继续。
  • COMPONENTS:指定要查找的组件。通常一个包可能包含多个组件(可以理解为多个库,例如把C++的std看成一个包的概念,那么vector就是std下的其中一个组件),我们的工程可能会依赖包下的具体某个组件,因此可以通过这个选项来检测这些组件是否存在。通常的约定是,该选项后的组件应该都找到时才认为包找到,否则认为未找到满足条件的包。这个约束会依赖包的.cmake来实现,通过find_package命令传入的COMPONENTS可以通过<PackName>_FIND_COMPONENTS这个变量来获得

来源

NO_DEFAULT_PATH

不适用默认的包查找路径。

find_package_handle_standard_args

本质:

宏。

作用:

不会主动去找包,也不会主动给生成的可执行文件或者库文件配置找到的库的依赖。

用来定义所需要寻找的包的有关变量;

当find_package命令找到包的配置文件时,它会将配置文件中定义的变量和选项导入到CMake中,并调用find_package_handle_standard_args来处理和验证找到的包。因此,find_package_handle_standard_args并不是用来查找包的工具,它只是用来处理和验证找到的包的工具。

eg:

需要找到的模块:

test.cmake模块。

项目CMakeLists.txt:

find_package(test MODULE REQUIRED)

test.cmake中设置test模块的相关变量:

find_package_handle_standard_args(
  test
  FOUND_VAR test_FOUND
  REQUIRED_VARS test_LIB test_DIR
  VERSION_VAR test_VERSION)

这个宏在find_package中调用,也可以人为调用

链接

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐