Skip to content

Wiki

CMakePresets and Build Installation

About 32 min read

Existing English translations were reused. 31 current source blocks remain in Simplified Chinese, without triggering paid translation.

CMakePresets.json Used to store commonly used CMake configurations. The problem it solves is: avoid having to manually write a long string of cmake -S ... -B ... -G ... -D... commands every time.

The template's CMakePresets.json is as follows:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 22,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "base",
      "hidden": true,
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
        "CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}"
      }
    },
    {
      "name": "linux-debug",
      "displayName": "Linux Debug",
      "inherits": "base",
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Linux"
      },
      "cacheVariables": {
        "BUILD_SHARED_LIBS": "ON"
      }
    },
    {
      "name": "linux-release",
      "displayName": "Linux Release",
      "inherits": "linux-debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    },
    {
      "name": "windows-debug",
      "displayName": "Windows GCC Debug",
      "inherits": "base",
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Windows"
      },
      "cacheVariables": {
        "CMAKE_C_COMPILER": "gcc",
        "CMAKE_CXX_COMPILER": "g++",
        "BUILD_SHARED_LIBS": "OFF"
      }
    },
    {
      "name": "windows-release",
      "displayName": "Windows GCC Release",
      "inherits": "windows-debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    }
  ],
  "buildPresets": [
    {
      "name": "linux-debug",
      "configurePreset": "linux-debug"
    },
    {
      "name": "linux-release",
      "configurePreset": "linux-release"
    },
    {
      "name": "windows-debug",
      "configurePreset": "windows-debug"
    },
    {
      "name": "windows-release",
      "configurePreset": "windows-release"
    }
  ],
  "testPresets": [
    {
      "name": "linux-debug",
      "configurePreset": "linux-debug",
      "output": {
        "outputOnFailure": true
      }
    },
    {
      "name": "linux-release",
      "configurePreset": "linux-release",
      "output": {
        "outputOnFailure": true
      }
    },
    {
      "name": "windows-debug",
      "configurePreset": "windows-debug",
      "output": {
        "outputOnFailure": true
      }
    },
    {
      "name": "windows-release",
      "configurePreset": "windows-release",
      "output": {
        "outputOnFailure": true
      }
    }
  ]
}

后面逐项解释时,很多地方继续用 linux-debug 举例。Windows 对应使用 windows-debug,Release 则分别使用 linux-release、windows-release;当前系统可选择的配置由 condition 决定。

1.root field

1.1.version

"version": 3

indicates CMakePresets.json the file format version, not the project version.

What can be filled in:

值 含义
1、2、3、... CMake preset 文件格式版本
3 本模板使用的版本,CMake 3.21 起支持;本工程统一要求 CMake 3.22 及以上
6 CMake 3.25 起支持,新增打包预设和工作流预设等功能

Note:

  1. This is not cmake_template's version number.
  2. To be compatible with older CMake, lower version, but some fields may no longer be usable.
  3. If the local CMake is very new, you do not necessarily have to use the highest preset version; as long as it is sufficient.

本模板只使用格式 3 已支持的配置、构建、测试和平台条件字段,因此 Ubuntu 22.04 的 CMake 3.22.1 就能读取。格式与字段说明见 CMake 3.22 预设文档;格式 6 的新增功能见 CMake 3.25 预设文档。

1.2.cmakeMinimumRequired

"cmakeMinimumRequired": {
  "major": 3,
  "minor": 22,
  "patch": 0
}

声明工程要求的最低 CMake 版本。CMake 还会单独检查自己是否支持前面的预设格式版本,两个条件都要满足。

What can be filled in:

字段 示例 含义
major 3 主版本号
minor 22 次版本号
patch 0 补丁版本号

本模板以 CMake 3.22 为兼容基线,顶层 CMakeLists.txt 同样写为:

cmake_minimum_required(VERSION 3.22)

二者保持一致。Ubuntu 22.04 可以直接使用 CMake 3.22.1;如果把旧模板改为这个配置,需要同时修改顶层最低版本、预设格式 version 和这里的 minor 三处,原有的 Debug / Release 预设、目录和 Ninja 生成器保持不变。

2.configurePresets

configurePresets is the preset for the "configuration phase".

Commands corresponding to the configuration phase:

cmake --preset linux-debug

It is equivalent to telling CMake:

  1. Which generator to use.
  2. Where the build directory is.
  3. What the build type is.
  4. Where the install directory is.
  5. Whether to generate compile_commands.json.

