Cmake中find_package命令的搜索模式之模块模式(Modulemode)_...

Cmake中find_package命令的搜索模式之模块模式(Modulemode)_...

2023年7月26日发(作者:)

Cmake中find_package命令的搜索模式之模块模式(Modulemode)⼀、模块模式简介  前⾯介绍了find_package有两种搜索包的模式(参考find_package介绍),本篇⽂章介绍其中的⼀种:模块模式(Module Mode)。在这种模式下,当调⽤find_package命令查找包的时候,实际上会去查找⼀个名为Find.cmake的⽂件,这个⽂件的主要任务就是确定⼀个包是否可⽤,查找的结果会反映在变量_FOUND上供find_package的调⽤者使⽤。当找到可⽤的包,同时也会提供使⽤这个包所需要的变量、宏和导⼊⽬标(例如库⽂件)。  前⾯已经介绍过使⽤系统提供的来查找LibLZMA库,这个⽂件是CMake在安装的时候就提供的,位于CMake的安装⽬录之下。因此对于未提供该⽂件的第三⽅库,我们可以通过⾃⼰⽣成Find.cmake来供CMake使⽤,接下来将介绍如何利⽤⾃⼰⽣成的.cmake⽂件找到⾃⼰编写的库。  模块模式依赖另⼀个程序:pkg-config,在继续往下之前,请参考pkg-config⽤法详解了解这个命令。⼆、标准变量名称  Find.cmake⽂件承担了定义包相关的变量的作⽤,这些变量称作"标准变量"。⼀旦find_package调⽤成功,这些变量将返回给调⽤者使⽤,为了保证不同的包之间返回的变量不冲突,对编写的Find.cmake返回的标准变量名称有如下约束:所有的变量都是以PackageName_开头,PackageName就是⽂件Find.cmake中的,必须完全⼀致,⼤⼩写敏感。简单的列举⼏个变量定义如下,更多的变量定义见本⽂的四、对标准变量名称的更多说明:PackageName_INCLUDE_DIRS:使⽤包需要包含的头⽂件。PackageName_LIBRARIES:使⽤包所需要的库⽂件,是全路径或者链接器能在库搜索⽬录下找到的库⽂件名称。PackageName_DEFINITIONS:使⽤包所需要的编译选项。PackageName_LIBRARY:库的路径,只有当包提供的是单个库的时候才能使⽤这形式。PackageName_INCLUDE_DIR:使⽤包所需要包含的头⽂件⽬录,只能在单个库的使⽤,使⽤者需要将该路径加⼊到搜索路径中。三、编写.cmake⽂件  接下来我们来写⼀个.cmake⽂件,假设我们的包名为mymath,该包提供⼀个libmymath.a的库,其中包含⼀个add接⼝,简单计算两个整数的和并打印出结果(对这个库的更多信息可以参考pkg-config⽤法详解的4.1~4.3⼩节)。在编写之前,我们先来看下.cmake⽂件的格式。3.1

