CMake find_package

目录

Summary:

1. find_package的两种搜索模式

1.1 Module Mode

1.2 Config Mode

两种Mode的选择

2 两种Signature

2.1 Basi signature

2.2 full signature

2.3 Config Mode Search Procedure¶

2.4 Config Mode Version Selection


Summary

介绍cmake 的find_package指令的概念、用法以及相关周边概念。阅读官方文档(find_package — CMake 3.22.0-rc3 Documentation) 能得到较为全面的理解。本Blog结合官方文档以及遇到的现实case,进行叙述。
 

1. find_package的两种搜索模式

1.1 Module Mode



In this mode, CMake searches for a file called Find.cmake, looking first in the locations listed in the CMAKE_MODULE_PATH, then among the Find Modules provided by the CMake installation. If the file is found, it is read and processed by CMake. It is responsible for finding the package, checking the version, and producing any needed messages. Some Find modules provide limited or no support for versioning; check the Find module's documentation.

The Find.cmake file is not typically provided by the package itself. Rather, it is normally provided by something external to the package, such as the operating system, CMake itself, or even the project from which the find_package() command was called. Being externally provided, Find Modules tend to be heuristic in nature and are susceptible to becoming out-of-date. They typically search for certain libraries, files and other package artifacts.

Module mode is only supported by the basic command signature.


在该模式下, CMake会搜索名字为Find.cmake的文件。该文件一般会定义头文件路径、lib路径等。首先在CMAKE_MODULE_PATH 指定的路径下搜索, 然后会在安装CMake时的一些模块路径下搜索。

一般的package中并不会提供Find.cmake文件,一般是由pgakage的使用者自己写这个文件,这种情况下会存在.cmake文件和package不一致问题,例如package突然更新了。
该模式只能对应baseic command signature.
 

1.2 Config Mode

In this mode, CMake searches for a file called -config.cmake or Config.cmake. It will also look for -config-version.cmake or ConfigVersion.cmake if version details were specified (see Config Mode Version Selection for an explanation of how these separate version files are used).

In config mode, the command can be given a list of names to search for as package names. The locations where CMake searches for the config and version files is considerably more complicated than for Module mode (see Config Mode Search Procedure).

The config and version files are typically installed as part of the package, so they tend to be more reliable than Find modules. They usually contain direct knowledge of the package contents, so no searching or heuristics are needed within the config or version files themselves.

Config mode is supported by both the basic and full command signatures.

该模式下,CMake会搜索名字为 -config.cmake or Config.cmake的文件,如果指定了版本,还需要搜索-config-version.cmake or ConfigVersion.cmake文件。 搜索路径和搜索顺序后面的会单独讲解。

这种文件通常由package的发布者提供,很可靠。
 

该模式可以对应baseic/full command signature.

两种Mode的选择


The command arguments determine which of the above modes is used. When the basic signature is used, the command searches in Module mode first. If the package is not found, the search falls back to Config mode. A user may set the CMAKE_FIND_PACKAGE_PREFER_CONFIG variable to true to reverse the priority and direct CMake to search using Config mode first before falling back to Module mode. The basic signature can also be forced to use only Module mode with a MODULE keyword. If the full signature is used, the command only searches in Config mode.

Where possible, user code should generally look for packages using the basic signature, since that allows the package to be found with either mode. Project maintainers wishing to provide a config package should understand the bigger picture, as explained in Full Signature and all subsequent sections on this page.

例如,这3种情况下是Config模式:

  • find_package()中指定CONFIG关键字

  • find_package()中指定NO_MODULE关键字

  • find_package()中使用了不属于"basic signature"的关键字
     

2 两种Signature

2.1 Basi signature

