%%
# 纲要
> 主干纲要、Hint/线索/路标
# Q&A
#### 已明确
#### 待明确
> 当下仍存有的疑惑
**❓<font color="#c0504d"> 有什么问题?</font>**
%%
# CMake 变量
> 参见[^1]
## 定义和引用变量
- **定义变量**:`set(variable value...)`。当存在多个 value 时,将作为一个 list 变量(list 变量本质上是`;`分隔的字符串列表)
- **引用变量值**:`${variable}`
当在 `CMakeLists.txt` 中**引用一个变量**时:
- 如果该变量在 **当前作用域中** 已通过 `set()` 命令定义,则将使用这一值;
- 如果该变量在当前作用域中尚未定义,则将**使用该变量的缓存值**;
- 如果该变量在即未在当前作用域中定义,也不存在缓存值,则将报错。
> [!note] 变量既可以在`CMakeLists.txt`中设置,也可以使用 `cmake` 命令时指定,二者等价,后者会覆盖前者。
>
> - 在 `CMakeLists.txt`中设置值:`set(CMAKE_EXPORT_COMPILE_COMMANDS ON)`
> - 使用`cmake`命令时通过 `-D` 选项设置:`cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1`
>
### 选项变量 option
`CMakeLists.txt` 中可通过 `option()` 命令定义一个 "**选项变量**",用作为 **==布尔值==**,可用于 `if()` 语句中。
```cmake
# 命令说明:
option(<变量名> "描述信息" <默认值>) # 值可为ON或OFF.
# 示例一: 默认USE_MYMATH=ON; 在cmake配置阶段,可通过`-D`选项覆盖默认值: `cmake -DUSE_MYMATH=OFF`
option(USE_MYMATH "Use custom math implementation" ON)
# 示例二: 指定默认构造动态库
option(BUILD_SHARED_LIBS "add_library build shared lib default" ON)
```
#### 使用示例
示例一:利用 CMake 选项变量控制 "**宏定义**",进而控制 "条件编译"。
```cmake
# 当CMake选项变量USE_MYMATH为ON时, 为MathFunctions目标定义宏"USE_MYMATH"
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") # 为MathFunctions目标定义宏 "USE_MYMATH"
message(STATUS "Using custom math implementation")
endif()
```
```cpp
#include "MathFunctions.h"
#include <cmath>
// Wrap the mysqrt include in a precompiled ifdef based on USE_MYMATH
#ifdef USE_MYMATH
#include "mysqrt.h"
#endif
namespace mathfunctions {
double sqrt(double x) {
// If USE_MYMATH is defined, use detail::mysqrt.
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
}
} // mathfunctions end
```
---
%%
## 查看变量值
有几种方式:
%%
<br><br><br>
# CMake 内置变量
## 目录与路径相关变量
###### 项目源码目录/构建目录
| 变量名 | 说明 |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| CMAKE_ROOT | CMake 自身的安装目录. |
| CMAKE_COMMAND | `cmake`可执行文件所在的路径. |
| | |
| CMAKE_SOURCE_DIR | 指向项目的**顶层源代码目录**,即包含项目**顶层 `CMakeLists.txt` 文件**的目录。 |
| CMAKE_BINARY_DIR | 指向项目的**顶层二进制目录**(或称为 **==构建目录==**,即 `build/`,**CMake 运行目录**)。<br>即 CMake 生成构建系统文件(如 Makefiles 或 VS 项目文件)以及编译生成二进制文件(可执行文件或库)的顶层目录。 |
| CMAKE_CURRENT_SOURCE_DIR | 指向 **当前正在处理的 `CMakeLists.txt` 文件所在的目录** |
| CMAKE_CURRENT_BINARY_DIR | 指向 **当前正在构建的构建目录**。 |
| | |
| PROJECT_BINARY_DIR | 指向 **当前项目的构建目录**。 |
| PROJECT_SOURCE_DIR | 指向 **当前项目的源代码目录**。 |
> [!NOTE] `PROJECT_BINARY_DIR` 和 `PROJECT_SOURCE_DIR` 指向**当前 CMake 项目**(可能是整个工程或任何子项目)的**根目录**。
>
> - 在包含**多个子项目**的构建环境中,这两个变量对于**每个子项目**来说都是唯一且不同的,分别指向各个子项目的构建目录和源代码目录。
> - 在**单个项目**的构建环境中,这两个变量就等同于 `CMAKE_SOURCE_DIR`、`CMAKE_BINARY_DIR` 。
>
> [!quote]
> When run in [`cmake -P`](https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-P) script mode, CMake sets the variables [`CMAKE_BINARY_DIR`](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html#variable:CMAKE_BINARY_DIR), `CMAKE_SOURCE_DIR`, [`CMAKE_CURRENT_BINARY_DIR`](https://cmake.org/cmake/help/latest/variable/CMAKE_CURRENT_BINARY_DIR.html#variable:CMAKE_CURRENT_BINARY_DIR) and [`CMAKE_CURRENT_SOURCE_DIR`](https://cmake.org/cmake/help/latest/variable/CMAKE_CURRENT_SOURCE_DIR.html#variable:CMAKE_CURRENT_SOURCE_DIR) to the current working directory.
###### CMake 生成文件输出目录
| 变量名 | 说明 |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| CMAKE_RUNTIME_OUTPUT_DIRECTORY | 指定**可执行文件输出路径**(该变量会用于初始化所有目标上的 RUNTIME_OUTPUT_DIRECTORY 属性) |
| CMAKE_LIBRARY_OUTPUT_DIRECTORY | 指定**共享库 (`.so/.dll/.dylib`) 输出路径**(该变量用于初始化所有目标上的 LIBRARY_OUTPUT_DIRECTORY 属性。) |
| CMAKE_ARCHIVE_OUTPUT_DIRECTORY | 指定**静态库 (`.a/.lib`) 输出路径**(该变量用于初始化所有目标上的 ARCHIVE_OUTPUT_DIRECTORY 属性。 |
| CMAKE_INSTALL_PREFIX | `install()`命令所使用的安装路径前缀 <br>(Linux/UNIX 上默认为 `/usr/local`,Windows 上默认为 `c:/Program Files/${PROJECT_NAME}`) |
> [!NOTE] 可执行文件、共享库、静态库的默认输出路径
>
> 即上表变量的默认分别为 `${CMAKE_BINARY_DIR}/bin, ${CMAKE_BINARY_DIR}/lib, ${CMAKE_BINARY_DIR}/lib`
>
###### CMake 搜索路径
| 变量名 | 说明 | `find_file` | `find_path` | `find_library` | `find_package` | `find_program` | `include` |
| -------------------- | ---------------------------------------------------------------------------------- | ----------- | ----------- | -------------- | -------------- | -------------- | --------- |
| CMAKE_FIND_ROOT_PATH | 指定 **CMake 搜索的文件系统根路径**(sysroot) <br> | ✔️ | ✔️ | ✔️ | ✔️ | ❌ | ❌ |
| CMAKE_IGNORE_PATH | 指定所有 `find_*()` 命令将**忽略**的目录列表 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
| CMAKE_PREFIX_PATH | 指定 **额外的外部依赖项查找路径** <br>(包括库文件、头文件、可执行程序、包等) | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
| CMAKE_LIBRARY_PATH | 指定 **额外的库文件查找路径** <br>(`.so`, `.a`, `.lib` 等) | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ |
| CMAKE_INCLUDE_PATH | 指定 **额外的头文件查找路径** | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| CMAKE_MODULE_PATH | 指定 **额外的 `.cmake` 模块查找路径** | ❌ | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| `<PackageName>_ROOT` | 指定 **特定依赖库/包**的根目录。 <br>该变量设置后, 对 `find_package(<PackagName>)` 命令的调用将会搜索该变量指定的路径. | | | | ✔️ | | |
> [!NOTE] 上述变量设置 `find_*` 相关函数的搜索路径,均为 list 变量,路径列表值需以 "分号`;`" 分隔。
> [!NOTE] CMake 会 **==优先==** 在上述变量指定路径中进行查找,若不存在,其次再查找系统默认路径(如 `/usr/lib`, `/usr/include` 等)
> [!NOTE] 关于 `CMAKE_FIND_ROOT_PATH` 变量
>
> 原本 Linux 系统下 CMake 的**搜索根路径是 `/`**,其默认将在是 `/usr/lib`、`/usr/include` 等路径进行查找。
> 若设置 `CMKAE_FIND_ROOT_PATH` 为 `/opt/riscv-sysroot` 后,其**将在该路径下搜索 `/opt/riscv-sysroot/lib`、`/opt/riscv-sysroot/include` 等子目录**。
>
> 通常用于**交叉编译**的场景,例如嵌入式开发:在 x86_64 PC 上编译程序,但程序要运行在 ARM/RISC-V 设备上,后者的文件系统挂载在 `/opt/riscv-sysroot` 目录下,需要使用设备中的库文件和头文件,则通过该变量**修改 CMake 搜索的系统根路径**。
> [!NOTE] 关于 `CMAKE_PREFIX_PATH` 变量
>
> 该变量指定 CMake 查找**外部依赖项**(包括库文件、头文件、可执行程序、包等)的**额外目录前缀**。
> "**前缀**" 的含义是,CMake 会在这些路径下**进一步查找 `lib`、`bin`、`include` 等子目录**。
> [!example]
>
> ```cmake
> set(CMAKE_PREFIX_PATH "/usr/local/opencv")
> find_package(OpenCV REQUIRED)
> include_directories(${OpenCV_INCLUDE_DIRS})
> target_link_libraries(MyApp PRIVATE ${OpenCV_LIBS})
> ```
>
<br>
## 编译控制相关变量
| 变量名 | 说明 |
| --------------------------------- | --------------------------------------------------------------------------- |
| CMAKE_BUILD_TYPE | 指定构建类型(仅适用于 **单配置生成器**)。常见值:`Debug`、`Release`、`RelWithDebInfo`、`MinSizeRel` |
| CMAKE_CONFIGURATION_TYPES | 适用于 **多配置生成器**(如 Visual Studio),可选值同 `CMAKE_BUILD_TYPE` |
| | |
| `CMAKE_<LANG>_STANDARD` | 指定所使用的语言标准版本。 |
| `CMAKE_<LANG>_STANDARD_REQUIRED` | 为 ON 时,表示 `CMAKE_XXX_STANDARD` 变量必须被指定。 |
| `CMAKE_<LANG>_EXTENSIONS` | 是否使用 **编译器扩展**(如 `-std=c++14` vs `-std=gnu++14`),默认 `ON` |
| | |
| `CMAKE_<LANG>_FLAGS` | 编译标志。将会传递给编译器的所有调用。 |
| `CMAKE_<LANG>_FLAGS_DEBUG` | 针对 Debug 构建模式的编译标志 |
| `CMAKE_<LANG>_FLAGS_RELEASE` | 针对 Release 构建模式的编译标志 |
| | |
| `CMAKE_EXE_LINKER_FLAGS` | 可执行文件的链接选项 |
| `CMAKE_SHARED_LINKER_FLAGS` | 共享库的链接选项 |
| `CMAKE_STATIC_LINKER_FLAGS` | 静态库的链接选项 |
| `CMAKE_POSITION_INDEPENDENT_CODE` | 设置 `ON` 以启用 **PIC(位置无关代码)**,适用于共享库 |
| | |
| `CMAKE_<LANG>_OUTPUT_EXTENTION` | 为单个文件编译输出的扩展名 |
> [!NOTE] CMake 构建时会组合 `CMAKE_CXX_FLAGS` 以及 "构建类型特定" 的编译选项
>
> 例如,Release 配置下构建时会传递 `g++ ${CMAKE_CXX_FLAGS} {CMAKE_CXX_FLAGS_RELEASE}`。
>
> - `CMAKE_CXX_FLAGS` 变量默认为空。
> - `CMAKE_CXX_FLAGS_DEBUG` 变量默认值为`-g`;
> - `CMAKE_CXX_FLAGS_RELEASE` 变量默认值为 `-O3 -DNDEBUG`;
>
> 因此,通常可设置如下:
>
> ```cpp
> set(CMAKE_CXX_FLAGS "-Wall -Wextra -Werror")
> set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
> set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
> ```
>
> [!note] `<LANG>` 表示为特定语言,例如 `C`, `CXX`。
>
> ```CMake
> # 指定编译器
> set(CMAKE_C_COMPILER clang)
> set(CMAKE_CXX_COMPILER clang++)
>
> # 指定编译选项
> # 值为命令行字符串片段。因此,多个选项应该用空格分隔,带空格的选项应该加引号。
> # 对于每种语言,如果这一变量没有定义,则 CMake 将结合环境变量的值以及 CMake 对于工具链的内置默认值对该变量进行初始化并存储在缓存中.
> # 如果需要为特定构建目标设置编译器选项,而不是全局地设置,应使用`target_compile_options()`
> set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") # 追加添加标志, 启用额外警告信息
> set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") # 追加标志, 启用调试信息
> set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMY_MYCRO") # 追加标志, 定义一个宏
> # 该变量可以在用户提供的工具链文件中设置,也可以通过命令行上的-D 设置. 例如:
> # cmake -DCMAKE_CXX_FLAGS="-Wall;-Wextra;-g;" <source_dir>
> # cmake -DCMAKE_CXX_FLAGS="-isystem /path/to/include" <srouces_dir>
> # cmake -DCMAKE_CXX_FLAGS="-Ipath/to/includes" <source_dir>
> ```
###### 编译工具链相关变量
| 变量名 | 说明 |
| ----------------------- | ------------------------------------- |
| `CMAKE_<LANG>_COMPILER` | 指定 **特定语言** 所用的编译器(如 `g++`、`clang++`) |
| CMAKE_LINKER | 指定链接器(如 `ld`、`lld`、`gold`) |
| CMAKE_AR | 指定静态库归档工具(如 `ar`) |
| CMAKE_NM | 指定符号表工具(如 `nm`) |
| CMAKE_RANLIB | 指定静态库索引工具(如 `ranlib`) |
###### 编译命令模版相关变量
```cmake
# -----编译命令模版相关.
CMAKE_<LANG>_COMPILER_OBJECT # 定义编译单个C++源文件时使用的命令模板.包括编译器调用, 编译标志, 源文件和输出目标.
# 该变量的值应当被设置为:`<编译器> <编译标志> -o <输出文件> <输入源文件>`的形式.
# 这个变量通常在 CMake 的编译器配置阶段被设置,并且是根据所选编译器自动生成的, 不应由用户直接修改.
# CMake 使用这个模板生成实际的构建规则,这些规则随后被构建系统(如 Makefiles、Ninja 等)使用
CMAKE_<LANG>_CREATE_SHARED_LIBRARY # 定义编译共享库(动态链接库)所用的命令模版
CMAKE_<LANG>_CREATE_SHARED_MODULE # 定义编译共享模块(通常用于插件)的命令模版
CMAKE_<LANG>_CREATE_STATIC_LIBRARY # 定义编译静态库的命令模版
```
<br>
## 构建行为控制相关变量
| 变量名 | 说明 |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| BUILD_SHARED_LIBS | 设置 `add_library()` **默认创建动态库/共享库**。默认为 OFF,即创建静态库。 |
| CMAKE_EXPORT_COMPILE_COMMANDS | 生成过程中启用/禁用 **==编译命令输出==**。 <br>(如果为ON, 将在构建目录生成一个`compile_commands.json`文件, 该文件中包含了编译器对项目中所有可翻译单元(translation units)的精确调用(即项目中每个文件编译时所使用的精确编译器命令)) |
| CMAKE_WARN_DEPRECATED | 使用**已弃用功能**时是否发出警告。默认为 ON。 <br>(运行`cmake`命令时,该选项可由 -Wdeprecated 选项启用,也可以由-Wno-deprecated 选项禁用) |
| CMAKE_INCLUDE_CURRENT_DIR | 自动将当前源代码和构建目录添加到包含路径。默认为 OFF。 <br>(如果设置为ON, cmake会自动将 `CMAKE_CURRENT_SOURCE_DIR` 和 `CMAKE_CURRENT_BINARY_DIR` 添加到每个 include 路径中) |
<br>
## 平台信息相关变量
| 变量 | 说明 |
| ----------------------------- | ----------------------------------------------------------------------------------------------------- |
| `CMAKE_HOST_SYSTEM` | 当前运行 CMake 的主机 OS 名称 <br>(该变量由`CMAKE_HOST_SYSTEM_NAME`以及 `CMAKE_HOST_SYSTEM_VERSION` 两变量的值构成,经中划线连接) |
| `CMAKE_HOST_SYSTEM_NAME` | 主机 OS 名称 |
| `CMAKE_HOST_SYSTEM_VERSION` | 主机 OS 版本 |
| `CMAKE_HOST_SYSTEM_PROCESSOR` | 主机 CPU 架构(例如值为 `x86_64`,`aarch64` 等) |
| | |
| `CMAKE_SYSTEM_NAME` | 目标系统名称(如 `Linux`、`Windows`、`Darwin`) |
| `CMAKE_SYSTEM_VERSION` | 目标系统版本 |
| | |
| `CMAKE_HOST_LINUX` | 当主机系统为 Linux 时, 该变量值为 true. |
| `CMAKE_HOST_WIN32` | 当主机系统为 Windows(包括 Windows 64 以及 MYYS), 该变量值为 true. 注意, 在 Cygwin 上,该变量为 falae |
<br><br><br>
# CMake 缓存(Cache)
> 参见[^2]
CMake缓存可以被认为是一个 **配置文件 `CMakeCache.txt`** 。
**当CMake首次在一个项目上运行时,会在构建树的顶层目录中生成一个`CMakeCache.txt` 文件。**
CMake 使用该文件来**存储一组全局缓存变量**(global cache variables),**这些缓存变量的值是持久的**,会在项目后续每次运行 CMake 时持续生效,直到手动清理构建目录或重新配置项目。
如果 `CMakeCache.txt` 丢失或损坏,则 CMake 会在下一次运行时重新生成,但之前的缓存信息将丢失。
CMake 缓存的目的在于:
- 存储用户的选择,以便再次运行 CMake 时不需要重新输入这些信息。
> 例如,option 命令将创建一个布尔变量**并将其值存储在缓存中**,当用户再次运行 CMake 时,该变量的值将从缓存中读取。
- 在 CMake 运行之间持久地存储变量值。
> 用户可能无法看到或调整这些条目。通常,这些值是系统相关的变量,需要 CMake 编译和运行程序来确定它们的值。**一旦这些值被确定,它们被存储在缓存中,以避免每次 CMake 运行时都必须重新计算它们**。如果对计算机进行了重大更改,例如更改操作系统或切换到不同的编译器,则需要删除缓存文件。
==注意==:
- **用户不应当直接编辑修改 `CMakeCache.txt` 文件,该文件由 CMake 工具自动维护**。
> 在 CMake 中,通过 `cmake -D` 命令设置缓存初始值或是在 `CMakeLists.txt` 文件中使用 `set(<VAR> <VALUE> CACHE <TYPE> FORCE)` 等命令指定缓存值时,都会影响 `CMakeCache.txt` 文件中的内容。
>
> CMake会在下次执行配置的过程中将**新设定**的缓存值写入到`CMakeCache.txt`文件(如果文件尚未存在,则会先创建)。
- 一旦一个变量位于缓存中,则其 **缓存值**(cache value)**不会被 `CMakeLists.txt` 进行修改**,例如`set(FOO ON CACHE BOOL "doc")` 这样设置 **缓存值**的命令**只在该缓存变量尚不存在时会生效**。
如果一个变量已经存在于缓存中(存在于 `CMakeCache.txt` 中),**则该命令无效,不会产生任何效果**。
但是,该**变量的值(非缓存中的值)**仍然可以通过 `set(FOO ON "doc")` 命令进行**重写**并生效。
> CMake的机制是,**缓存当中的值仅当该变量在当前作用域尚未定义时才会被使用**,如果通过不带`CACHE`关键字的`set()` 命令定义了一个普通变量,则**此处定义的变量值将被使用**,而cache中的同一变量的缓存值不会被使用。而**不带`CACHE`关键字的`set()` 命令设置的变量值不会影响 cache 中的缓存值**。
>
> ```cmake
> # assume that FOO is set to ON in the cache
>
> set(FOO OFF)
> # sets foo to OFF for processing this CMakeLists file
> # and subdirectories; the value in the cache stays ON
> ```
- 在极少数确实需要修改**变量缓存值**的情况,需要为`set()` 命令搭配 `FORCE` 和`CACHE` 选项,`FORCE`选项将导致`set` 命令**覆盖并更改变量的缓存值**。
```cmake
# Users has previously run CMake and turned the cache value off.
# The `FORCE` keywords can force the cache values to be set `ON`.
# Build the vtkHybrid kit always.
set(VTK_USE_HYBRID ON CACHE BOOL "doc" FORCE)
```
### 创建缓存变量的方式
- 使用`option()`
```cmake
option(USE_JPEG "include jpeg supports?")`
```
- 使用`set()` 命令并搭配 `CACHE`关键字
```cmake
set(USE_JPEG ON CACHE BOOL "include jpeg supports?")
```
- 使用`find_file()` 命令时也会将查找结果存储为一个 cache 变量
> `find_file(<VAR> name1 [path1 path2 ...] )` 命令用于查找指定文件的完整路径。
>
> 如果查找成功,查找结果将保存到名为 `<VAR>` 的cache变量中(如果指定了`NO_CACHE` 则保存为普通变量);如果未找到,结果将为`<VAR>-NOTFOUND`。
### 设置缓存初始值
> ==注意==:下列方式都会使得**下一次运行 CMake 配置过程**时 **修改 `CMakecache.txt` 中的内容**,其中方**式一的优先级最高**。
>
> - 如果 `CMakeCache.txt` 文件尚不存在,则CMake会在下一次运行配置的过程中创建 `CMakeCache.txt` 文件并将**下列方式设置的缓存变量值**写入文件内。
> - 如果 `CMakeCache.txt` 文件已存在,则 CMake 会在下一次运行配置的过程中**修改该文件中的缓存变量值**。
- 方式一:使用`cmake` 命令时通过 `-D<CACHE_VAR>:TYPE=<VALUE>` **指定缓存变量的初始值**。
```shell
cmake -DBUILD_TESTING:BOOL=ON <etc..> ..
```
- 方式二:创建一个文件指定缓存变量的初始值,并在**运行`cmake` 命令时通过 `-C` 选项加载该文件**
(该文件使用CMakeLists语法,内容是一系列的`set()` 命令)。
- 文件内容示例:
```cmake
# Build the vtkHybrid kit.
set(VTK_USE_HYBRID ON CACHE BOOL "doc string")
```
- 方式三:设置缓存变量并进行"**隐藏**(在 CMake GUI 中的 cache 编辑器中该缓存变量将不可见)
通过指定缓存变量类型为 `INTERNAL`,该缓存变量将被应用`FORCE` 并且在 CMake GUI 中的 cache 编辑器中不可见。示例:
```cmake
# Build the vtkHybrid kit always and don't distract the user by showing the option.
set(VTK_USE_HYBRID ON CACHE INTERNAL "doc")
```
<br><br><br>
# Buffer
## 闪念
> sudden idea
## 候选资料
> Read it later
# ♾️参考资料
# Footnotes
[^1]: [cmake-variables(7)](https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html#id1)
[^2]: [CMake Cache — Mastering CMake](https://cmake.org/cmake/help/book/mastering-cmake/chapter/CMake%20Cache.html)