cmake--find_package
软件包(Package),也称为程序包或模块包,是一种将程序、相关文件和配置信息打包到一起的格式化文件集合,通常包括可执行文件、库文件、文档、示例代码等。不需要,只需要指定包的名称和其他参数。
作用
查找系统上安装的包所在的路径,执行这个包的配置文件(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中调用,也可以人为调用
更多推荐
所有评论(0)