find_package( [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [NO_POLICY_SCOPE])

The basic signature is supported by both Module and Config modes. The MODULE keyword implies that only Module mode can be used to find the package, with no fallback to Config mode.

Regardless of the mode used, a _FOUND variable will be set to indicate whether the package was found.

When the package is found, package-specific information may be provided through other variables and Imported Targets documented by the package itself.

QUIET:

The QUIET option disables informational messages, including those indicating that the package cannot be found if it is not REQUIRED.

REQUIRED:

The REQUIRED option stops processing with an error message if the package cannot be found.

COMPONENTS:

A package-specific list of required components may be listed after the COMPONENTS keyword. If any of these components are not able to be satisfied, the package overall is considered to be not found. If the REQUIRED option is also present, this is treated as a fatal error, otherwise execution still continues. As a form of shorthand, if the REQUIRED option is present, the COMPONENTS keyword can be omitted and the required components can be listed directly after REQUIRED.

OPTIONAL_COMPONENTS:
Additional optional components may be listed after OPTIONAL_COMPONENTS. If these cannot be satisfied, the package overall can still be considered found, as long as all required components are satisfied.

The set of available components and their meaning are defined by the target package. Formally, it is up to the target package how to interpret the component information given to it, but it should follow the expectations stated above. For calls where no components are specified, there is no single expected behavior and target packages should clearly define what occurs in such cases. Common arrangements include assuming it should find all components, no components or some well-defined subset of the available components.

version:

The [version] argument requests a version with which the package found should be compatible. There are two possible forms in which it may be specified:

  • A single version with the format major[.minor[.patch[.tweak]]], where each component is a numeric value.

  • A version range with the format versionMin...[<]versionMax where versionMin and versionMax have the same format and constraints on components being integers as the single version. By default, both end points are included. By specifying <, the upper end point will be excluded. Version ranges are only supported with CMake 3.19 or later.

The EXACT option requests that the version be matched exactly. This option is incompatible with the specification of a version range.

If no [version] and/or component list is given to a recursive invocation inside a find-module, the corresponding arguments are forwarded automatically from the outer call (including the EXACT flag for [version]). Version support is currently provided only on a package-by-package basis (see the Version Selection section below). When a version range is specified but the package is only designed to expect a single version, the package will ignore the upper end point of the range and only take the single version at the lower end of the range into account.

See the cmake_policy() command documentation for discussion of the NO_POLICY_SCOPE option.
 

2.2 full signature

find_package(<PackageName> [version] [EXACT] [QUIET]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [CONFIG|NO_MODULE]
             [NO_POLICY_SCOPE]
             [NAMES name1 [name2 ...]]
             [CONFIGS config1 [config2 ...]]
             [HINTS path1 [path2 ... ]]
             [PATHS path1 [path2 ... ]]
             [PATH_SUFFIXES suffix1 [suffix2 ...]]
             [NO_DEFAULT_PATH]
             [NO_PACKAGE_ROOT_PATH]
             [NO_CMAKE_PATH]
             [NO_CMAKE_ENVIRONMENT_PATH]
             [NO_SYSTEM_ENVIRONMENT_PATH]
             [NO_CMAKE_PACKAGE_REGISTRY]
             [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
             [NO_CMAKE_SYSTEM_PATH]
             [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
             [CMAKE_FIND_ROOT_PATH_BOTH |
              ONLY_CMAKE_FIND_ROOT_PATH |
              NO_CMAKE_FIND_ROOT_PATH])

The CONFIG option, the synonymous NO_MODULE option, or the use of options not specified in the basic signature all enforce pure Config mode. In pure Config mode, the command skips Module mode search and proceeds at once with Config mode search.

Config mode search attempts to locate a configuration file provided by the package to be found. A cache entry called _DIR is created to hold the directory containing the file. By default the command searches for a package with the name . If the NAMES option is given the names following it are used instead of .

The command searches for a file called Config.cmake or -config.cmake for each name specified. A replacement set of possible configuration file names may be given using the CONFIGS option.

The Config Mode Search Procedure is specified below. Once found, any version constraint is checked, and if satisfied, the configuration file is read and processed by CMake. Since the file is provided by the package it already knows the location of package contents. The full path to the configuration file is stored in the cmake variable _CONFIG.

All configuration files which have been considered by CMake while searching for the package with an appropriate version are stored in the _CONSIDERED_CONFIGS variable, and the associated versions in the _CONSIDERED_VERSIONS variable.

If the package configuration file cannot be found CMake will generate an error describing the problem unless the QUIET argument is specified.

If REQUIRED is specified and the package is not found a fatal error is generated and the configure step stops executing.

If _DIR has been set to a directory not containing a configuration file CMake will ignore it and search from scratch.

Package maintainers providing CMake package configuration files are encouraged to name and install them such that the Config Mode Search Procedure outlined below will find them without requiring use of additional options.

2.3 Config Mode Search Procedure¶

Note

When Config mode is used, this search procedure is applied regardless of whether the full or basic signature was given.

 The set of installation prefixes is constructed using the following steps. If NO_DEFAULT_PATH is specified all NO_* options are enabled.

搜索顺序:

1)New in version 3.12: Search paths specified in the _ROOT CMake variable and the _ROOT environment variable, where is the package to be found.
The package root variables are maintained as a stack so if called from within a find module, root paths from the parent's find module will also be searched after paths for the current package.

This can be skipped if NO_PACKAGE_ROOT_PATH is passed or by setting the CMAKE_FIND_USE_PACKAGE_ROOT_PATH to FALSE. See policy CMP0074.


2)Search paths specified in cmake-specific cache variables. These are intended to be used on the command line with a -DVAR=value. The values are interpreted as semicolon-separated lists.

This can be skipped if NO_CMAKE_PATH is passed or by setting the CMAKE_FIND_USE_CMAKE_PATH to FALSE:

  • CMAKE_PREFIX_PATH

  • CMAKE_FRAMEWORK_PATH

  • CMAKE_APPBUNDLE_PATH

3)Search paths specified in cmake-specific environment variables. These are intended to be set in the user's shell configuration, and therefore use the host's native path separator (; on Windows and : on UNIX). This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed or by setting the CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH to FALSE:

  • _DIR

  • CMAKE_PREFIX_PATH

  • CMAKE_FRAMEWORK_PATH

  • CMAKE_APPBUNDLE_PATH

4)...


2.4 Config Mode Version Selection

When the [version] argument is given, Config mode will only find a version of the package that claims compatibility with the requested version (see format specification). If the EXACT option is given, only a version of the package claiming an exact match of the requested version may be found. 
 

Ref:

find_package()的使用 - penuel - 博客园

你可能感兴趣的:(CMake,c++)