.cmake⽂件的格式⽂件开头是license信息接着是⼀个CMake⽀持的多⾏注释(单⾏注释以#开头;多⾏注释是指:以#[开头,紧接着跟着0个或多个=,之后是[,接下来就是注释内容,注释可以跨越多⾏,然后以]、0个或多个=、]组成结束,开头的=个数要和结尾的=个数相等),.cmake要求注释以.rst:开头:# 多⾏注释,0个=的情况#[[...中间的内容都是注释...]]# 多⾏注释,多个=的情况,开始的=和结尾的=要保持数量⼀致,此例⼦中为5个=#[=====[...中间的内容都是注释...]=====]接下来在注释中间申明find_package的标准变量及相关说明。1)⾸先是包的名字,分为两⾏,第⼀⾏是包名字,第⼆⾏是包名字下⽅的下划线---(与包名字等长度)。2)接着是对包的⼀个简要描述,这个没有特殊要求。3)接下来分为⼏个部分,主要是作⽤对⼏类变量的申明(导⼊变量、结果变量、缓存变量),格式都是⼀致的:⾸先是变量类型的说明,并在其下⽅以等长^^^^标识,接着是⼀段⽂件对变量内容的简要描述,接着是我们要定义的标准变量了,变量以``标准变量``标识(两对``符号,中间是变量名称),每个变量下可以对变量做⼀个简短的描述说明。注释部分到此结束,接下来是对库进⾏真正查找,并把注释部分申明的变量进⾏赋值的过程。1)先尝试使⽤pkg-config来找到真正的库,pkg-config是系统提供的命令⽤于找系统中是否存在相关的库(参考pkg-config⽤法详解),在CMake中使⽤如下两条,CMake会从.pc⽂件中读取对应的变量。find_package(PkgConfig)pkg_check_modules(PC_mymath QUIET mymath)2)如果能找到库,那么变量PC_mymath_FOUND存在,并且可以得到mymath相关的头⽂件和库⽬录,并且是存储在以PC_mymath_XXX开头的变量中,例如PC_mymath_INCLUDE_DIRS(头⽂件⽬录)、PC_mymath_LIBRARY_DIRS(库⽂件⽬录)、PC_mymath_LIBRARIES(库名称)等等(具体有哪些变量可以参考man pkg-config或者在中过滤PC_mymath查看)。上⼀步利⽤了pkg-config获得的变量还不是最终要给find_package返回的变量,我们要对返回的变量做正确的赋值,并最终调⽤include(FindPackageHandleStandardArgs)和find_package_handle_standard_args将变量返回给find_package调⽤处。include(FindPackageHandleStandardArgs)find_package_handle_standard_args(mymathFOUND_VAR mymath_FOUNDREQUIRED_VARS mymath_LIBRARY mymath_INCLUDE_DIRVERSION_VAR mymath_VERSION)3.2 编写⾃⼰的⽂件  假定我们使⽤的库mymath已经提供了.pc⽂件,并能够通过pkg-config⽅式找到它(可以通过pkg-onfig --list-all查看到mymath库,参考pkg-config⽤法详解)。  接下来我们来编写库mymath的⽂件,参照前⾯.cmake⽂件说明,内容如下,⽰例只提供了库⽬录、库⽂件、头⽂件等少量变量信息:# #[============[.rst:Findmymath----------对这个⽂件的描述:查找mymath库Imported Targets^^^^^^^^^^^^^^^^如果提供导出可执⾏⽬标,可以在下⾯进⾏定义:``mymath::mymath`` 导出mymath::mymath可执⾏⽬标,我们的测试库并未提供,该处只是⼀个⽰意Result Variables^^^^^^^^^^^^^^^^可以在下⾯定义⼀些普通变量:``mymath_FOUND`` 如果找到mymath库,该变量值为True.``mymath_VERSION`` mymath库的版本.``mymath_INCLUDE_DIRS`` 使⽤mymath库需要包含的头⽂件.``mymath_LIBRARIES`` 使⽤mymath库需要⽤到的库⽂件.Cache Variables^^^^^^^^^^^^^^^可以在下⾯定义⼀些缓存变量:``mymath_INCLUDE_DIR`` 包含mymath.h头⽂件的⽬录.``mymath_LIBRARY`` mymath库所在的⽬录.]============]find_package(PkgConfig)pkg_check_modules(PC_mymath QUIET mymath)find_path(mymath_INCLUDE_DIR NAMES mymath.h PATHS ${PC_mymath_INCLUDE_DIRS} PATH_SUFFIXES mymath)find_library(mymath_LIBRARY NAMES mymath PATHS ${PC_mymath_LIBRARY_DIRS})set(mymath_VERSION ${PC_mymath_VERSION})set(mymath_INCLUDE_DIRS "/just/for/include/test") # 只是为了测试⽤,没有实际作⽤set(mymath_LIBRARY_DIRS "/just/for/library/test") # 只是为了测试⽤,没有实际作⽤# 将变量导出给调⽤者使⽤include(FindPackageHandleStandardArgs)find_package_handle_standard_args(mymath FOUND_VAR mymath_FOUND REQUIRED_VARS mymath_LIBRARY mymath_INCLUDE_DIR mymath_INCLUDE_DIRS mymath_LIBRARY_DIRS VERSION_VAR mymath_VERSION)  我们的测试⽂件如下:// #include "mymath.h"int main(int argc, char** argv){ mymath::add(1, 2); return 0;}  最后,在我们的来使⽤find_package来找到并使⽤mymath库# ,和测试⽂件在同个⽬录cmake_minimum_required(VERSION 3.10.2)project(find_package_test)message("Find path: ${CMAKE_MODULE_PATH}")find_package(mymath)if (mymath_FOUND) add_executable(test ) include_directories(${mymath_INCLUDE_DIR}) target_link_libraries(test ${mymath_LIBRARY}) set_target_properties(test PROPERTIES INTERFACE_COMPILE_OPTIONS "${PC_mymath_CFLAGS_OTHER}") # 这个语句在本例中不是必须,只是说明可以通过这种⽅式获取编译mymath库需要使⽤的编译选项endif()  在下执⾏cmake命令,此处为了演⽰,直接指定CMAKE_MODULE_PATH的值为当前的.cmake所在路径,这样find_package命令会直接找到我们编写的.cmake⽂件并读取其中的内容,编译并运⾏最终程序(只摘取了我们关注的显⽰信息):# 执⾏cmakecmake . -DCMAKE_MODULE_PATH=./# 运⾏结果,⾸次会打印出来找到的库以及所在的全路径、版本号等信息......-- Found PkgConfig: /usr/local/bin/pkg-config (found version "0.29.2")-- Found mymath: /XXX/mymath/lib/libmymath.a (found version "1.0")......# 执⾏makemake# 运⾏程序./test# 运⾏结果Add 1 and 2 is 3四、对标准变量名称的更多说明PackageName_INCLUDE_DIRS:使⽤包需要包含的头⽂件。PackageName_LIBRARIES:使⽤包所需要的库⽂件,是全路径或者链接器能在库搜索⽬录下找到的库⽂件名称。PackageName_DEFINITIONS:使⽤包所需要的编译选项。PackageName_EXECUTABLE:可执⾏⽂件的全路径。PackageName_YYY_EXECUTABLE:与上⾯类似,不过此处的YYY表⽰包中提供的其他可执⾏⽂件的名字,通常是全⼤写,可以使⽤这种⽅式避免名称冲突。可以⽤于包提供多个可执⾏⽂件的场景。PackageName_LIBRARY_DIRS:可选,库⽬录。PackageName_ROOT_DIR:包查找的根⽬录PackageName_VERSION_VV:指定模块的版本号是VV,但是要注意,⼀个模块可能有多个历史的版本,只能有⼀个版本的变量设置成true,例如模块mymath有三个版本,分别是Version 1、Version 2、Version 3,那么mymath_VERSION_1、mymath_VERSION_2、mymath_VERSION_3这三个变量只能有⼀个设置为true,否则会报错。PackageName_WRAP_YY:当该变量设置为false,表明相关的包装命令⽆法使⽤。PackageName_Yy_FOUND:此处的Yy表⽰包的组件,必须跟find_package命令提供的组件名称完全匹配,如果该变量设置为false,表明组件未找到或者不可⽤。可⽤于检查哪些组件是可⽤的。PackageName_FOUND:如果能找到模块,那么该变量会置为true。PackageName_NOT_FOUND_MESSAGE:未找到时候的消息提⽰。PackageName_RUNTIME_LIBRARY_DIRS:可选,运⾏库的搜索路径,当可执⾏⽂件需要链接到共享库的时候需要指定该变量,以让链接器能找到对应的共享库路径。在windows下,会将该变量内容加⼊到PATH,Linux下会加⼊到LD_LIBRARY_PATH。PackageName_VERSION:找到模块的全版本字符串,值得注意的是当前许多存在的模块使⽤的是PackageName_VERSION_STRING替代。PackageName_VERSION_MAJOR:主版本号PackageName_VERSION_MINOR:次版本号PackageName_VERSION_PATCH:补丁版本号PackageName_LIBRARY:库路径,只有当模块提供的是单个库的时候才能使⽤这形式,多个库可以参考下⾯的命令。PackageName_Yy_LIBRARY:模块PackageName提供的库Yy的路径,当⼀个包下有多个库、或者其他包有同名的库时(也就是不同包之间库重名的时)使⽤。PackageName_INCLUDE_DIR:使⽤库需要包含的头⽂件⽬录,只能在单个库的使⽤。使⽤者需要将该路径加⼊到搜索路径中。PackageName_Yy_INCLUDE_DIR:多个库时候,指定使⽤库Yy需要包含的头⽂件。附录:参考⽂档1. /cmake/help/v3.0/module/

发布者:admin,转转请注明出处:http://www.yc00.com/news/1690364641a338579.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信