2.1.name

"name": "linux-debug"

A machine-readable name for the preset.

What can be filled in:

Naming Description
linux-debug Debug preset for this template
linux-release Release preset for this template
debug This is also possible, but not as clear as linux-debugclear
gcc-debug If distinguishing compilers, you can name them like this
clang-debug If adding a Clang preset, you can name it like this

Requirements:

  1. 同一个数组里不能重名。
  2. buildPresets 里的 configurePreset 要引用这里的名字。
  3. 命令行使用的就是这个名字。

Example:

cmake --preset linux-debug

2.2.displayName

"displayName": "Linux Debug"

A human-readable name, mainly used for display in IDEs, such as the preset list in VSCode CMake Tools.

What can be filled in:

Writing style Description
Linux Debug Clear
Linux Release Clear
Debug OK, but no platform distinction
Fedora GCC Debug If there are many presets, you can be more specific

This field does not affect the actual build logic.

2.3.generator

"generator": "Ninja"

Specify what build system files CMake should generate.

Linux common optional values:

Value Description
Ninja Recommended, fast, clean output, suitable for VSCode CMake Tools
Unix Makefiles Traditional Makefile workflow
Ninja Multi-Config Multi-config Ninja, can manage Debug / Release simultaneously

This template only supports Linux and uses Ninja, so it is fixed as:

"generator": "Ninja"

If using Unix Makefiles, the build command can still be used:

cmake --build --preset linux-debug

But the underlying layer is no longer Ninja.

2.4.binaryDir

"binaryDir": "${sourceDir}/build/linux-debug"

Specify the build directory.

What can be filled in:

Syntax Description
${sourceDir}/build/linux-debug Recommended; build artifacts stay in the project's build subdirectory
${sourceDir}/build/debug Also acceptable, but less clear than linux-debug.
/tmp/my-build Can be placed outside the project, but is not suitable as a template default

Common macros:

Macro Meaning
${sourceDir} Project source root directory
${presetName} Current preset name
${sourceParentDir} Parent directory of the source root directory

It can also be written as:

"binaryDir": "${sourceDir}/build/${presetName}"

This way linux-debug is automatically generated to:

build/linux-debug

This template explicitly writes out the table of contents to make it more intuitive for beginners.

2.5.cacheVariables

"cacheVariables": {
  "CMAKE_BUILD_TYPE": "Debug",
  "CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
  "CMAKE_INSTALL_PREFIX": "${sourceDir}/install/linux-debug"
}

cacheVariablesEquivalent to the -D parameter on the command line.

For example:

"CMAKE_BUILD_TYPE": "Debug"

Equivalent to:

-DCMAKE_BUILD_TYPE=Debug

3.Common cache variables

3.1.CMAKE_BUILD_TYPE

"CMAKE_BUILD_TYPE": "Debug"

Build type used in single-configuration generators.Ninja and Unix Makefiles are both common single-configuration generators.

What can be filled in:

Value Effect
Debug Debug build, usually with -g, less optimization
Release Release build, usually with optimization enabled
RelWithDebInfo Optimization + debug information
MinSizeRel Optimize for size

Common choices:

Scenario Recommended
Writing code, debugging breakpoints Debug
Release, performance testing Release
Performance testing but want to retain symbols RelWithDebInfo
Embedded or size-sensitive MinSizeRel

3.2.CMAKE_EXPORT_COMPILE_COMMANDS

"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"

Generate compile_commands.json.

What can be filled in:

value role
ON Generate compile_commands.json
OFF Do not generate

compile_commands.json Record the actual compilation command for each source file.clangd、VSCode, and many static analysis tools use it to obtain information such as include paths, macro definitions, and compilation standards.

It is recommended to enable this by default in the template:

"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"

3.2.1.Let clangd find compile_commands.json

Just generate compile_commands.json, it does not mean that clangd will definitely find it automatically.

Before using this approach in VSCode, you need to install the official LLVM clangd extension. CMake Tools is responsible for configuration, building, and selecting targets, while clangd is responsible for code completion, goto definition, semantic checking, and other editing features; they are not the same extension.

This template sets the Debug build directory to:

build/linux-debug/

Therefore, execute:

cmake --preset linux-debug

Afterwards, the compilation database is located at:

build/linux-debug/compile_commands.json

