cmake-compile-features

package: cmake

title: cmake-compile-features(7)

summary: CMake Compile Features Reference

text:
# cmake-compile-features(7)

## NAME
cmake-compile-features - CMake Compile Features Reference

## INTRODUCTION
Project source code may depend on, or be conditional on, the availability of certain features of the compiler. There are three use-cases which arise: Compile Feature Requirements, Optional Compile Features and Conditional Compilation Options.

While features are typically specified in programming language standards, CMake provides a primary user interface based on granular handling of the features, not the language standard that introduced the feature.

The CMAKE_C_KNOWN_FEATURES <#prop_gbl:CMAKE_C_KNOWN_FEATURES>, CMAKE_CUDA_KNOWN_FEATURES <#prop_gbl:CMAKE_CUDA_KNOWN_FEATURES>, and CMAKE_CXX_KNOWN_FEATURES <#prop_gbl:CMAKE_CXX_KNOWN_FEATURES> global properties contain all the features known to CMake, regardless of compiler support for the feature. The CMAKE_C_COMPILE_FEATURES <#variable:CMAKE_C_COMPILE_FEATURES>, CMAKE_CUDA_COMPILE_FEATURES <#variable:CMAKE_CUDA_COMPILE_FEATURES> , and CMAKE_CXX_COMPILE_FEATURES <#variable:CMAKE_CXX_COMPILE_FEATURES> variables contain all features CMake knows are known to the compiler, regardless of language standard or compile flags needed to use them.

Features known to CMake are named mostly following the same convention as the Clang feature test macros. There are some exceptions, such as CMake using cxx_final and cxx_override instead of the single cxx_override_control used by Clang.

Note that there are no separate compile features properties or variables for the OBJC or OBJCXX languages. These are based off C or C++ respectively, so the properties and variables for their corresponding base language should be used instead.

## COMPILE FEATURE REQUIREMENTS
Compile feature requirements may be specified with the target_compile_features() <#command:target_compile_features> command. For example, if a target must be compiled with compiler support for the cxx_constexpr <#prop_gbl:CMAKE_CXX_KNOWN_FEATURES> feature:

```
add_library(mylib requires_constexpr.cpp)
target_compile_features(mylib PRIVATE cxx_constexpr)
```

In processing the requirement for the cxx_constexpr feature, cmake(1) <#manual:cmake(1)> will ensure that the in-use C++ compiler is capable of the feature, and will add any necessary flags such as -std=gnu++11 to the compile lines of C++ files in the mylib target. A FATAL_ERROR is issued if the compiler is not capable of the feature.

The exact compile flags and language standard are deliberately not part of the user interface for this use-case. CMake will compute the appropriate compile flags to use by considering the features specified for each target.

Such compile flags are added even if the compiler supports the particular feature without the flag. For example, the GNU compiler supports variadic templates (with a warning) even if -std=gnu++98 is used. CMake adds the -std=gnu++11 flag if cxx_variadic_templates is specified as a requirement.

In the above example, mylib requires cxx_constexpr when it is built itself, but consumers of mylib are not required to use a compiler which supports cxx_constexpr. If the interface of mylib does require the cxx_constexpr feature (or any other known feature), that may be specified with the PUBLIC or INTERFACE signatures of target_compile_features() <#command:target_compile_features>:

```
add_library(mylib requires_constexpr.cpp)
# cxx_constexpr is a usage-requirement
target_compile_features(mylib PUBLIC cxx_constexpr)
# main.cpp will be compiled with -std=gnu++11 on GNU for cxx_constexpr.
add_executable(myexe main.cpp)
target_link_libraries(myexe mylib)
```

Feature requirements are evaluated transitively by consuming the link implementation. See cmake-buildsystem(7) <#manual:cmake-buildsystem(7)> for more on transitive behavior of build properties and usage requirements.

### Requiring Language Standards
In projects that use a large number of commonly available features from a particular language standard (e.g. C++ 11) one may specify a meta-feature (e.g. cxx_std_11) that requires use of a compiler mode that is at minimum aware of that standard, but could be greater. This is simpler than specifying all the features individually, but does not guarantee the existence of any particular feature. Diagnosis of use of unsupported features will be delayed until compile time.

For example, if C++ 11 features are used extensively in a project's header files, then clients must use a compiler mode that is no less than C++ 11. This can be requested with the code:

```
target_compile_features(mylib PUBLIC cxx_std_11)
```

In this example, CMake will ensure the compiler is invoked in a mode of at-least C++ 11 (or C++ 14, C++ 17, ...), adding flags such as -std=gnu++11 if necessary. This applies to sources within mylib as well as any dependents (that may include headers from mylib).

Note:

If the compiler's default standard level is at least that of the requested feature, CMake may omit the -std= flag. The flag may still be added if the compiler's default extensions mode does not match the <LANG>_EXTENSIONS <#prop_tgt:<LANG>_EXTENSIONS> target property, or if the <LANG>_STANDARD <#prop_tgt:<LANG>_STANDARD> target property is set.

### Availability of Compiler Extensions
The <LANG>_EXTENSIONS <#prop_tgt:<LANG>_EXTENSIONS> target property defaults to the compiler's default (see CMAKE_<LANG>_EXTENSIONS_DEFAULT <#variable:CMAKE_<LANG>_EXTENSIONS_DEFAULT>). Note that because most compilers enable extensions by default, this may expose portability bugs in user code or in the headers of third-party dependencies.

<LANG>_EXTENSIONS <#prop_tgt:<LANG>_EXTENSIONS> used to default to ON. See CMP0128 <#policy:CMP0128>.

## OPTIONAL COMPILE FEATURES
Compile features may be preferred if available, without creating a hard requirement. This can be achieved by not specifying features with target_compile_features() <#command:target_compile_features> and instead checking the compiler capabilities with preprocessor conditions in project code.

In this use-case, the project may wish to establish a particular language standard if available from the compiler, and use preprocessor conditions to detect the features actually available. A language standard may be established by Requiring Language Standards using target_compile_features() <#command:target_compile_features> with meta-features like cxx_std_11, or by setting the CXX_STANDARD <#prop_tgt:CXX_STANDARD> target property or CMAKE_CXX_STANDARD <#variable:CMAKE_CXX_STANDARD> variable.

See also policy CMP0120 <#policy:CMP0120> and legacy documentation on Example Usage <#wcdh-example-usage> of the deprecated WriteCompilerDetectionHeader <#module:WriteCompilerDetectionHeader> module.

## CONDITIONAL COMPILATION OPTIONS
Libraries may provide entirely different header files depending on requested compiler features.

For example, a header at with_variadics/interface.h may contain:

```
template<int I, int... Is>
struct Interface;
template<int I>
struct Interface<I>
{

  static int accumulate()

  {

    return I;

  }
};
template<int I, int... Is>
struct Interface
{

  static int accumulate()

  {

    return I + Interface<Is...>::accumulate();

  }
};
```

while a header at no_variadics/interface.h may contain:

```
template<int I1, int I2 = 0, int I3 = 0, int I4 = 0>
struct Interface
{

  static int accumulate() { return I1 + I2 + I3 + I4; }
};
```

It may be possible to write an abstraction interface.h header containing something like:

```
#ifdef HAVE_CXX_VARIADIC_TEMPLATES
#include "with_variadics/interface.h"
#else
#include "no_variadics/interface.h"
#endif
```

However this could be unmaintainable if there are many files to abstract. What is needed is to use alternative include directories depending on the compiler capabilities.

CMake provides a COMPILE_FEATURES generator expression <#manual:cmake-generator-expressions(7)> to implement such conditions. This may be used with the build-property commands such as target_include_directories() <#command:target_include_directories> and target_link_libraries() <#command:target_link_libraries> to set the appropriate buildsystem <#manual:cmake-buildsystem(7)> properties:

```
add_library(foo INTERFACE)
set(with_variadics ${CMAKE_CURRENT_SOURCE_DIR}/with_variadics)
set(no_variadics ${CMAKE_CURRENT_SOURCE_DIR}/no_variadics)
target_include_directories(foo

  INTERFACE

    "$<$<COMPILE_FEATURES:cxx_variadic_templates>:${with_variadics}>"

    "$<$<NOT:$<COMPILE_FEATURES:cxx_variadic_templates>>:${no_variadics}>"

  )
```

Consuming code then simply links to the foo target as usual and uses the feature-appropriate include directory

```
add_executable(consumer_with consumer_with.cpp)
target_link_libraries(consumer_with foo)
set_property(TARGET consumer_with CXX_STANDARD 11)
add_executable(consumer_no consumer_no.cpp)
target_link_libraries(consumer_no foo)
```

## SUPPORTED COMPILERS
CMake is currently aware of the C++ standards <#prop_tgt:CXX_STANDARD> and compile features <#prop_gbl:CMAKE_CXX_KNOWN_FEATURES> available from the following compiler ids <#variable:CMAKE_<LANG>_COMPILER_ID> as of the versions specified for each:

- AppleClang: Apple Clang for Xcode versions 4.4+.

- Clang: Clang compiler versions 2.9+.

- GNU: GNU compiler versions 4.4+.

- MSVC: Microsoft Visual Studio versions 2010+.

- SunPro: Oracle SolarisStudio versions 12.4+.

- Intel: Intel compiler versions 12.1+.

CMake is currently aware of the C standards <#prop_tgt:C_STANDARD> and compile features <#prop_gbl:CMAKE_C_KNOWN_FEATURES> available from the following compiler ids <#variable:CMAKE_<LANG>_COMPILER_ID> as of the versions specified for each:

- all compilers and versions listed above for C++.

- GNU: GNU compiler versions 3.4+

CMake is currently aware of the C++ standards <#prop_tgt:CXX_STANDARD> and their associated meta-features (e.g. cxx_std_11) available from the following compiler ids <#variable:CMAKE_<LANG>_COMPILER_ID> as of the versions specified for each:

- Cray: Cray Compiler Environment version 8.1+.

- Fujitsu: Fujitsu HPC compiler 4.0+.

- PGI: PGI version 12.10+.

- NVHPC: NVIDIA HPC compilers version 11.0+.

- TI: Texas Instruments compiler.

- TIClang: Texas Instruments Clang-based compilers.

- XL: IBM XL version 10.1+.

CMake is currently aware of the C standards <#prop_tgt:C_STANDARD> and their associated meta-features (e.g. c_std_99) available from the following compiler ids <#variable:CMAKE_<LANG>_COMPILER_ID> as of the versions specified for each:

•

all compilers and versions listed above with only meta-features for C++.

CMake is currently aware of the CUDA standards <#prop_tgt:CUDA_STANDARD> and their associated meta-features (e.g. cuda_std_11) available from the following compiler ids <#variable:CMAKE_<LANG>_COMPILER_ID> as of the versions specified for each:

- Clang: Clang compiler 5.0+.

- NVIDIA: NVIDIA nvcc compiler 7.5+.

## LANGUAGE STANDARD FLAGS
In order to satisfy requirements specified by the target_compile_features() <#command:target_compile_features> command or the CMAKE_<LANG>_STANDARD <#variable:CMAKE_<LANG>_STANDARD> variable, CMake may pass a language standard flag to the compiler, such as -std=c++11.

For Visual Studio Generators <#visual-studio-generators>, CMake cannot precisely control the placement of the language standard flag on the compiler command line. For Ninja Generators <#ninja-generators>, Makefile Generators <#makefile-generators>, and Xcode <#generator:Xcode>, CMake places the language standard flag just after the language-wide flags from CMAKE_<LANG>_FLAGS <#variable:CMAKE_<LANG>_FLAGS> and CMAKE_<LANG>_FLAGS_<CONFIG> <#variable:CMAKE_<LANG>_FLAGS_<CONFIG>>.

Changed in version 3.26: The language standard flag is placed before flags specified by other abstractions such as the target_compile_options() <#command:target_compile_options> command. Prior to CMake 3.26, the language standard flag was placed after them.

## Copyright
2000-2026 Kitware, Inc. and Contributors

branch: sisyphus


cmake-configure-log

title: cmake-configure-log(7)

summary: CMake Configure Log

text:
# cmake-configure-log(7)

## NAME
cmake-configure-log - CMake Configure Log

Added in version 3.26.

## INTRODUCTION
CMake writes a running log, known as the configure log, of certain events that occur during the Configure step. The configure log does not contain a log of all output, errors, or messages printed while configuring a project. It is a log of detailed information about specific events, such as toolchain inspection by try_compile() <#command:try_compile>, meant for use in debugging the configuration of a build tree.

For human use, this version of CMake writes the configure log to the file:

```
${CMAKE_BINARY_DIR}/CMakeFiles/CMakeConfigureLog.yaml
```

However, the location and name of the log file may change in future versions of CMake. Tools that read the configure log should get its location using a configureLog <#file-api-configurelog> query to the cmake-file-api(7) <#manual:cmake-file-api(7)>. See the Log Versioning section below for details.

## LOG STRUCTURE
The configure log is designed to be both machine- and human-readable.

The log file is a YAML document stream containing zero or more YAML documents separated by document markers. Each document begins with a --- document marker line, contains a single YAML mapping that logs events from one CMake "configure" step, and, if the configure step finished normally, ends with a ... document marker line:

```
---
events:

  -

    kind: "try_compile-v1"

    # (other fields omitted)

  -

    kind: "try_compile-v1"

    # (other fields omitted)
...
```

A new document is appended to the log every time CMake configures the build tree and logs new events.

The keys of each document root mapping are:

events

A YAML block sequence of nodes corresponding to events logged during one CMake "configure" step. Each event is a YAML node containing one of the Event Kinds documented below.

### Log Versioning
Each of the Event Kinds is versioned independently. The set of keys an event's log entry provides is specific to its major version. When an event is logged, the latest version of its event kind that is known to the running version of CMake is always written to the log.

Tools reading the configure log must ignore event kinds and versions they do not understand:

- A future version of CMake may introduce a new event kind or version.

- If an existing build tree is re-configured with a different version of CMake, the log may contain different versions of the same event kind.

- If cmake-file-api(7) <#manual:cmake-file-api(7)> queries request one or more configureLog <#file-api-configurelog> object versions, the log may contain multiple entries for the same event, each with a different version of its event kind.

IDEs should write a cmake-file-api(7) <#manual:cmake-file-api(7)> query requesting a specific configureLog <#file-api-configurelog> object version, before running CMake, and then read the configure log only as described by the file-api reply.

### Text Block Encoding
In order to make the log human-readable, text blocks are always represented using YAML literal block scalars (|). Since literal block scalars do not support escaping, backslashes and non-printable characters are encoded at the application layer:

- \\ encodes a backslash.

- \xXX encodes a byte using two hexadecimal digits, XX.

## EVENT KINDS
Every event kind is represented by a YAML mapping of the form:

```
kind: "<kind>-v<major>"
backtrace:

  - "<file>:<line> (<function>)"
checks:

  - "Checking for something"
#...event-specific keys...
```

The keys common to all events are:

kind

A string identifying the event kind and major version.

backtrace

A YAML block sequence reporting the call stack of CMake source locations at which the event occurred, from most-recent to least-recent. Each node is a string specifying one location formatted as <file>:<line> (<function>).

checks

An optional key that is present when the event occurred with at least one pending message(CHECK_START) <#command:message>. Its value is a YAML block sequence reporting the stack of pending checks, from most-recent to least-recent. Each node is a string containing a pending check message.

Additional mapping keys are specific to each (versioned) event kind, described below.

### Event Kind message
The message(CONFIGURE_LOG) <#command:message> command logs message events.

There is only one message event major version, version 1.

### message-v1 Event
A message-v1 event is a YAML mapping:

```
kind: "message-v1"
backtrace:

  - "CMakeLists.txt:123 (message)"
checks:

  - "Checking for something"
message: |

  # ...
```

The keys specific to message-v1 mappings are:

message

A YAML literal block scalar containing the message text, represented using our Text Block Encoding.

### Event Kind try_compile
The try_compile() <#command:try_compile> command logs try_compile events.

There is only one try_compile event major version, version 1.

### try_compile-v1 Event
A try_compile-v1 event is a YAML mapping:

```
kind: "try_compile-v1"
backtrace:

  - "CMakeLists.txt:123 (try_compile)"
checks:

  - "Checking for something"
description: "Explicit LOG_DESCRIPTION"
directories:

  source: "/path/to/.../TryCompile-01234"

  binary: "/path/to/.../TryCompile-01234"
cmakeVariables:

  SOME_VARIABLE: "Some Value"
buildResult:

  variable: "COMPILE_RESULT"

  cached: true

  stdout: |

    # ...

  exitCode: 0
```

The keys specific to try_compile-v1 mappings are:

description

An optional key that is present when the LOG_DESCRIPTION <text> option was used. Its value is a string containing the description <text>.

directories

A mapping describing the directories associated with the compilation attempt. It has the following keys:

source

String specifying the source directory of the try_compile() <#command:try_compile> project.

binary

String specifying the binary directory of the try_compile() <#command:try_compile> project. For non-project invocations, this is often the same as the source directory.

cmakeVariables

An optional key that is present when CMake propagates variables into the test project, either automatically or due to the CMAKE_TRY_COMPILE_PLATFORM_VARIABLES <#variable:CMAKE_TRY_COMPILE_PLATFORM_VARIABLES> variable. Its value is a mapping from variable names to their values.

buildResult

A mapping describing the result of compiling the test code. It has the following keys:

variable

A string specifying the name of the CMake variable storing the result of trying to build the test project.

cached

A boolean indicating whether the above result variable is stored in the CMake cache.

stdout

A YAML literal block scalar containing the output from building the test project, represented using our Text Block Encoding. This contains build output from both stdout and stderr.

exitCode

An integer specifying the build tool exit code from trying to build the test project.

### Event Kind try_run
The try_run() <#command:try_run> command logs try_run events.

There is only one try_run event major version, version 1.

### try_run-v1 Event
A try_run-v1 event is a YAML mapping:

```
kind: "try_run-v1"
backtrace:

  - "CMakeLists.txt:456 (try_run)"
checks:

  - "Checking for something"
description: "Explicit LOG_DESCRIPTION"
directories:

  source: "/path/to/.../TryCompile-56789"

  binary: "/path/to/.../TryCompile-56789"
buildResult:

  variable: "COMPILE_RESULT"

  cached: true

  stdout: |

    # ...

  exitCode: 0
runResult:

  variable: "RUN_RESULT"

  cached: true

  stdout: |

    # ...

  stderr: |

    # ...

  exitCode: 0
```

The keys specific to try_run-v1 mappings include those documented by the try_compile-v1 event, plus:

runResult

A mapping describing the result of running the test code. It has the following keys:

variable

A string specifying the name of the CMake variable storing the result of trying to run the test executable.

cached

A boolean indicating whether the above result variable is stored in the CMake cache.

stdout

An optional key that is present when the test project built successfully. Its value is a YAML literal block scalar containing output from running the test executable, represented using our Text Block Encoding. If RUN_OUTPUT_VARIABLE was used, stdout and stderr are captured together, so this will contain both. Otherwise, this will contain only the stdout output.

stderr

An optional key that is present when the test project built successfully and the RUN_OUTPUT_VARIABLE option was not used. Its value is a YAML literal block scalar containing output from running the test executable, represented using our Text Block Encoding. If RUN_OUTPUT_VARIABLE was used, stdout and stderr are captured together in the stdout key, and this key will not be present. Otherwise, this will contain the stderr output.

exitCode

An optional key that is present when the test project built successfully. Its value is an integer specifying the exit code, or a string containing an error message, from trying to run the test executable.

