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

  前面有介绍过find_package的两种搜索模式之一模块模式(请参考Cmake命令之find_package介绍和模块模式),本文将介绍另外一种模式:配置模式。

一、配置模式下的.cmake文件

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

  同样的,当find_package调用返回时,一系列跟包相关的变量也会提供给调用者。例如_FOUND标识包是否找到、_DIR变量用于指示包配置文件所在的位置。实际上,返回的变量并没有特别的限制,但是还是建议遵循模块模式的标准变量名称的命名规则。

二、配置模式的配置文件生成

  一个配置文件方式提供的包由包配置文件(必须包含,名为-config.cmake文件或Config.cmake)和包版本文件(可选,名为-config-version.cmakeConfigVersion.cmake)组成。配置文件和版本文件的命名要配对出现,也就是:

-config.cmake
-config-version.cmake

或者是:

Config.cmake
ConfigVersion.cmake

  仍然是以我们自己编写的mymath库为例,假设mymath库提供了如下的文件:

/XXX/mymath/CMakeLists.txt # 生成libmymath.a的cmake配置
/XXX/mymath/mymath.h
/XXX/mymath/libmymath.a
/XXX/mymath/mymath/mymath/mymathConfig.cmake
/XXX/mymath/mymath/mymath/mymathConfigVersion.cmake

2.1 配置文件mymathConfig.cmake

  mymathConfig.cmake文件有两种方式可以生成:

  • CMakeinclude(CMakePackageConfigHelpers),用CMakePackageConfigHelpers提供的configure_package_config_file()来生成。
  • 直接通过set设置对应的变量,本文采用这种方式提供,如下:
# mymath/mymath/mymathConfig.cmake
set(mymath_INCLUDE_DIR "/XXX/mymath")
set(mymath_LIBRARY "/XXX/mymath/libmymath.a")

  可以参考Cmake命令之find_package介绍的4.1章节查看.cmake文件的搜索路径,我们的例子将在find_package中通过PATHS来指定。

2.2 版本文件mymathConfigVersion.cmake

  find_package找到一个配置文件后,会尝试去查找版本文件。版本文件的主要作用是用来验证包的版本是否与find_package命令中指定的版本信息匹配。如果匹配的话,就会使用配置文件中的内容,否则会忽略配置文件中的内容。

  和配置文件一样,版本文件也有两种方式生成:

  • CMakeinclude(CMakePackageConfigHelpers),用CMakePackageConfigHelpers提供的write_basic_package_version_file()来生成。我们的例子采用自动生成的方式,在mymath库生成的CMakeLists.txt中添加:
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  "${CMAKE_CURRENT_BINARY_DIR}/mymath/mymathConfigVersion.cmake"
  VERSION ${Inner_VERSION}
  COMPATIBILITY AnyNewerVersion
)
  • 自己手动写版本文件的校验规则。

  当find_package命令在加载版本文件时,首先会通过从find_package中得到的版本信息设置如下变量,用于版本文件中版本对比:

  • PACKAGE_FIND_NAME:包名
  • PACKAGE_FIND_VERSION:全版本字符串
  • PACKAGE_FIND_VERSION_MAJOR:主版本,默认值为0
  • PACKAGE_FIND_VERSION_MINOR:次版本,默认为0
  • PACKAGE_FIND_VERSION_PATCH:补丁版本,默认为0
  • PACKAGE_FIND_VERSION_TWEAK:小版本,默认为0

  在版本文件中可以使用上述变量来检查版本的兼容性、版本是否匹配,并设置如下变量作为返回结果:

  • PACKAGE_VERSION:全版本字符串
  • PACKAGE_VERSION_EXACT:版本是否精确匹配,True表示精确匹配
  • PACKAGE_VERSION_COMPATIBLE:版本是否兼容,True表示兼容
  • PACKAGE_VERSION_UNSUITABLE:版本是否合适,True表示不合适

  find_package会检查上述变量,如果版本匹配成功,那么find_package会返回如下变量给调用者:

  • _VERSION:包的全版本字符串
  • _VERSION_MAJOR:主版本
  • _VERSION_MINOR:此版本
  • _VERSION_PATCH:补丁版本
  • _VERSION_TWEAK:小版本
  • _VERSION_COUNT:点分版本组成的数量,范围0~4

2.3 生成自己的库

  mymath库的CMakeLists.txt内容如下:

# /XXX/mymath/CMakeLists.txt
cmake_minimum_required (VERSION 3.18)
project (mymath)

set(Inner_VERSION 1.2.3.4)
add_library (mymath mymath.cpp)
set_property(TARGET mymath PROPERTY VERSION ${Inner_VERSION})

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  "${CMAKE_CURRENT_BINARY_DIR}/mymath/mymathConfigVersion.cmake"
  VERSION ${Inner_VERSION}
  COMPATIBILITY AnyNewerVersion
)
// /XXX/mymath/mymath.cpp
#include "mymath.h"
#include 
namespace mymath {
    int add(int a, int b)
    {
        std::cout << "Add " << a << " and " << b << " is " << a + b << std::endl;
        return a + b;
    }
};
// /XXX/mymath/mymath.h
namespace mymath {
    int add(int a, int b);
};

  在命令行中执行cmake .make生成libmymath.a库。

三、完整的例子

  mymath库及其提供的.cmake配置文件见本文的第二章节。下面来编写测试文件:

// /XXX/test.cpp
#include "mymath.h"
int main(int argc, char** argv)
{
    mymath::add(1, 2);
    return 0;
}
# 顶层的CMakeLists.txt:/XXX/CMakeLists.txt
cmake_minimum_required(VERSION 3.10.2)
project(find_package_test)

find_package(mymath 1.2.3.2...1.2.4.0
    CONFIG
    PATHS ./mymath/mymath
)

if(mymath_FOUND)
    message("Find mymath: ${mymath_INCLUDE_DIR}; ${mymath_LIBRARY}")
    add_executable(test test.cpp)
    include_directories(${mymath_INCLUDE_DIR})
    target_link_libraries(test ${mymath_LIBRARY})
endif()

  在命令行中执行cmake .make生成test可执行文件并执行./test,对应的输出结果如下(摘取重要部分呈现):

# 命令行中执行 cmake .的打印
Find mymath: /XXX/mymath; /XXX/mymath/libmymath.a;

#命令行中执行make,得到可执行文件test,并执行test
./test
Add 1 and 2 is 3

你可能感兴趣的:(Cmake中find_package命令的搜索模式之配置模式(Config mode))