By default, clangd searches upward level by level starting from the directory containing the current source file compile_commands.jsonIt can usually find the database in the project root directory or the directory directly under build/ but it may not continue searching preset directories with multiple levels such as build/linux-debug/.

If clangd does not find the database, it enters fallback mode and analyzes source files using only a small set of default parameters. In this case, even if CMake can compile normally, the following may still occur in VSCode:

  1. 项目头文件显示找不到。
  2. Eigen、OpenCV 等第三方库显示找不到。
  3. C++ 标准识别错误,例如工程使用 C++20,clangd 却按照 C++17 分析。
  4. 跳转定义、自动补全和错误提示不准确。

It is recommended to create in the project root directory .clangd:

CompileFlags:
  CompilationDatabase: build/linux-debug

The directory structure will become:

.
├── .clangd
├── CMakeLists.txt
├── CMakePresets.json
├── build/
│   └── linux-debug/
│       └── compile_commands.json
└── src/

CompilationDatabase Use paths relative to the directory where .clangd is located, so do not write an absolute path on a user's computer. This file only stores project-wide configuration and can be committed to Git.

Note, .clangd does not generate a compilation database. The first time you use the project, or after modifying CMakeLists.txt、 compilation options, dependencies, and presets, you still need to rerun:

cmake --preset linux-debug

Or select linux-debug in VSCode CMake Tools and click Configure.

If .clangd does not take effect immediately after creation, you can run the following in the VSCode Command Palette:

clangd: Restart language server

You can also close and reopen the current .cpp file.

If the Microsoft C/C++ extension is also installed and the editor shows two duplicate sets of error prompts, you can keep the GDB debugging functionality provided by the extension while disabling its IntelliSense, letting clangd handle code analysis independently. This is a personal VSCode setting and does not need to be written into the CMake template.

Windows 的数据库位于 build/windows-debug/compile_commands.json,因此 .clangd 要对应改成:

CompileFlags:
  CompilationDatabase: build/windows-debug

CMAKE_EXPORT_COMPILE_COMMANDS 在 Ninja 生成器下适用,两种平台都保持使用 Ninja。Windows 中 clangd 查询 GCC 标准库路径的配置见 Windows开发环境搭建与测试。

3.2.2.Check whether clangd is actually taking effect

Open in VSCode:

查看 -> 输出 -> clangd

Normally, similar content should be seen:

Loaded compilation database from .../build/linux-debug/compile_commands.json
Compile command from CDB is: ...

If you see:

Failed to find compilation database
command clangd fallback

This indicates that clangd still has not read the compilation database. Check sequentially:

  1. Whether the one opened by VSCode is the project root directory.
  2. .clangd Whether it is located in the project root directory.
  3. Whether it has already been executed cmake --preset linux-debug.
  4. build/linux-debug/compile_commands.json Whether it actually exists.
  5. .clangd Whether the directory name in binaryDir is completely consistent with

If it can be used directly in the system terminal, clangdyou can also check a single source file:

clangd --check=src/main.cpp

The output should show that it loaded build/linux-debug/compile_commands.json, and use the include paths, macro definitions, and C++ standard generated by CMake.

3.2.3.Use the Release database

If you want clangd to analyze according to the Release configuration, you can change it to:

CompileFlags:
  CompilationDatabase: build/linux-release

And generate the corresponding database first:

cmake --preset linux-release

Daily development typically uses build/linux-debug. Do not let both .clangd point to a build directory that has not yet been generated or has already expired.

3.3.CMAKE_INSTALL_PREFIX

"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/linux-debug"

Specify the installation directory.

What can be filled in:

Usage Description
${sourceDir}/install/linux-debug Debug installation directory for this template
${sourceDir}/install/linux-release Release installation directory for this template
/usr/local System-level installation path, requires privileges, not suitable as template default
/opt/my_project System-level or deployment path

This template places the installation directory inside the project to make it easy to learn from and delete.

After installation, run:

./install/linux-debug/bin/cmake_template

3.4.BUILD_SHARED_LIBS

当前模板的库类型由预设选择:

预设 值 项目中的库
Linux Debug / Release ON 动态库
Windows Debug / Release OFF 静态库

Release 预设继承对应 Debug 预设中的设置。两种系统使用同一份函数声明和源文件,按照自己的预设构建即可。这里控制的是模板自己创建的库,第三方安装包仍按各自提供的方式使用。