### Event Kind find
The find_file() <#command:find_file>, find_path() <#command:find_path>, find_library() <#command:find_library>, and find_program() <#command:find_program> commands log find events.

There is only one find event major version, version 1.

### find-v1 Event
Added in version 4.1.

A find-v1 event is a YAML mapping:

```
kind: "find-v1"
backtrace:

  - "CMakeLists.txt:456 (find_program)"
mode: "program"
variable: "PROGRAM_PATH"
description: "Docstring for variable"
settings:

  SearchFramework: "NEVER"

  SearchAppBundle: "NEVER"

  CMAKE_FIND_USE_CMAKE_PATH: true

  CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: true

  CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: true

  CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: true

  CMAKE_FIND_USE_INSTALL_PREFIX: true
names:

  - "name1"

  - "name2"
candidate_directories:

  - "/path/to/search"

  - "/other/path/to/search"

  - "/path/to/found"

  - "/further/path/to/search"
searched_directories:

  - "/path/to/search"

  - "/other/path/to/search"
found: "/path/to/found/program"
```

The keys specific to find-v1 mappings are:

mode

A string describing the command using the search performed. One of file, path, program, or library.

variable

The variable to which the search stored its result.

description

The documentation string of the variable.

settings

Search settings active for the search.

SearchFramework

A string describing how framework search is performed. One of FIRST, LAST, ONLY, or NEVER. See CMAKE_FIND_FRAMEWORK <#variable:CMAKE_FIND_FRAMEWORK>.

SearchAppBundle

A string describing how application bundle search is performed. One of FIRST, LAST, ONLY, or NEVER. See CMAKE_FIND_APPBUNDLE <#variable:CMAKE_FIND_APPBUNDLE>.

CMAKE_FIND_USE_CMAKE_PATH

A boolean indicating whether or not CMake-specific cache variables are used when searching. See CMAKE_FIND_USE_CMAKE_PATH <#variable:CMAKE_FIND_USE_CMAKE_PATH>.

CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH

A boolean indicating whether or not CMake-specific environment variables are used when searching. See CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH <#variable:CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH>.

CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH

A boolean indicating whether or not platform-specific environment variables are used when searching. See CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH <#variable:CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH>.

CMAKE_FIND_USE_CMAKE_SYSTEM_PATH

A boolean indicating whether or not platform-specific CMake variables are used when searching. See CMAKE_FIND_USE_CMAKE_SYSTEM_PATH <#variable:CMAKE_FIND_USE_CMAKE_SYSTEM_PATH>.

CMAKE_FIND_USE_INSTALL_PREFIX

A boolean indicating whether or not the install prefix is used when searching. See CMAKE_FIND_USE_INSTALL_PREFIX <#variable:CMAKE_FIND_USE_INSTALL_PREFIX>.

names

The names to look for the queries.

candidate_directories

Candidate directories, in order, to look in during the search.

searched_directories

Directories, in order, looked at during the search process.

found

Either a string representing the found value or false if it was not found.

search_context

A mapping of variable names to search paths specified by them (either a string or an array of strings depending on the variable). Environment variables are wrapped with ENV{ and }, otherwise CMake variables are used. Only variables with any paths specified are used.

package_stack

An array of objects with paths which come from the stack of paths made available by find_package() <#command:find_package> calls.

package_paths

The paths made available by find_package() <#command:find_package> commands in the call stack.

### Event Kind find_package
Added in version 4.1.

The find_package() <#command:find_package> command logs find_package events.

There is only one find_package event major version, version 1.

### find_package-v1 Event
A find_package-v1 event is a YAML mapping:

```
kind: "find_package-v1"
backtrace:

  - "CMakeLists.txt:456 (find_program)"
name: "PackageName"
components:

  -

    name: "Component"

    required: true

    found: true
configs:

  -

    filename: PackageNameConfig.cmake

    kind: "cmake"

  -

    filename: packagename-config.cmake

    kind: "cmake"
version_request:

  version: "1.0"

  version_complete: "1.0...1.5"

  min: "INCLUDE"

  max: "INCLUDE"

  exact: false
settings:

  required: "optional"

  quiet: false

  global: false

  policy_scope: true

  bypass_provider: false

  hints:

    - "/hint/path"

  names:

    - "name1"

    - "name2"

  search_paths:

    - "/search/path"

  path_suffixes:

    - ""

    - "suffix"

  registry_view: "HOST"

  paths:

    CMAKE_FIND_USE_CMAKE_PATH: true

    CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: true

    CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: true

    CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: true

    CMAKE_FIND_USE_INSTALL_PREFIX: true

    CMAKE_FIND_USE_PACKAGE_ROOT_PATH: true

    CMAKE_FIND_USE_CMAKE_PACKAGE_REGISTRY: true

    CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY: true

    CMAKE_FIND_ROOT_PATH_MODE: "BOTH"

  candidates:

    -

      path: "/path/to/config/PackageName/PackageNameConfig.cmake"

      mode: "config"

      reason: "insufficient_version"

    -

      path: "/path/to/config/PackageName/packagename-config.cmake"

      mode: "config"

      reason: "no_exist"

  found:

    path: "/path/to/config/PackageName-2.5/PackageNameConfig.cmake"

    mode: "config"

    version: "2.5"
```

The keys specific to find_package-v1 mappings are:

name

The name of the requested package.

components

If present, an array of objects containing the fields:

name

The name of the component.

required

A boolean indicating whether the component is required or optional.

found

A boolean indicating whether the component was found or not.

configs

If present, an array of objects indicating the configuration files to search for.

filename

The filename of the configuration file.

kind

The kind of file. Either cmake or cps.

version_request

An object indicating the version constraints on the search.

version

The minimum version required.

version_complete

The user-provided version range.

min

Whether to INCLUDE or EXCLUDE the lower bound on the version range.

max

Whether to INCLUDE or EXCLUDE the upper bound on the version range.

exact

A boolean indicating whether an EXACT version match was requested.

settings

Search settings active for the search.

required

The requirement request of the search. One of optional, optional_explicit, required_explicit, required_from_package_variable, or required_from_find_variable.

quiet

A boolean indicating whether the search is QUIET or not.

global

A boolean indicating whether the GLOBAL keyword has been provided or not.

policy_scope

A boolean indicating whether the NO_POLICY_SCOPE keyword has been provided or not.

bypass_provider

A boolean indicating whether the BYPASS_PROVIDER keyword has been provided or not.

hints

An array of paths provided as HINTS.

names

An array of package names to use when searching, provided by NAMES.

search_paths

An array of paths to search, provided by PATHS.

path_suffixes

An array of suffixes to use when searching, provided by PATH_SUFFIXES.

registry_view

The REGISTRY_VIEW requested for the search.

paths

Path settings active for the search.

CMAKE_FIND_USE_CMAKE_PATH

A boolean indicating whether or not CMake-specific cache variables are used when searching. See CMAKE_FIND_USE_CMAKE_PATH <#variable:CMAKE_FIND_USE_CMAKE_PATH>.

CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH

A boolean indicating whether or not CMake-specific environment variables are used when searching. See CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH <#variable:CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH>.

CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH

A boolean indicating whether or not platform-specific environment variables are used when searching. See CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH <#variable:CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH>.

CMAKE_FIND_USE_CMAKE_SYSTEM_PATH

A boolean indicating whether or not platform-specific CMake variables are used when searching. See CMAKE_FIND_USE_CMAKE_SYSTEM_PATH <#variable:CMAKE_FIND_USE_CMAKE_SYSTEM_PATH>.

CMAKE_FIND_USE_INSTALL_PREFIX

A boolean indicating whether or not the install prefix is used when searching. See CMAKE_FIND_USE_INSTALL_PREFIX <#variable:CMAKE_FIND_USE_INSTALL_PREFIX>.

CMAKE_FIND_USE_CMAKE_PACKAGE_REGISTRY

A boolean indicating whether or not to search the CMake package registry for the package. See CMAKE_FIND_USE_PACKAGE_REGISTRY <#variable:CMAKE_FIND_USE_PACKAGE_REGISTRY>.

CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY

A boolean indicating whether or not to search the system CMake package registry for the package. See CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY <#variable:CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY>.

CMAKE_FIND_ROOT_PATH_MODE

A string indicating the root path mode in effect as selected by the CMAKE_FIND_ROOT_PATH_BOTH, ONLY_CMAKE_FIND_ROOT_PATH, and NO_CMAKE_FIND_ROOT_PATH arguments.

candidates

An array of rejected candidate paths. Each element contains the following keys:

path

The path to the considered file. In the case of a dependency provider, the value is in the form of dependency_provider::<COMMAND_NAME>.

mode

The mode which found the file. One of module, cps, cmake, or provider.

reason

The reason the path was rejected. One of insufficient_version, no_exist, ignored, no_config_file, or not_found.

message

If present, a string describing why the package is considered as not found.

found

If the package has been found, information on the found file. If it is not found, this is null. Keys available:

path

The path to the module or configuration that found the package. In the case of a dependency provider, the value is in the form of dependency_provider::<COMMAND_NAME>.

mode

The mode that considered the path. One of module, cps, cmake, or provider.

version

The reported version of the package.

search_context

A mapping of variable names to search paths specified by them (either a string or an array of strings depending on the variable). Environment variables are wrapped with ENV{ and }, otherwise CMake variables are used. Only variables with any paths specified are used.

package_stack

An array of objects with paths which come from the stack of paths made available by find_package() <#command:find_package> calls.

package_paths

The paths made available by find_package() <#command:find_package> commands in the call stack.

## Copyright
2000-2026 Kitware, Inc. and Contributors


cmake-cxxmodules

title: cmake-cxxmodules(7)

summary: CMake C++ Modules Support Reference

text:
# cmake-cxxmodules(7)

## NAME
cmake-cxxmodules - CMake C++ Modules Support Reference

Added in version 3.28.

