• C++-Cmake指令:find_package【用于查找包(通常是使用三方库)】


    一、搜索模式

    find_package用于查找包(通常是使用三方库),并返回关于包的细节(使用包所依赖的头文件、库文件、编译选项、链接选项等)

    find_libaray直接在指定搜索目录下搜索库不同,find_package命令可以获取更多的信息,那么它的搜索方式也是与find_libaray不一样,它有两种不同的搜索方式,因此在介绍这个命令的细节之前,先简单介绍一下find_package命令的两种搜索模式:模块模式Module mode)和配置模式Config mode)。

    1.1 模块模式(Module mode

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

    搜索路径的顺序依次是:

    • 从变量CMAKE_MODULE_PATH指定的路径中进行查找
    • Cmake安装路径中查找。Cmake会在其安装路径下提供很多.cmake文件,例如/XXX/cmake/Modules/目录下(不同的系统安装目录可能不一致)

    如果找到文件Find.cmakeCmake会读取并处理该文件,简而言之,它负责检查一些条件(如版本号是否满足等)是否满足,并在找到包后,返回给调用者一些变量,用以获取包的详细信息。

    一般来说,Find.cmake文件不是随包本身一起提供的,更多的是外部针对已有包的重新包装,例如操作系统、Cmake程序、甚至是调用find_package命令的工程针对已有的包提供针对该包的.cmake文件。

    1.2 配置模式(Config mode

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

    该模式下对.cmake文件的搜索路径的顺序比较复杂,具体见本文的4.1节。

    .cmake后缀文件的作用是什么?

    find_package的两种搜索模式都会按照一定规则从路径下搜索.cmake后缀的文件,两种模式下的.cmake文件作用都是为了给find_package命令的调用方返回有关包的信息(头文件路径、库文件路径、编译连接选项、版本信息等等)

    二、命令格式

    find_package命令有两种格式,基本命令格式完整命令格式

    2.1 基本命令

    1. find_package( [version] [EXACT] [QUIET] [MODULE]
    2.   [REQUIRED] [[COMPONENTS] [components...]]
    3.   [OPTIONAL_COMPONENTS components...]
    4.   [NO_POLICY_SCOPE])

    几个重要的参数介绍:

    • PackageName:待查找包的名称。此外它还决定两种搜索模下的.cmake文件名称:例如模块模式下的名称为Find.cmake,而配置模式下为-config.cmake/-config-version.cmake
    • MODULE:该选项指定find_package命令只使用模块模式搜索方式查找。未指定该选项时,find_package会优先使用模块模式搜索,仍未找到包时,会切换成配置模式搜索。
    • version:待查找包的版本号要求,版本号为点分格式,由四个部分组成,每个部分都是一个数字,均为可选:major[.minor[.patch[.tweak]]],例如1.1.1.11.0、等。同样也可以指定版本范围(CMake 3.19及之后才支持),格式为:versionMin...[<]versionMaxversionMinversionMax均是major[.minor[.patch[.tweak]]]形式的版本号,默认情况下会包含这个指定区间两端的版本号,但如果指定了<,那么会排除掉versionMax,例如1.1.1.1...1.1.2.01.1.1.1...<1.1.2.0等。
    • EXACT:该选项要求待查找包的版本必须与指定的版本精确匹配,因此如果指定的是一个版本范围,不能使用该参数。
    • QUIET:禁止输出信息,正常情况当找到包时,CMake会打印一些信息,指定该选项时会禁止掉这些打印。例外是当同时指定QUIET时,如果找不到包,仍然会输出错误信息并终止执行过程。
    • REQUIRED:当未找到满足条件的包(例如版本号不匹配,或指定组件未找到等),会终止CMake的执行过程,并输出一条错误信息。如果未指定该选项,即使未找到满足条件的包,CMake的执行过程也会继续。
    • COMPONENTS:指定要查找的组件。通常一个包可能包含多个组件(可以理解为多个库,例如把C++的std看成一个包的概念,那么vector就是std下的其中一个组件),我们的工程可能会依赖包下的具体某个组件,因此可以通过这个选项来检测这些组件是否存在。通常的约定是,该选项后的组件应该都找到时才认为包找到,否则认为未找到满足条件的包。这个约束会依赖包的.cmake来实现,通过find_package命令传入的COMPONENTS可以通过_FIND_COMPONENTS这个变量来获得。举个简单的例子:
      1. # mymathConfig.cmake,假定它位于./mymath/mymath目录下
      2. # 作用就是校验COMPONENTS是否是test,只有当COMPONENTS为空或者为test时,包mymath才会被找到
      3. message(${mymath_FIND_COMPONENTS}) # `find_package`命令的`COMPONENTS`传入的
      4. if(${mymath_FIND_COMPONENTS} STREQUAL "")
      5. message("Empty comps.")
      6. set(mymath_INCLUDE_DIR "/XXX/mymath")
      7. set(mymath_LIBRARY "/XXX/mymath/libmymath.a")
      8. else()
      9. foreach(comp ${mymath_FIND_COMPONENTS})
      10. if (comp MATCHES "test")
      11. message("Find comp test")
      12. set(mymath_INCLUDE_DIR "/XXX/mymath")
      13. set(mymath_LIBRARY "/XXX/mymath/libmymath.a")
      14. endif()
      15. endforeach()
      16. endif()
      1. # 顶层目录的CMakeLists.txt
      2. cmake_minimum_required(VERSION 3.10.2)
      3. project(find_package_test)
      4. find_package(mymath
      5. CONFIG
      6. REQUIRED
      7. COMPONENTS test
      8. PATHS ./mymath/mymath
      9. )
      10. if(mymath_FOUND)
      11. message("Find mymath: ${mymath_INCLUDE_DIR}; ${mymath_LIBRARY};")
      12. endif()
      1. # 执行cmake .
      2. cmake .
      3. # 输出为
      4. test
      5. Find comp test
      6. Find mymath: /XXX/mymath; /XXX/mymath/libmymath.a;

    • OPTIONAL_COMPONENTS:与COMPONENTS的区别是,不强制要求这些组件必须存在。不影响CMake的执行。

    2.2 完整命令

    1. find_package(<PackageName> [version] [EXACT] [QUIET]
    2.   [REQUIRED] [[COMPONENTS] [components...]]
    3.   [OPTIONAL_COMPONENTS components...]
    4.   [CONFIG|NO_MODULE]
    5.   [NO_POLICY_SCOPE]
    6.   [NAMES name1 [name2 ...]]
    7.   [CONFIGS config1 [config2 ...]]
    8.   [HINTS path1 [path2 ... ]]
    9.   [PATHS path1 [path2 ... ]]
    10.   [PATH_SUFFIXES suffix1 [suffix2 ...]]
    11.   [NO_DEFAULT_PATH]
    12.   [NO_PACKAGE_ROOT_PATH]
    13.   [NO_CMAKE_PATH]
    14.   [NO_CMAKE_ENVIRONMENT_PATH]
    15.   [NO_SYSTEM_ENVIRONMENT_PATH]
    16.   [NO_CMAKE_PACKAGE_REGISTRY]
    17.   [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
    18.   [NO_CMAKE_SYSTEM_PATH]
    19.   [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
    20.   [CMAKE_FIND_ROOT_PATH_BOTH |
    21.   ONLY_CMAKE_FIND_ROOT_PATH |
    22.   NO_CMAKE_FIND_ROOT_PATH])

    这里介绍一下与基本命令有差异的地方:

    • CONFIG|NO_MODULE:这两个选项二选一即可,表示强制find_package命令使用配置模式搜索,忽略模块模式搜索。
    • NAMES:默认情况下find_package命令会查找名为的包。如果NAMES选项后指定了名称,则会使用这些名字来查找包而忽略参数。
    • PATHS/HINTS:配置模式下指定.cmake文件的搜索路径。
    • NO_XXX_PATH:配置模式下忽略指定的路径,具体的含义可以参考4.1.2节。



     

    Cmake命令之find_package介绍 - 简书

    Cmake中find_package命令的搜索模式之模块模式(Module mode) - 简书

     Cmake中find_package命令的搜索模式之配置模式(Config mode) - 简书

  • 相关阅读:
    JAVA 虚拟机的最常见选项配置
    网络相关知识——HTTP
    第二章 编译运行Android Wenet语音识别
    16.Xaml WrapPanel控件 ---> 流面板
    Python实现聚类分析和数据降维
    npm install node-sass 安装失败的解决方案:利用国内镜像加速安装
    C++学习day4
    C++ Qt 学习(九):模型视图代理
    C++中tuple数据结构使用
    星际争霸之小霸王之小蜜蜂(十二)--猫有九条命
  • 原文地址:https://blog.csdn.net/u013250861/article/details/127935779