4.buildPresets

buildPresets is a preset for the "build phase".

Build phase corresponding command:

cmake --build --preset linux-debug

Template format:

"buildPresets": [
  {
    "name": "linux-debug",
    "configurePreset": "linux-debug"
  },
  {
    "name": "linux-release",
    "configurePreset": "linux-release"
  }
]

4.1.name

"name": "linux-debug"

Build preset name.

It is generally recommended to give it the same name as the corresponding configure preset, so that the commands remain consistent:

cmake --preset linux-debug
cmake --build --preset linux-debug

4.2.configurePreset

"configurePreset": "linux-debug"

Indicates which configure preset this build preset uses to generate the build directory.

What can be filled in:

Value Description
linux-debug Use Debug build directory
linux-release Use Release build directory

Must correspond to the existing configurePresets in name.

5.testPresets

当前模板还带有测试预设,例如:

{
  "name": "windows-debug",
  "configurePreset": "windows-debug",
  "output": { "outputOnFailure": true }
}

构建完成后执行:

ctest --preset windows-debug

Linux 则使用 ctest --preset linux-debug。CTest 会运行原始 Eigen 示例,并检查输出中是否包含 Determinant = -2。后面修改 main.cpp 做语法练习时,输出变化会使这个原始示例测试失败;应该按新程序的要求修改测试,而不是把测试当作所有练习的统一运行命令。

6.继承、平台条件与其他字段

当前模板已经用到了 hidden 和 inherits 来复用配置,下面再解释它们的含义。

6.1.description

Add a longer description to the preset.

"description": "Debug build for Linux using Ninja"

6.2.hidden

Hide a certain preset and do not present it directly to the user for selection; typically used for inheritance.

"hidden": true

6.3.inherits

Inherit from another preset to reduce duplication.

{
  "name": "linux-debug",
  "inherits": "linux-base",
  "cacheVariables": {
    "CMAKE_BUILD_TYPE": "Debug"
  }
}

6.4.${presetName}

公共预设把目录写成:

"binaryDir": "${sourceDir}/build/${presetName}"

当 windows-debug 继承公共配置时,${presetName} 会展开成 windows-debug;使用 linux-release 时则展开成 linux-release。因此不同平台、不同构建类型有自己的缓存和安装目录。

6.5.condition

例如 Windows 预设使用:

"condition": {
  "type": "equals",
  "lhs": "${hostSystemName}",
  "rhs": "Windows"
}

这里检查运行 CMake 的宿主系统。Linux 对应 Linux,Windows 对应 Windows。在 Windows 原生 CMake 中,配置列表只显示 Windows 的预设;公共 base 预设由于设置了 hidden: true,也不会单独显示。

6.6.environment

Set the environment variable.

"environment": {
  "CC": "/usr/bin/gcc",
  "CXX": "/usr/bin/g++"
}

本模板的 Windows 预设明确选择 gcc 和 g++,保证使用本教程的 MinGW-w64 路线,但没有写死它们的绝对路径。Linux 默认让 CMake 从系统环境选择编译器。自己的工具位置可以放进 CMakeUserPresets.json,不要把个人电脑路径提交到公共预设中。

6.7.targets

Specify which targets to build by default.

"targets": ["cmake_template"]

If not specified, all targets are built by default.

6.8.jobs

Specify the number of parallel compilations.

"jobs": 8

If not specified, it is determined by the underlying build tool.

7.Why is there no installPresets

Many people would guess that one could write:

cmake --install --preset linux-debug

However, common CMake preset files do not use this root field. This template uses a more general install command:

cmake --install build/linux-debug

The install command requires passing in the build directory, because the install rules are generated into the build directory during the configure stage.

以下图形化步骤和截图以 Linux 为例。Windows 选择 Windows GCC Debug,程序路径改为 build/windows-debug/bin/cmake_template.exe,其他操作的意义相同。

8.VSCode CMake Tools Workflow

After installing the CMake Tools extension for VSCode, it will automatically recognize CMakePresets.json。

This section maps command-line operations to the corresponding VSCode graphical interface operations.

8.1.Open the CMake panel

After opening the project root directory with VSCode, click the CMake in the left sidebar.

If CMake Tools recognizes the project correctly, you will see entries such as preset, Configure, Build, and run target.

8.2.Configure

Command line:

cmake --preset linux-debug