C++ 20 introduced the concept of "modules" to the language. The design requires build systems to order compilations to satisfy import statements reliably. CMake's implementation asks the compiler to scan source files for module dependencies during the build, collates scanning results to infer ordering constraints, and tells the build tool how to dynamically update the build graph.

## COMPILATION STRATEGY
With C++ modules, compiling a set of C++ sources is no longer embarrassingly parallel. That is, any given source may require the compilation of another source file first in order to provide a "BMI" (or "CMI") that C++ compilers use to satisfy import statements in other sources. With included headers, sources could share their declarations so that any consumers could compile independently. With modules, the compiler now generates BMI files during compilation based on the contents of the source file and its export statements. This means that, to ensure a correct build without having to regenerate the build graph (by running configure and generate steps) for every source change, the correct ordering must be determined from the source files during the build phase.

Build systems must be able to order these compilations within the build graph. There are multiple strategies that are suitable for this, but each has advantages and disadvantages. CMake uses a "scanning" step strategy, which is the most visible modules-related change for CMake users in the context of the build. CMake provides multiple ways to control the scanning behavior of source files.

## SCANNING CONTROL
Whether or not sources get scanned for C++ module usage is dependent on the following queries. The first query that provides a decision of whether to scan or not is used.

- If the source file belongs to a file set of type CXX_MODULES, it will be scanned.

- If the target does not use at least C++ 20, it will not be scanned.

- If the source file is not the language CXX, it will not be scanned.

- If the CXX_SCAN_FOR_MODULES <#prop_sf:CXX_SCAN_FOR_MODULES> source file property is set, its value will be used.

- If the CXX_SCAN_FOR_MODULES <#prop_tgt:CXX_SCAN_FOR_MODULES> target property is set, its value will be used. Set the CMAKE_CXX_SCAN_FOR_MODULES <#variable:CMAKE_CXX_SCAN_FOR_MODULES> variable to initialize this property on all targets as they are created.

- Otherwise, the source file will be scanned if the compiler and generator support scanning. See policy CMP0155 <#policy:CMP0155>.

Note that any scanned source will be excluded from any unity build (see UNITY_BUILD <#prop_tgt:UNITY_BUILD>) because module-related statements can only happen at one place within a C++ translation unit.

## COMPILER SUPPORT
The list of compilers for which CMake supports scanning sources for C++ modules includes:

- MSVC toolset 14.34 and newer (provided with Visual Studio 17.4 and newer)

- LLVM/Clang 16.0 and newer

- GCC 14 and newer

## IMPORT STD SUPPORT
Support for import std is limited to the following toolchain and standard library combinations:

- Clang 18.1.2 and newer with standard library libc++ or libstdc++

- MSVC toolset 14.36 and newer (provided with Visual Studio 17.6 and newer)

- GCC 15 and newer Note:

Ubuntu prior to 26.04 ships broken libstdc++.modules.json files. See Ubuntu issue 2141579 <https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2141579>.

The CMAKE_CXX_COMPILER_IMPORT_STD <#variable:CMAKE_CXX_COMPILER_IMPORT_STD> variable lists standard levels which have support for import std in the active C++ toolchain.

Additionally, only the Ninja Generators <#ninja-generators> currently support import std at this time because Visual Studio Generators <#visual-studio-generators> do not support building BMIs for IMPORTED targets.

Note:

This support is provided only when experimental support for import std has been enabled by the CMAKE_EXPERIMENTAL_CXX_IMPORT_STD gate.

## GENERATOR SUPPORT
The list of generators which support scanning sources for C++ modules includes:

- Ninja <#generator:Ninja>

- Ninja Multi-Config <#generator:Ninja Multi-Config>

- Visual Studio 17 2022 <#generator:Visual Studio 17 2022>

- Visual Studio 18 2026 <#generator:Visual Studio 18 2026>

Note that the Ninja Generators <#ninja-generators> require ninja 1.11 or newer.

### Limitations
There are a number of known limitations of the current C++ module support in CMake. Known limitations or bugs in compilers are not listed here, as these can change over time.

For all generators:

•

Header units are not supported.

For the Visual Studio Generators <#visual-studio-generators>:

- Only Visual Studio 2022 and MSVC toolsets 14.34 (Visual Studio 17.4) and newer are supported.

- Exporting or installing BMI or module information is not supported.

- Compiling BMIs from IMPORTED targets with C++ modules (including import std) is not supported.

- Use of modules provided by PRIVATE sources from PUBLIC module sources is not diagnosed.

Separately, as a design choice, CMake does not express configuration-agnostic module maps for imported targets. The IMPORTED_CXX_MODULES_<CONFIG> <#prop_tgt:IMPORTED_CXX_MODULES_<CONFIG>> target property is always tied to a specific configuration. This can lead to some friction when importing/exporting targets from/to configuration-unaware build systems. Future work will alleviate this restriction.

## USAGE

### Troubleshooting CMake
This section aims to answer common questions about CMake's implementation and to help diagnose or explain errors in CMake's C++ modules support.

### File Extension Support
CMake imposes no requirements upon file extensions for modules of any unit type. While there are preferences that differ between toolchains (e.g., .ixx on MSVC and .cppm on Clang), there is no universally agreed-upon extension. As such, CMake only requires that the file be recognized as a CXX-language source file. By default, any recognized extension will suffice, but the LANGUAGE <#prop_sf:LANGUAGE> property may be used with any other extension as well.

### File Name Requirements
The name of a module has no relation to the name or path of the file in which its declaration resides. The C++ standard has no requirements here and neither does CMake. However, it may be useful to have some pattern in use within a project for easier navigation within environments that lack IDE-like "find symbol" functionality (e.g., on code review platforms).

### Scanning Without Modules
A common problem for projects that have not yet adopted modules is unnecessary scanning of sources. This typically happens when a C++20 project becomes aware of CMake 3.28, or a 3.28-aware project starts using C++20. Either case ends up setting CMP0155 <#policy:CMP0155> to NEW, which enables scanning of C++ sources with C++20 or newer by default. The easiest way for projects to turn this off is to add:

```
set(CMAKE_CXX_SCAN_FOR_MODULES 0)
```

near the top of their top-level CMakeLists.txt file. Note that it should not be in the cache, as it may otherwise affect projects using it via FetchContent. Attention should also be paid to vendored projects which may want to enable scanning for their own sources, as this would change the default for them as well.

### Debugging Module Builds
This section aims to help diagnose or explain common errors that may arise on the build side of CMake's C++ modules support.

### Import Cycles
The C++ standard does not allow for cycles in the import graph of a translation unit; therefore, CMake does not either. Currently, CMake will leave it to the build tool to detect this based on the dynamic dependencies used to order module compilations. CMake Issue 26119 <https://gitlab.kitware.com/cmake/cmake/-/issues/26119> tracks the desire to improve the user experience in this case.

### Internal Module Partition Extension
When the implementation of building C++ modules was first investigated, it appeared as though there existed a type of translation unit that represented the intersection of a partition unit and an implementation unit. Initial CMake designs included specific support for these translation units; however, after a closer reading of the standard, these did not actually exist. These units would have had module M:part; as their module declaration statement. The problem is that this is also the exact syntax also used for declaring module partitions that do not contribute to the external interface of the primary module. Only MSVC supports this distinction. Other compilers do not and will treat such files as an internal partition unit and CMake will raise an error that a module-providing C++ source must be in a FILE_SET of type CXX_MODULES.

The fix is to not use the extension, as it provides no further expressivity over not using the extension. All implementation unit source files should instead only use module M; as their module declaration statement regardless of what partition the defined entities are declared within. As an example:

```
// module-interface.cpp
export module M;
export int foo();
// module-impl.cpp
module M:part; // module M:part; looks like an internal partition
int foo() { return 42; }
```

Instead use explicit interface/implementation separation:

```
// module-interface.cpp
export module M;
export int foo();
// module-impl.cpp
module M;
int foo() { return 42; }
```

### Module Visibility
CMake enforces module visibility between and within targets. This essentially means that a module (say, I) provided from a PRIVATE FILE_SET on a target T may not be imported by:

- other targets depending on T; or

- modules provided from a PUBLIC FILE_SET on target T itself.

This is because, in general, all imported entities from a module must also be importable by all potential importers of that module. Even if module I is only used within parts of a module without the export keyword, it may affect things within it in such a way that consumers of the module need to be able to transitively import it to work correctly. As CMake uses the module visibility to determine whether to install module interface units, a PRIVATE module interface unit will not be installed, meaning that usage of any installed module which imports I would not work.

Instead, import PRIVATE C++ modules only from within an implementation unit, as these are not exposed to consumers of any module.

## DESIGN
The design of CMake's C++ module support makes a number of trade-offs compared to other designs. First, CMake's chosen design will be covered. Later sections cover alternative designs that were not chosen for CMake's implementation.

Overall, the designs fall somewhere along two axes:

Explicit Dynamic

Explicit Static

Explicit Fixed

Implicit Dynamic

Implicit Static

Implicit Fixed

- Explicit builds control which modules are visible to each translation unit directly. For example, when compiling a source requiring a module M, the compiler will be given information which states the exact BMI file to use when importing the M module.

- Implicit builds can control module visibility as well, but do so by instead grouping BMIs into directories which are then searched for files to satisfy import statements in the source file.

- Static builds use a static set of build commands in order to complete the build. There must be support to add edges between nodes at build time.

- Dynamic builds may create new build commands during the build and schedule any discovered work during the build.

- Fixed builds are generated with all module dependencies already known.

### Design Goals
CMake's implementation of building C++ modules focuses on the following design goals:

1.

Correct Builds

2.

Deterministic Builds

3.

Support Generated Sources

4.

Static Communication

5.

Minimize Regeneration

### Correct Builds
Above all else, an incorrect build is a frustrating experience for all involved. A build which does not detect errors and instead lets a build with detectable problems run to completion is a good way to start wild goose chase debugging sessions. CMake errs on the side of avoiding such situations.

### Deterministic Builds
Given an on-disk state of a build, it should be possible to determine what steps will happen next. This does not mean that the exact order of rules within the build that can be run concurrently is deterministic, but instead that the set of work to be done and its results are deterministic. For example, if there is no dependency between tasks A and B, A should have no effects on the execution of B and vice versa.

### Support Generated Sources
Code generation is prevalent in the C++ ecosystem, so only supporting modules in files whose content is known at configure time is not suitable. Without supporting generated sources which use or provide modules, code generation tools are effectively cut off from the use of modules, and any dependencies of generated sources must also provide non-modular ways of using their interfaces (i.e., provide headers). Given that all C++ implementations use strong module ownership for symbol mangling, this is problematic when such interfaces end up referring to compiled symbols in other libraries.

### Static Communication
All communication between different steps of the build should be handled statically. Given the build tools that CMake supports, it is challenging to establish a controlled lifetime for a companion tool that needs to interact during compilation. Neither make nor ninja offer a way to start a tool at the beginning of a build and ensure it is stopped at the end. Instead, communication with compilers is managed through input and output files, using dependencies in the build tool to keep everything up-to-date. This approach enables standard debugging strategies for builds and allows developers to run build commands directly when investigating issues, without needing to account for other tools running in the background.

### Minimize Regeneration
Active development of a build with modules should not require the build graph to be regenerated on every change. This means that the module dependencies must be constructed after the build graph is available. Without this, a correct build would need to regenerate the build graph any time a module-aware source file is edited, as any changes may alter module dependencies.

It also means that all module-aware sources must be known at configure time (even if they do not yet exist) so that the build graph can include the commands to scan for their dependencies.

Note:

There is a known issue with ninja which can result in an erroneous detection of a dependency cycle when the dependency order between two sources reverses (i.e., a importing b becomes b importing a) between two builds. See ninja issue 2666 <https://github.com/ninja-build/ninja/issues/2666> for details.

### Use Case Considerations
The design goals described above constrain the implementation. Additionally, mixed configurations are supported by CMake via multi-config generators such as Ninja Multi-Config <#generator:Ninja Multi-Config> and Visual Studio Generators <#visual-studio-generators>. This section describes how CMake addresses these constraints.

### Selected Design
The general strategy CMake uses is to "scan" sources to extract the ordering dependency information and update the build graph with new edges between existing edges. This is done by taking the per-source scan results (represented by P1689R5 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html> files) and then "collating" them for each target with information from its dependencies. The primary task of the collator is to generate "module map" files to pass to each compile rule with the paths to the BMIs needed to satisfy import statements, and to inform the build tool of dependencies needed to satisfy those import statements during the compilation. The collator also uses the build-time information to generate install rules for the module interface units, their BMIs, and properties for any exported targets with C++ modules. It also enforces that PRIVATE modules may not be used by other targets or by any PUBLIC module interface unit within the target.

### Implementation Details
Warning:

The implementation details are not a stable interface. Each version of CMake may revise them without any attempt at providing compatibility. External toolchain maintainers are responsible for updating their implementations for each version of CMake they support.

This section describes how CMake actually structures the build graph, the data passed between various parts, and the files which contain that data. It is intended to be used both as functional documentation and as a guide to help those debugging a module build to understand where to locate various bits of data.

Note:

This section documents internal implementation details that may be useful for toolchain file <#manual:cmake-toolchains(7)> authors or during debugging of a module-related issue. Projects should not need to inspect or modify any of the variables, properties, files, or targets mentioned here.

### Toolchain (scanning)
Compilers which support modules must also provide a scanning tool. This will usually be either the compiler itself with some extra flags or a tool shipped with the compiler. The command template for scanning is stored in the CMAKE_CXX_SCANDEP_SOURCE variable. The command is expected to write P1689R5 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html> results to the <DYNDEP_FILE> placeholder. Additionally, the command should provide any discovered dependencies to the <DEP_FILE> placeholder. This allows build tools to rerun the scan if any of the dependencies of the scanning command change.

Additionally, toolchains should set the following variables:

- CMAKE_CXX_MODULE_MAP_FORMAT: The format of the module map describing where dependent BMI files for imported modules exist during compilation. Must be one of gcc, clang, or msvc.

- CMAKE_CXX_MODULE_MAP_FLAG: The arguments used to inform the compiler of the module map file. It should use the <MODULE_MAP_FILE> placeholder.

- CMAKE_CXX_COMPILE_BMI: The command template to compile a BMI file from a module interface unit. Used when CMAKE_CXX_MODULE_BMI_ONLY_FLAG is not completely additive to an object compilation template.

- CMAKE_CXX_MODULE_BMI_ONLY_FLAG: The arguments used to compile only a BMI file from a module interface unit. This is used when consuming modules from external projects to compile BMI files for use within the current build.

If a toolchain does not provide the CMAKE_CXX_COMPILE_BMI or CMAKE_CXX_MODULE_BMI_ONLY_FLAG variables, it will not be able to consume modules provided by IMPORTED targets.

### Configure
During the configure step, CMake needs to track which sources care about modules at all. See Scanning Control for how each source determines whether it cares about modules or not. CMake tracks these in its internal target representation structure (cmTarget). The set of sources which need to be scanned may be modified using the target_sources() <#command:target_sources>, target_compile_features() <#command:target_compile_features>, and set_property() <#command:set_property> commands.

Additionally, targets may use the CXX_MODULE_STD <#prop_tgt:CXX_MODULE_STD> target property to indicate that import std is desired within the target's sources.

### Generate
During generation, CMake needs to add additional rules to ensure that the sources providing modules can be built before sources that import those modules. Since CMake uses a static build, the build graph must contain all possible commands for scanning and module generation. The dependency edges between commands to ensure that modules are provided will then ensure that the build graph executes correctly. This means that, while all sources may get scanned, only modules that are actually used will be generated.

The first step CMake performs is to generate a synthetic target for each unique usage of a module-providing target. These targets are based on other targets, but provide only BMI files for other targets rather than object files. This is because the compatibility of BMI files is extremely narrow and cannot be shared between arbitrary import instances. Due to the internal workings of toolchains, there can generally only be a single set of settings for a variety of flags for any one compilation, including BMI files for imported modules. As an example, the C++ standard in use needs to be consistent across all modules, but there are many settings which may cause incompatibilities.

Note:

CMake currently assumes that all usages are compatible and will only create one set of BMIs for each target. This may cause build failures where multiple BMI files are required, but CMake only provides one set. See CMake Issue 25916 <https://gitlab.kitware.com/cmake/cmake/-/issues/25916> for progress on removing this assumption.

Once all of the synthetic targets are created, CMake looks at each target that has any source that might use C++ modules and creates a command to scan each of them. This command will output a P1689R5 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html>-formatted file describing the C++ modules it uses and provides (if any). It will also create a command to collate module dependencies for the eligible compilations. This command depends on the scan results of all eligible sources, information about the target itself, as well as the collate results of any dependent targets which provide C++ modules. The collate step uses a target-specific CXXDependInfo.json file which contains the following information:

- compiler-*: basic compiler information (id, frontend-variant, and simulate-id) which is used to generate correctly formatted paths when generating paths for the compiler

- cxx-modules: a map of object files to the FILE_SET information, which is used to enforce module visibility and generate install rules for module interface unit sources

- module-dir: where to place BMI files for this target

- dir-{cur,top}-{src,bld}: the source (src) and build (bld) directories for the current directory (cur) and the top (top) of the project, used to compute accurate relative paths for the build tool dynamic dependencies

- exports: The list of exports which both contain the target and are providing C++ module information, used to provide accurate module properties on IMPORTED targets from the exported targets.

- bmi-installation: installation information, used to generate install scripts for BMI files

- database-info: information required to generate build database information if requested by EXPORT_BUILD_DATABASE <#prop_tgt:EXPORT_BUILD_DATABASE>

- sources: list of other source files in the target, used to add to the build database if requested

- config: the configuration for the target, used to set the appropriate properties in generated export files

- language: the language (e.g., C++ or Fortran) the collation metadata file is describing

- include-dirs and forward-modules-from-target-dirs: unused for C++

Each entry in the cxx-modules map records the following:

- bmi-only (bool): True if only the BMI, not the source of the BMI, is available

- compile-features (list[string]): cmake-compile-features(7) <#manual:cmake-compile-features(7)> used to build the object

- compile-options (list[string]): compilation options/flags used to build the object, except for those derived from compile-features

- definitions (list[string]): preprocessor defines used to build the object

- destination (string): intended install destination of the source file

- include-directories (list[string]): include directories used to build the object

- name (string): name of the file set which owns the source file

- relative-directory (string): base path relative to which the source file will be relocated into the install destination

- source (string): path to the source file

- type (string): type of the file set which owns the source file

- visibility (string): visibility of the file set which owns the source file

For each compilation, CMake will also provide a module map which will be created during the build by the collate command. How this is provided to the compiler is specified by the CMAKE_CXX_MODULE_MAP_FORMAT and CMAKE_CXX_MODULE_MAP_FLAG toolchain variables.

### Scan
The compiler is expected to implement the scan command. This is because only the compiler itself can reliably answer preprocessor predicates like __has_builtin in order to provide accurate module usage information in the face of arbitrary flags that may be used when compiling sources.

CMake names these files with the .ddi extension, which stands for "dynamic dependency information". These files are in P1689R5 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html> format and are used by the collate command to perform its tasks.

### Collate
The collate command performs the bulk of the work to make C++ modules work within the build graph. It consumes the following files as input:

- CXXDependInfo.json from the generate step

- .ddi files from the scanning results of the target's sources

- CXXModules.json files output from eligible dependent targets' collate commands

It uses the information from these files to generate:

- CXX.dd files to inform the build tool of dependencies that exist between the compilation of a source and the BMI files of the modules that it imports

- CXXModules.json files for use in collate commands of depending targets

- *.modmap files for each compilation to find BMI files for imported modules

- install-cxx-module-bmi-$<CONFIG>.cmake scripts for the installation of any BMI files (included by the install scripts)

- target-*-$<CONFIG>.cmake export files for any exports of the target to provide the IMPORTED_CXX_MODULES_<CONFIG> <#prop_tgt:IMPORTED_CXX_MODULES_<CONFIG>> properties

- CXX_build_database.json build database files for the target when the its EXPORT_BUILD_DATABASE <#prop_tgt:EXPORT_BUILD_DATABASE> property is set

During its processing, it enforces the following guarantees:

- BMI usage is consistent

- module visibility is respected

C++ modules have the rule that only a single module of a given name may exist within a program. This is not exactly enforceable with the existence of private modules, but it is enforceable for public modules. The enforcement is done by the collate command. Part of the CXXModules.json files is the set of modules that are transitively imported by each module it provides. When a module is then imported, the collate command ensures that all modules with a given name agree upon a given BMI file to provide that module.

### Compile
Compilation uses the module map file generated by the collate command to find imported modules during compilation. Because CMake only provides the locations of modules that are discovered by the scan command, any modules missed by it will not be provided to the compilation.

It is possible for toolchains to reject the BMI file that CMake provides to a compilation as incompatible. This is because CMake assumes that all usages are compatible at the moment. See CMake Issue 25916 <https://gitlab.kitware.com/cmake/cmake/-/issues/25916> for progress on removing this assumption.

### Install
During installation, install scripts which have been written by the collate command during the build are included so that any BMI files are installed as needed. These need to be generated, as it is not known what the BMI file names will be during CMake's generation (because CMake names the BMI files after the module name itself). These install scripts are included with the OPTIONAL keyword, so an incomplete build may result in an incomplete installation as well.

### Alternative Designs
There are alternative designs that CMake does not implement. This section aims to give a brief overview and to explain why they were not chosen for CMake's implementation.

### Implicit Builds
An implicit build performs module builds using compile-time search paths to make the implementation of the build simpler. This is certainly something that can be made to work. However, CMake's goals exclude it as a solution.

When a build uses search directory management, the compiler is directed to place module output files into a specified directory. These directories are then provided as search paths to any compilation allowed to use the modules within them.

This strategy risks running into problems with the Correct Builds goal. This stems from the hazard of stale files being present in the search directories. Since the build system is unaware of the actual files being written, it is difficult to know which files are allowed to be deleted (e.g., using ninja -t cleandead to remove outputs ninja has encountered but are no longer generated). Removal of intermediate files may also cause the build to become stuck if the outputs are not known to the build system beyond consumers reporting "usage of file X".

There is also a need to at least do some level of ordering of BMI generation commands which share an output directory. Separate directories may be used to order groups of modules (e.g., one directory per target); otherwise, modules within the same directory may not assume that other modules writing to the shared directory will complete first. If module paths are grouped accurately according to the module dependency graph, it is a small step to being an explicit build where the files are directly specified.

### Static Scanning
A fixed build performs a scan while generating the build graph and includes the necessary dependencies up-front. In CMake's case, it would look at the source files during the generate phase and add the dependencies directly to the build graph. This is more likely to be suitable for a build system that is also its own build tool where build graph manipulation can be done cooperatively.

No matter whether it is integrated or not, this strategy necessitates either a suitable C++ parser to extract the information in the first place, or toolchain cooperation to obtain it. While module dependency information is available to a simpler C++ parser, dependencies may be hidden behind preprocessor conditionals that need to be understood in order to be accurate. Of course, choosing to not support preprocessor conditionals around import statements is also an option, but this may severely limit external library support.

For CMake, this strategy would mean that any change to a module-aware source file may need to trigger regeneration of the build graph. A benign edit would at least need to trigger the check for changed imports, but may skip actually regenerating if it is unchanged. This may be less critical for a build system which is also its own build tool, but it is a direct violation of the Minimize Regeneration goal.

Additionally, CMake's Support Generated Sources goal would be unsupportable with this strategy. CMake could defer scanning until the generated files are available, but those sources cannot be compiled until such a scan has been performed. This would mean that there would be some unbounded (but finite) number of regenerations of the build graph as sources become available.

### Module Mapping Service
Another strategy is to run a service alongside the build that can act as an oracle for where to place and discover modules. The compiler is instructed to query the service with questions such as "this source is exporting module X" and "this source is importing module Y" and receive the path to either create or find the BMI, respectively. In this case, the service dynamically implements the collation logic.

Of particular note, this conflicts with the Deterministic Builds and Static Communication goals because the on-disk state may not match the actual state, and coordinating the lifetime of the build tool itself with the service is difficult. The primary missing feature is some signal when a build session starts and ends so that such a service can know in what context it is answering requests. There also needs to be a way to resume a session and detect when a session is invalidated. No build tool that CMake supports today has such features.

There are also hazards which conflict with the Correct Builds goal. When a module is imported, the compiler waits for a response before continuing. However, there is no guarantee that a (visible) module of that name even exists, so it may wait indefinitely. While waiting for a compilation to report that it creates that module, it may run into a dependency cycle which leaves the compilations hanging until some resource limit is reached (probably time, or that all possible providers of the module have not reported a module of that name). While these compilations are waiting on answers, there is the question of how they affect the parallelism limits of the build tool in use. Do compilations waiting on an answer count towards the limit and block other compilations from launching to potentially discover the module? If they do not, what about other resources that may be held in use by those compilations (e.g., memory or available file descriptors)?

## POSSIBLE FUTURE ENHANCEMENTS
This section documents possible future enhancements to CMake's support of C++ modules. Nothing here is a guarantee of future implementation, and the ordering is arbitrary.

### Batch Scanning
It is possible to scan all sources within a target at once, which should be faster when sources share transitive includes. This does have side effects for incremental builds, as the update of any source in the target means that all sources in the target are scanned again. Given how much faster scanning can be, it should be negligible to do such "extra" scanning assuming that unchanged results do not trigger recompilations.

### BMI Modification Optimization
Currently, as with object files, compilers always update a BMI file even if the contents have not changed. Because modules increase the potential scope of "non-changes" to cause (conceptually) unnecessary recompilation, it might be useful to avoid recompilation of module consumers if the BMI file has not changed. This might be achieved by wrapping the compilation to juggle the BMI through a cmake -E copy_if_different pass with ninja's restat = 1 feature to avoid recompiling importers if the BMI file doesn't actually change.

### Easier Source Specification
The initial implementation of CMake's module support had used the "just list sources; CMake will figure it out" pattern. However, this ran into issues related to other metadata requirements. These were discovered while implementing CMake support beyond just building the modules-using code.

Conflicts with Separate BMI Generation on a single target, as that requires knowledge of all BMI-generating rules at generate time.

### Separate BMI Generation
CMake currently uses a single rule to generate both the BMI and the object file for a compilation. At least Clang supports compiling an object directly from the BMI. This would be beneficial because BMI generation is typically faster than compilation and generating the BMI as a separate step allows importers to start compiling without waiting for the object to also be generated.

This is not supported in the current implementation as only Clang supports generating an object directly from the BMI. Other compilers either do not support such a two-phase generation (GCC) or need to start object compilation from the source again.

Conflicts with Easier Source Specification on a single target because CMake must know all BMI-generating sources at generate time rather than build time to create the two-phase rules.

## MODULE COMPILATION GLOSSARY
BMI

Built Module Interface. A compiler-generated binary representation of a C++ module's interface that is required by consumers of the module. File extensions vary by compiler.

CMI

Compiled Module Interface. Alternative name for BMI used by some compilers.

build database

A JSON file containing compilation commands, module dependencies, and grouping information. Used for IDE integration and build analysis.

build system

A tool that facilitates the building of software which includes a model of how components of the build relate to each other. For example, CMake, Meson, build2, and more.

build tool

A build graph execution tool. For example, ninja and make. Some build tools are also their own build system.

C++ module

A C++20 language feature for describing the API of a piece of software. Intended as a replacement for headers for this purpose.

collate

The process of aggregating module information from scanned sources to ensure correct compilation order and to provide metadata for other parts of the build (e.g., installation or a build database).

discovered dependencies

Dependencies found during the processing of a command that do not need to be explicitly declared.

dynamic dependencies

Dependencies which require a separate command to detect so that a further command may have its dependencies satisfied.

embarrassingly parallel

A set of tasks which, due to having minimal dependencies between them, can be easily divided into many independent tasks that can be executed concurrently.

explicit build

A build strategy where module dependencies are explicitly specified rather than discovered.

fixed build

A build strategy where all module dependencies are computed and inserted directly into the build graph.

header unit

A header file which is used via an import statement rather than an #include preprocessor directive. Implementations may provide support for treating #include as import as well.

implementation unit

A C++ translation unit that implements module entities declared in a module interface unit.

implicit build

A build strategy where module dependencies are discovered by searching for BMI files during compilation.

internal partition unit

A translation unit which contains a partition name and is not exported from the primary module interface unit.

module interface unit

A translation unit that declares a module's public interface using export module. Such a unit may or may not be also be a partition unit.

module map

A compiler-specific file mapping module names to BMI locations.

module visibility

CMake's enforcement of access rules for modules based on their declaration scope (PUBLIC/PRIVATE).

ODR

One Definition Rule. The C++ requirement that any entity be defined exactly once per program.

partition unit

A translation unit which describes a module with a partition name (i.e., module MODNAME:PARTITION;). The partition may or may not use the export keyword. If it does, it is also a module interface unit; otherwise, it is a internal partition unit.

primary module interface unit

A module interface unit which exports a named module that is not a partition unit.

scan

The process of analyzing a translation unit to discover module imports and exports.

static build

A build configuration where all compilation rules are determined at generate time.

strong module ownership

C++ implementations have settled on a model where the module "owns" the symbols declared within it. In practice, this means that the module name is included into the symbol mangling of entities declared within it.

synthetic target

A CMake-generated build target used to supply BMIs to a specific user of a module-providing target.

translation unit

The smallest component of a compilation for a C++ program. Generally, there is one translation unit per source file. C++ source files which do not use C++ modules may be combined into a single translation unit.

## Copyright
2000-2026 Kitware, Inc. and Contributors


cmake-developer

title: cmake-developer(7)

summary: CMake Developer Reference

text:
# cmake-developer(7)

## NAME
cmake-developer - CMake Developer Reference

## INTRODUCTION
This manual is intended for reference by developers working with cmake-language(7) <#manual:cmake-language(7)> code, whether writing their own modules, authoring their own build systems, or working on CMake itself.

See <https://cmake.org/get-involved/> to get involved in development of CMake upstream. It includes links to contribution instructions, which in turn link to developer guides for CMake itself.

## ACCESSING WINDOWS REGISTRY
CMake offers some facilities to access the registry on Windows platforms.

### Query Windows Registry
Added in version 3.24.

The cmake_host_system_information() <#command:cmake_host_system_information> command offers the possibility to query the registry on the local computer. See the cmake_host_system_information(QUERY WINDOWS_REGISTRY) <#query-windows-registry> sub-command for more information.

### Find Using Windows Registry
Changed in version 3.24.

Options HINTS and PATHS of find_file() <#command:find_file>, find_library() <#command:find_library>, find_path() <#command:find_path>, find_program() <#command:find_program>, and find_package() <#command:find_package> commands offer the possibility, on Windows platform, to query the registry.

The formal syntax, as specified using BNF <https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form> notation with the regular extensions, for registry query is the following:

```
registry_query  ::= '[' sep_definition? root_key

                    ((key_separator sub_key)? (value_separator value_name_)?)? ']'
sep_definition  ::= '{' value_separator '}'
root_key        ::= 'HKLM' | 'HKEY_LOCAL_MACHINE' | 'HKCU' | 'HKEY_CURRENT_USER' |

                    'HKCR' | 'HKEY_CLASSES_ROOT' | 'HKCC' | 'HKEY_CURRENT_CONFIG' |

                    'HKU' | 'HKEY_USERS'
sub_key         ::= element (key_separator element)*
key_separator   ::= '/' | '\\'
value_separator ::= element | ';'
value_name      ::= element | '(default)'
element         ::= character\+
character       ::= <any character except key_separator and value_separator>
```

The sep_definition optional item offers the possibility to specify the string used to separate the sub_key from the value_name item. If not specified, the character ; is used. Multiple registry_query items can be specified as part of a path.

```
# example using default separator
find_file(... PATHS "/root/[HKLM/Stuff;InstallDir]/lib[HKLM\\\\Stuff;Architecture]")
# example using different specified separators
find_library(... HINTS "/root/[{|}HKCU/Stuff|InstallDir]/lib[{@@}HKCU\\\\Stuff@@Architecture]")
```

If the value_name item is not specified or has the special name (default), the content of the default value, if any, will be returned. The supported types for the value_name are:

- REG_SZ.

- REG_EXPAND_SZ. The returned data is expanded.

- REG_DWORD.

- REG_QWORD.

When the registry query failed, typically because the key does not exist or the data type is not supported, the string /REGISTRY-NOTFOUND is substituted to the [] query expression.

## FIND MODULES
A "find module" is a Find<PackageName>.cmake file to be loaded by the find_package() <#command:find_package> command when invoked for <PackageName>.

The primary task of a find module is to determine whether a package is available, set the <PackageName>_FOUND variable to reflect this and provide any variables, macros and imported targets required to use the package. A find module is useful in cases where an upstream library does not provide a config file package <#config-file-packages>.

The traditional approach is to use variables for everything, including libraries and executables: see the Standard Variable Names section below. This is what most of the existing find modules provided by CMake do.

The more modern approach is to behave as much like config file packages <#config-file-packages> files as possible, by providing imported target <#imported-targets>. This has the advantage of propagating usage requirements <#target-usage-requirements> to consumers.

In either case (or even when providing both variables and imported targets), find modules should provide backwards compatibility with old versions that had the same name.

A FindFoo.cmake module will typically be loaded by the command:

```
find_package(Foo [major[.minor[.patch[.tweak]]]]

             [EXACT] [QUIET] [REQUIRED]

             [[COMPONENTS] [components...]]

             [OPTIONAL_COMPONENTS components...]

             [NO_POLICY_SCOPE])
```

See the find_package() <#command:find_package> documentation for details on what variables are set for the find module. Most of these are dealt with by using FindPackageHandleStandardArgs <#module:FindPackageHandleStandardArgs>.

Briefly, the module should only locate versions of the package compatible with the requested version, as described by the Foo_FIND_VERSION family of variables. If Foo_FIND_QUIETLY is set to true, it should avoid printing messages, including anything complaining about the package not being found. If Foo_FIND_REQUIRED is set to true, the module should issue a FATAL_ERROR if the package cannot be found. If neither are set to true, it should print a non-fatal message if it cannot find the package.

Packages that find multiple semi-independent parts (like bundles of libraries) should search for the components listed in Foo_FIND_COMPONENTS if it is set , and only set Foo_FOUND to true if for each searched-for component <c> that was not found, Foo_FIND_REQUIRED_<c> is not set to true. The HANDLE_COMPONENTS argument of find_package_handle_standard_args() <#command:find_package_handle_standard_args> can be used to implement this.

If Foo_FIND_COMPONENTS is not set, which modules are searched for and required is up to the find module, but should be documented.

For internal implementation, it is a generally accepted convention that variables starting with underscore are for temporary use only.

### Standard Variable Names
For a FindXxx.cmake module that takes the approach of setting variables (either instead of or in addition to creating imported targets), the following variable names should be used to keep things consistent between Find modules. Note that all variables start with Xxx_, which (unless otherwise noted) must match exactly the name of the FindXxx.cmake file, including upper/lowercase. This prefix on the variable names ensures that they do not conflict with variables of other Find modules. The same pattern should also be followed for any macros, functions and imported targets defined by the Find module.

Xxx_INCLUDE_DIRS

The final set of include directories listed in one variable for use by client code. This should not be a cache entry (note that this also means this variable should not be used as the result variable of a find_path() <#command:find_path> command - see Xxx_INCLUDE_DIR below for that).

Xxx_LIBRARIES

The libraries to use with the module. These may be CMake targets, full absolute paths to a library binary or the name of a library that the linker must find in its search path. This should not be a cache entry (note that this also means this variable should not be used as the result variable of a find_library() <#command:find_library> command - see Xxx_LIBRARY below for that).

Xxx_DEFINITIONS

The compile definitions to use when compiling code that uses the module. This really shouldn't include options such as -DHAS_JPEG that a client source-code file uses to decide whether to #include <jpeg.h>

Xxx_EXECUTABLE

The full absolute path to an executable. In this case, Xxx might not be the name of the module, it might be the name of the tool (usually converted to all uppercase), assuming that tool has such a well-known name that it is unlikely that another tool with the same name exists. It would be appropriate to use this as the result variable of a find_program() <#command:find_program> command.

Xxx_YYY_EXECUTABLE

Similar to Xxx_EXECUTABLE except here the Xxx is always the module name and YYY is the tool name (again, usually fully uppercase). Prefer this form if the tool name is not very widely known or has the potential to clash with another tool. For greater consistency, also prefer this form if the module provides more than one executable.

Xxx_LIBRARY_DIRS

Optionally, the final set of library directories listed in one variable for use by client code. This should not be a cache entry.

Xxx_ROOT_DIR

The base directory of the installation of Xxx that can be optionally set by the find module if Xxx is found. This is useful for large packages where many files need to be referenced relative to a common base (or root) directory. Not to be confused with the Xxx_ROOT hint variable set from the outside for the find module to know where to look for the Xxx.

Xxx_VERSION_VV

Variables of this form specify whether the Xxx module being provided is version VV of the module. There should not be more than one variable of this form set to true for a given module. For example, a module Barry might have evolved over many years and gone through a number of different major versions. Version 3 of the Barry module might set the variable Barry_VERSION_3 to true, whereas an older version of the module might set Barry_VERSION_2 to true instead. It would be an error for both Barry_VERSION_3 and Barry_VERSION_2 to both be set to true.

Xxx_WRAP_YY

When a variable of this form is set to false, it indicates that the relevant wrapping command should not be used. The wrapping command depends on the module, it may be implied by the module name or it might be specified by the YY part of the variable.

Xxx_Yy_FOUND

For variables of this form, Yy is the name of a component for the module. It should match exactly one of the valid component names that may be passed to the find_package() <#command:find_package> command for the module. If a variable of this form is set to false, it means that the Yy component of module Xxx was not found or is not available. Variables of this form would typically be used for optional components so that the caller can check whether an optional component is available.

Xxx_FOUND

When the find_package() <#command:find_package> command returns to the caller, this variable will be set to true if the module was deemed to have been found successfully.

Xxx_NOT_FOUND_MESSAGE

Should be set by config-files in the case that it has set Xxx_FOUND to FALSE. The contained message will be printed by the find_package() <#command:find_package> command and by find_package_handle_standard_args() <#command:find_package_handle_standard_args> to inform the user about the problem. Use this instead of calling message() <#command:message> directly to report a reason for failing to find the module or package.

Xxx_RUNTIME_LIBRARY_DIRS

Optionally, the runtime library search path for use when running an executable linked to shared libraries. The list should be used by user code to create the PATH on windows or LD_LIBRARY_PATH on UNIX. This should not be a cache entry.

Xxx_VERSION

The full version string of the package found, if any. Note that some existing modules may also provide Xxx_VERSION_STRING, as it was traditionally used before the current naming convention.

Xxx_VERSION_MAJOR

The major version of the package found, if any.

Xxx_VERSION_MINOR

The minor version of the package found, if any.

Xxx_VERSION_PATCH

The patch version of the package found, if any.

The following names should not usually be used in CMakeLists.txt files. They are intended for use by Find modules to specify and cache the locations of specific files or directories. Users are typically able to set and edit these variables to control the behavior of Find modules (like entering the path to a library manually):

Xxx_LIBRARY

The path of the library. Use this form only when the module provides a single library. It is appropriate to use this as the result variable in a find_library() <#command:find_library> command.

Xxx_Yy_LIBRARY

The path of library Yy provided by the module Xxx. Use this form when the module provides more than one library or where other modules may also provide a library of the same name. It is also appropriate to use this form as the result variable in a find_library() <#command:find_library> command.

Xxx_INCLUDE_DIR

When the module provides only a single library, this variable can be used to specify where to find headers for using the library (or more accurately, the path that consumers of the library should add to their header search path). It would be appropriate to use this as the result variable in a find_path() <#command:find_path> command.

Xxx_Yy_INCLUDE_DIR

If the module provides more than one library or where other modules may also provide a library of the same name, this form is recommended for specifying where to find headers for using library Yy provided by the module. Again, it would be appropriate to use this as the result variable in a find_path() <#command:find_path> command.

To prevent users being overwhelmed with settings to configure, try to keep as many options as possible out of the cache, leaving at least one option which can be used to disable use of the module, or locate a not-found library (e.g. Xxx_ROOT_DIR). For the same reason, mark most cache options as advanced. For packages which provide both debug and release binaries, it is common to create cache variables with a _LIBRARY_<CONFIG> suffix, such as Foo_LIBRARY_RELEASE and Foo_LIBRARY_DEBUG. The SelectLibraryConfigurations <#module:SelectLibraryConfigurations> module can be helpful for such cases.

While these are the standard variable names, backward compatibility should be provided for any previously used names in the find module that is replacing an older version. Old variable names should be documented as deprecated to discourage further use.

### A Sample Find Module
We will describe how to create a simple find module for a library Foo.

The top of the module should begin with a license notice, followed by a blank line, and then followed by a Bracket Comment <#bracket-comment>. The comment should begin with .rst: to indicate that the rest of its content is reStructuredText-format documentation. For example:

```
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindFoo
-------
Finds the Foo library.
Imported Targets
^^^^^^^^^^^^^^^^
This module provides the following imported targets, if found:
``Foo::Foo``

  The Foo library
Result Variables
^^^^^^^^^^^^^^^^
This module defines the following variables:
``Foo_FOUND``

  Boolean indicating whether (the requested version of) Foo was found.
``Foo_VERSION``

  The version of the Foo library which was found.
``Foo_INCLUDE_DIRS``

  Include directories needed to use Foo.
``Foo_LIBRARIES``

  Libraries needed to link to Foo.
Cache Variables
^^^^^^^^^^^^^^^
The following cache variables may also be set:
``Foo_INCLUDE_DIR``

  The directory containing ``foo.h``.
``Foo_LIBRARY``

  The path to the Foo library.
#]=======================================================================]
```

The module documentation consists of:

- An underlined heading specifying the module name.

- A simple description of what the module finds. More description may be required for some packages. If there are caveats or other details users of the module should be aware of, specify them here.

- A section listing imported targets provided by the module, if any.

- A section listing result variables provided by the module.

- Optionally a section listing cache variables used by the module, if any.

If the package provides any macros or functions, they should be listed in an additional section, but can be documented by additional .rst: comment blocks immediately above where those macros or functions are defined.

The find module implementation may begin below the documentation block. Now the actual libraries and so on have to be found. The code here will obviously vary from module to module (dealing with that, after all, is the point of find modules), but there tends to be a common pattern for libraries.

First, we try to use pkg-config to find the library. Note that we cannot rely on this, as it may not be available, but it provides a good starting point.

```
find_package(PkgConfig)
if(PkgConfig_FOUND)

  pkg_check_modules(PC_Foo QUIET Foo)
endif()
```

This should define some variables starting PC_Foo_ that contain the information from the Foo.pc file.

Now we need to find the libraries and include files; we use the information from pkg-config to provide hints to CMake about where to look before checking other default paths.

```
find_path(Foo_INCLUDE_DIR

  NAMES foo.h

  HINTS ${PC_Foo_INCLUDE_DIRS}

  PATH_SUFFIXES Foo
)
find_library(Foo_LIBRARY

  NAMES foo

  HINTS ${PC_Foo_LIBRARY_DIRS}
)
```

Alternatively, if the library is available with multiple configurations, the SelectLibraryConfigurations <#module:SelectLibraryConfigurations> module can be used to automatically set the Foo_LIBRARY variable instead:

```
find_library(Foo_LIBRARY_RELEASE

  NAMES foo

  HINTS ${PC_Foo_LIBRARY_DIRS}/Release
)
find_library(Foo_LIBRARY_DEBUG

  NAMES foo

  HINTS ${PC_Foo_LIBRARY_DIRS}/Debug
)
include(SelectLibraryConfigurations)
select_library_configurations(Foo)
```

If there is a good way of getting the version (from a header file, for example), that information can be used to set Foo_VERSION. Otherwise, attempt to use the information from the pkg-config:

```
set(Foo_VERSION ${PC_Foo_VERSION})
```

Now we can use the FindPackageHandleStandardArgs <#module:FindPackageHandleStandardArgs> module to handle most of the remaining steps for us:

```
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Foo

  REQUIRED_VARS

    Foo_LIBRARY

    Foo_INCLUDE_DIR

  VERSION_VAR Foo_VERSION
)
```

This will check that the REQUIRED_VARS contain values (that do not end in -NOTFOUND) and set Foo_FOUND appropriately. It will also cache those values. If Foo_VERSION is set, and a required version was passed to find_package() <#command:find_package>, it will check the requested version against the one in Foo_VERSION. It will also print messages as appropriate; note that if the package was found, it will print the contents of the first required variable to indicate where it was found.

At this point, we have to provide a way for users of the find module to link to the library or libraries that were found. There are two approaches, as discussed in the Find Modules section above. The traditional variable approach looks like

```
if(Foo_FOUND)

  set(Foo_LIBRARIES ${Foo_LIBRARY})

  set(Foo_INCLUDE_DIRS ${Foo_INCLUDE_DIR})

  set(Foo_DEFINITIONS ${PC_Foo_CFLAGS_OTHER})
endif()
```

If more than one library was found, all of them should be included in these variables (see the Standard Variable Names section for more information).

When providing imported targets, these should be namespaced (hence the Foo:: prefix); CMake will recognize that values passed to target_link_libraries() <#command:target_link_libraries> that contain :: in their name are supposed to be imported targets (rather than just library names), and will produce appropriate diagnostic messages if that target does not exist (see policy CMP0028 <#policy:CMP0028>).

```
if(Foo_FOUND AND NOT TARGET Foo::Foo)

  add_library(Foo::Foo UNKNOWN IMPORTED)

  set_target_properties(Foo::Foo PROPERTIES

    IMPORTED_LOCATION "${Foo_LIBRARY}"

    INTERFACE_COMPILE_OPTIONS "${PC_Foo_CFLAGS_OTHER}"

    INTERFACE_INCLUDE_DIRECTORIES "${Foo_INCLUDE_DIR}"

  )
endif()
```

One thing to note about this is that the INTERFACE_INCLUDE_DIRECTORIES and similar properties should only contain information about the target itself, and not any of its dependencies. Instead, those dependencies should also be targets, and CMake should be told that they are dependencies of this target. CMake will then combine all the necessary information automatically.

The type of the IMPORTED <#prop_tgt:IMPORTED> target created in the add_library() <#command:add_library> command can always be specified as UNKNOWN type. This simplifies the code in cases where static or shared variants may be found, and CMake will determine the type by inspecting the files.

If the library is available with multiple configurations, the IMPORTED_CONFIGURATIONS <#prop_tgt:IMPORTED_CONFIGURATIONS> target property should also be populated:

```
if(Foo_FOUND)

  if (NOT TARGET Foo::Foo)

    add_library(Foo::Foo UNKNOWN IMPORTED)

  endif()

  if (Foo_LIBRARY_RELEASE)

    set_property(TARGET Foo::Foo APPEND PROPERTY

      IMPORTED_CONFIGURATIONS RELEASE

    )

    set_target_properties(Foo::Foo PROPERTIES

      IMPORTED_LOCATION_RELEASE "${Foo_LIBRARY_RELEASE}"

    )

  endif()

  if (Foo_LIBRARY_DEBUG)

    set_property(TARGET Foo::Foo APPEND PROPERTY

      IMPORTED_CONFIGURATIONS DEBUG

    )

    set_target_properties(Foo::Foo PROPERTIES

      IMPORTED_LOCATION_DEBUG "${Foo_LIBRARY_DEBUG}"

    )

  endif()

  set_target_properties(Foo::Foo PROPERTIES

    INTERFACE_COMPILE_OPTIONS "${PC_Foo_CFLAGS_OTHER}"

    INTERFACE_INCLUDE_DIRECTORIES "${Foo_INCLUDE_DIR}"

  )
endif()
```

The RELEASE variant should be listed first in the property so that the variant is chosen if the user uses a configuration which is not an exact match for any listed IMPORTED_CONFIGURATIONS.

Most of the cache variables should be marked as advanced to remain hidden in GUI interfaces such as cmake-gui(1) <#manual:cmake-gui(1)> or ccmake(1) <#manual:ccmake(1)>, unless the user explicitly chooses to display and modify them:

```
mark_as_advanced(

  Foo_INCLUDE_DIR

  Foo_LIBRARY
)
```

If this find module replaces an older module version that provided variables before the current standard variables naming conventions, also backward compatibility variables should be provided to cause the least disruption possible. For example:

```
# Backward compatibility variables
set(Foo_VERSION_STRING ${Foo_VERSION})
```

## Copyright
2000-2026 Kitware, Inc. and Contributors