In the VSCode graphical interface, the corresponding setting is:

  1. Click Configure.
  2. Select Linux Debug.

alt text

This step reads:

CMakePresets.json
CMakeLists.txt

and generate:

build/linux-debug/

If you changed CMakeLists.txt, added source files, or modified third-party dependencies, you usually need to reconfigure.

8.3.Build

Command line:

cmake --build --preset linux-debug

In the VSCode graphical interface, CMake Tools recognizes the corresponding build preset after Configure.

alt text

Then click the Build button in the lower-left corner or in the CMake panel:

alt text

This step compiles the .cpp files and generates the executable and shared libraries in the build directory.

The Debug executable file for this template is usually located at:

build/linux-debug/src/cmake_template

If you only modified the regular .cpp code, generally you just need to rebuild, not necessarily reconfigure.

8.4.Run the program in the build directory

Command line:

./build/linux-debug/src/cmake_template

In the VSCode graphical interface, the corresponding setting is:

  1. 选择运行/调试 target。
  2. 选择 cmake_template。
  3. 点击运行按钮。

alt text

alt text

After running, you will see the program output in the terminal.

alt text

If you want to debug with breakpoints, click the Debug button provided by CMake Tools; if you just want to run the program directly, click the Launch button.

In addition to the operation entry above, in the VSCode bottom status bar,Build next to the button, there are also Debug and Launch shortcut buttons. After selecting the cmake_template target and completing the build, you can directly click here to run or debug the program.

alt text

8.5.Install

Command line:

cmake --install build/linux-debug

In the VSCode graphical interface, you can press Ctrl+Shift+P to open the command palette, then enter:

CMake: Install

alt text

If the current selection is linux-debug preset, it is equivalent to:

cmake --install build/linux-debug

The installed program is located in:

install/linux-debug/bin/cmake_template

For everyday coding, running, and debugging, generally use the program in the build directory directly:

build/linux-debug/src/cmake_template

install is only needed when verifying the installation layout, header file installation, dynamic library RPATH, or preparing to release the program.

8.6.Summary of Correspondences

What you want to do Command line VSCode CMake Tools
Configure the project cmake --preset linux-debug Select Linux Debug and then click Configure
Build the project cmake --build --preset linux-debug Click Build
Run the build output ./build/linux-debug/src/cmake_template Select the cmake_template target and then click the run button
Debug the build output Debug with GDB build/linux-debug/src/cmake_template Select the cmake_template target and then click the Debug button
Install the project cmake --install build/linux-debug Execute in the command palette CMake: Install

In this way, there is no need to manually write .vscode/tasks.json, and there is also no need to prepare an additional VSCode debug configuration file.

9.Operation and Debugging Notes

CMake Tools can directly run or debug the currently selected executable target, so there is no need to manually write additional run scripts.

For debugging, it is recommended to install the Microsoft C/C++ extension and GDB, because CMake Tools is responsible for selecting the target, and the actual C/C++ debugger still requires GDB/LLDB support.

If you only changed the .cpp code, generally you just need to rebuild and then run or debug.

If you modified CMakeLists.txt, added source files, or changed dependencies, it is recommended to Configure first, then Build, and then run or debug.

9.1.Why not write tasks.json

Old templates often use .vscode/tasks.json to write a long string of commands:

cmake ..
make install
source setup.bash
run app

这个模板不这样做。原因是构建、运行和调试入口都可以交给 CMake Tools 管理,命令行流程则由 CMakePresets.json 固化。

This makes responsibilities clearer:

File responsible for
CMakePresets.json configure/build parameters
VSCode CMake Tools Select preset, Configure, Build, run and debug target
CMakeLists.txt targets, dependencies, install rules

9.2.GDB needs to be installed

Ubuntu/Debian:

sudo apt install gdb

Fedora:

sudo dnf install gdb

10.Common Errors

10.1.Forgot to install Ninja

The error may be similar to:

CMake was unable to find a build program corresponding to "Ninja"

Solution:

sudo apt install ninja-build

Or:

sudo dnf install ninja-build

10.2.The preset name is written incorrectly

Error command:

cmake --preset debug

If there is no debug preset in the file, it will fail.

View available presets:

cmake --list-presets

10.3.No configure before build

If running directly for the first time:

cmake --build --preset linux-debug

It may fail because the build directory has not yet been generated.

Correct order:

cmake --preset linux-debug
cmake --build --preset linux-debug