08. CMake 配置选项
项目配置是CMake工作流程的第一步,也是最重要的一步。
在这个阶段,CMake会检测系统环境、编译器、处理项目选项,并生成构建文件。
1. 项目目录
以一个计算加减乘除的C++程序为例:
03_CmdArgs/
├── 01
│ ├── CMakeLists.txt
│ └── src
│ ├── calc.cpp
│ ├── calc.h
│ └── main.cpp
├── 02
│ ├── CMakeLists.txt
│ └── src
│ ├── calc.cpp
│ ├── calc.h
│ └── main.cpp
└── 03
├── CMakeLists.txt
└── src
├── calc.cpp
├── calc.h
└── main.cpp
以下列出4个文件的内容。
1.1 calc.h
#ifndef CALC_H
#define CALC_H
int add(int a, int b); // 加法
int subtract(int a, int b); // 减法
int multiply(int a, int b); // 乘法
int divide(int a, int b); // 除法
#endif
1.2 calc.cpp
#include "calc.h"
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int multiply(int a, int b) {
return a * b;
}
int divide(int a, int b) {
return a / b;
}
1.3 main.cpp
#include <iostream>
#include "calc.h"
int main() {
int x, y;
std::cout << "Input two integers: ";
std::cin >> x >> y;
// 加法
std::cout << x << "+" << y << "=" << add(x, y) << std::endl;
// 减法
std::cout << x << "-" << y << "=" << subtract(x, y) << std::endl;
// 乘法
std::cout << x << "*" << y << "=" << multiply(x, y) << std::endl;
// 除法
std::cout << x << "/" << y << "=" << divide(x, y) << std::endl;
return 0;
}
1.4 CMakeLists.txt
# 指定CMake的最低版本要求
cmake_minimum_required(VERSION 3.20)
# 定义项目名称
project(HelloCMake)
# 创建可执行文件
add_executable(hello src/main.cpp src/calc.cpp)
2. 最简单的配置和构建
2.1 配置
cmake -S . -B build
其中,-S指定源码目录,-B指定构建目录
| 选项 | 全称 | 含义 | 默认值 |
|---|---|---|---|
| -S | --source |
源目录:包含CMakeLists.txt的目录 |
当前目录 (.) |
| -B | --build |
构建目录:生成构建文件(Makefile, 缓存,可执行文件)的目录 |
当前目录 (.) |
默认使用Visual Studio 18 2026生成器,生成msbuild相关的构建文件,配置输出如下:
yinsh@coding4096 /f/cmake_demos/03_CmdArgs
$ cmake -S . -B build
-- Building for: Visual Studio 18 2026
-- Selecting Windows SDK version 10.0.26100.0 to target Windows 10.0.19045.
-- The C compiler identification is MSVC 19.50.35724.0
-- The CXX compiler identification is MSVC 19.50.35724.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.50.35717/bin/Hostx64/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.50.35717/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (4.3s)
-- Generating done (0.0s)
-- Build files have been written to: F:/cmake_demos/03_CmdArgs/build
2.2 构建
cmake --build build
这是CMake的统一构建命令,用于编译已配置的项目。
它是对底层构建工具(如make、ninja、msbuild)的抽象封装,提供跨平台一致的构建体验。
构建输出如下:
yinsh@coding4096 /f/cmake_demos/03_CmdArgs
$ cmake --build build
适用于 .NET Framework MSBuild 版本 18.3.0-release-26070-10+3972042b7
1>Checking Build System
Building Custom Rule F:/cmake_demos/03_CmdArgs/CMakeLists.txt
main.cpp
calc.cpp
正在生成代码...
hello.vcxproj -> F:\cmake_demos\03_CmdArgs\build\Debug\hello.exe
Building Custom Rule F:/cmake_demos/03_CmdArgs/CMakeLists.txt
2.3 运行
yinsh@coding4096 /f/cmake_demos/03_CmdArgs
$ ./build/Debug/hello.exe
Input two integers: 10 5
10+5=15
10-5=5
10*5=50
10/5=2
2. 生成器 (Generator)
生成器负责为原生构建系统生成输入文件(如Makefile、Ninja构建文件、Visual Studio解决方案等)
2.1 查看支持哪些生成器
使用以下命令查看系统支持哪些生成器
cmake --help
# 或者
cmake -G
以下是我Windows系统中支持的生成器(带*的是默认生成器 ):
Generators
The following generators are available on this platform (* marks default):
* Visual Studio 18 2026 = Generates Visual Studio 2026 project files.
Use -A option to specify architecture.
Visual Studio 17 2022 = Generates Visual Studio 2022 project files.
Use -A option to specify architecture.
Visual Studio 16 2019 = Generates Visual Studio 2019 project files.
Use -A option to specify architecture.
Visual Studio 15 2017 = Generates Visual Studio 2017 project files.
Use -A option to specify architecture.
Visual Studio 14 2015 = Deprecated. Generates Visual Studio 2015
project files. Use -A option to specify
architecture.
Borland Makefiles = Generates Borland makefiles.
NMake Makefiles = Generates NMake makefiles.
NMake Makefiles JOM = Generates JOM makefiles.
MSYS Makefiles = Generates MSYS makefiles.
MinGW Makefiles = Generates a make file for use with
mingw32-make.
Green Hills MULTI = Generates Green Hills MULTI files
(experimental, work-in-progress).
Unix Makefiles = Generates standard UNIX makefiles.
Ninja = Generates build.ninja files.
Ninja Multi-Config = Generates build-<Config>.ninja files.
FASTBuild = Generates fbuild.bff files.
Watcom WMake = Generates Watcom WMake makefiles.
CodeBlocks - MinGW Makefiles = Generates CodeBlocks project files
(deprecated).
CodeBlocks - NMake Makefiles = Generates CodeBlocks project files
(deprecated).
CodeBlocks - NMake Makefiles JOM
= Generates CodeBlocks project files
(deprecated).
CodeBlocks - Ninja = Generates CodeBlocks project files
(deprecated).
CodeBlocks - Unix Makefiles = Generates CodeBlocks project files
(deprecated).
CodeLite - MinGW Makefiles = Generates CodeLite project files
(deprecated).
CodeLite - NMake Makefiles = Generates CodeLite project files
(deprecated).
CodeLite - Ninja = Generates CodeLite project files
(deprecated).
CodeLite - Unix Makefiles = Generates CodeLite project files
(deprecated).
Eclipse CDT4 - NMake Makefiles
= Generates Eclipse CDT 4.0 project files
(deprecated).
Eclipse CDT4 - MinGW Makefiles
= Generates Eclipse CDT 4.0 project files
(deprecated).
Eclipse CDT4 - Ninja = Generates Eclipse CDT 4.0 project files
(deprecated).
Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files
(deprecated).
Kate - MinGW Makefiles = Generates Kate project files (deprecated).
Kate - NMake Makefiles = Generates Kate project files (deprecated).
Kate - Ninja = Generates Kate project files (deprecated).
Kate - Ninja Multi-Config = Generates Kate project files (deprecated).
Kate - Unix Makefiles = Generates Kate project files (deprecated).
Sublime Text 2 - MinGW Makefiles
= Generates Sublime Text 2 project files
(deprecated).
Sublime Text 2 - NMake Makefiles
= Generates Sublime Text 2 project files
(deprecated).
Sublime Text 2 - Ninja = Generates Sublime Text 2 project files
(deprecated).
Sublime Text 2 - Unix Makefiles
= Generates Sublime Text 2 project files
(deprecated).
2.2 指定生成器
默认使用Visual Studio 18 2026生成器,接下来配置为Unix Makefiles和Ninja生成器
2.2.1 Unix Makefiles
使用Unix Makefiles生成器,会生成make需要的构建文件
yinsh@coding4096 /f/cmake_demos/03_CmdArgs
$ cmake -S . -B build -G "Unix Makefiles"
-- The C compiler identification is GNU 15.2.0
-- The CXX compiler identification is GNU 15.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/ucrt64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/ucrt64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (3.2s)
-- Generating done (0.0s)
-- Build files have been written to: F:/cmake_demos/03_CmdArgs/build
2.2.2 Ninja
使用Ninja生成器,会生成ninja需要的构建文件
yinsh@coding4096 /f/cmake_demos/03_CmdArgs
$ cmake -S . -B build -G "Ninja"
-- The C compiler identification is GNU 15.2.0
-- The CXX compiler identification is GNU 15.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/ucrt64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/ucrt64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (2.4s)
-- Generating done (0.0s)
-- Build files have been written to: F:/cmake_demos/03_CmdArgs/build
3. 编译器
编译器路径既可以是:
- 简单的命令名(如
g++):前提是该命令已添加到系统的PATH环境变量中 - 完整的绝对路径
配置完成后,可以使用以下命令看到配置的编译器:
# 列出所有缓存变量
cmake -LA <构建目录>
# 列出所有缓存变量,包括帮助文本
cmake -LAH <构建目录>
3.1 使用g++
yinsh@coding4096 /f/cmake_demos/03_CmdArgs
$ cmake -S . -B build -G "Ninja" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
-- The C compiler identification is GNU 15.2.0
-- The CXX compiler identification is GNU 15.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/ucrt64/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/ucrt64/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (2.4s)
-- Generating done (0.0s)
-- Build files have been written to: F:/cmake_demos/03_CmdArgs/build
3.2 使用clang++
yinsh@coding4096 /f/cmake_demos/03_CmdArgs
$ cmake -S . -B build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
-- The C compiler identification is Clang 21.1.8
-- The CXX compiler identification is Clang 21.1.8
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/ucrt64/bin/clang.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/ucrt64/bin/clang++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (2.6s)
-- Generating done (0.0s)
-- Build files have been written to: F:/cmake_demos/03_CmdArgs/build
4. 编译类型
4.1 简介
CMake支持多种预定义的构建类型,每种类型有不同的编译优化和调试选项,如下:
| 构建类型 | 说明 | 优化 | 调试信息 | 适用场景 |
|---|---|---|---|---|
| Debug | 调试版本 | 无优化 | 完整 | 开发和调试 |
| Release | 发布版本 | 最大优化 | 无 | 生产环境 |
| RelWithDebInfo | 带调试信息的发布版 | 优化 | 有 | 性能分析 |
| MinSizeRel | 最小体积发布版 | 体积优化 | 无 | 嵌入式、移动端 |
编译标志对比:
# GCC/Clang编译器
Debug: -g
Release: -O3 -DNDEBUG
RelWithDebInfo: -O2 -g -DNDEBUG
MinSizeRel: -Os -DNDEBUG
# MSVC编译器
Debug: /MDd /Zi /Ob0 /Od /RTC1
Release: /MD /O2 /Ob2 /DNDEBUG
RelWithDebInfo: /MD /Zi /O2 /Ob1 /DNDEBUG
MinSizeRel: /MD /O1 /Ob1 /DNDEBUG
可以通过-DCMAKE_BUILD_TYPE来指定构建类型,如下:
# Debug构建(开发阶段)
cmake -S . -B build-debug -DCMAKE_BUILD_TYPE=Debug
cmake --build build-debug
# 生成带调试符号的可执行文件,未优化
# Release构建(生产环境)
cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release
cmake --build build-release
# 生成优化的可执行文件,无调试符号
# RelWithDebInfo构建(性能分析)
cmake -S . -B build-profile -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build-profile
# 生成优化的可执行文件,保留调试符号
# MinSizeRel构建(嵌入式)
cmake -S . -B build-small -DCMAKE_BUILD_TYPE=MinSizeRel
cmake --build build-small
# 生成最小体积的可执行文件
配置完成后,可以使用以下命令查看编译标志:
# 列出所有缓存变量
cmake -LA <构建目录>
# 列出所有缓存变量,包括帮助文本
cmake -LAH <构建目录>
查看效果如下:
yinsh@coding4096 /f/cmake_demos/03_CmdArgs/02
$ cmake -LA build/Debug/
-- Configuring done (0.1s)
-- Generating done (0.0s)
-- Build files have been written to: F:/cmake_demos/03_CmdArgs/02/build/Debug
-- Cache values
CMAKE_ADDR2LINE:FILEPATH=C:/msys64/ucrt64/bin/addr2line.exe
CMAKE_AR:FILEPATH=C:/msys64/ucrt64/bin/ar.exe
CMAKE_BUILD_TYPE:STRING=Debug
CMAKE_CXX_COMPILER:STRING=C:/msys64/ucrt64/bin/g++.exe
CMAKE_CXX_COMPILER_AR:FILEPATH=C:/msys64/ucrt64/bin/gcc-ar.exe
CMAKE_CXX_COMPILER_RANLIB:FILEPATH=C:/msys64/ucrt64/bin/gcc-ranlib.exe
CMAKE_CXX_FLAGS:STRING=
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
...
4.2 Debug和Release文件大小
首先,配置Debug版本和Release版本,如下:
# Debug 版本
cmake -S . -B build/Debug -G "Ninja" -DCMAKE_C_COMPILER=gcc \
-DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Debug
# Release 版本
cmake -S . -B build/Release -G "Ninja" -DCMAKE_C_COMPILER=gcc \
-DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release
配置之后,可以使用cmake -LA <构建目录>来查看4个编译类型对应的编译选项。
然后,构建编译出可执行文件:
# Debug 版本
cmake --build build/Debug
# Release 版本
cmake --build build/Release
最后,比较文件大小
yinsh@coding4096 /f/cmake_demos/03_CmdArgs/01
$ ls -l build/Debug/hello.exe build/Release/hello.exe
-rwxr-xr-x 1 yinsh yinsh 175434 2月 25 12:31 build/Debug/hello.exe
-rwxr-xr-x 1 yinsh yinsh 144876 2月 25 12:31 build/Release/hello.exe
4.3 -DNDEBUG宏与assert()断言
-DNDEBUG是C/C++标准库约定的宏,用于控制断言(assertions)的行为,如果定义了NDEBUG这个宏:
assert语句在预处理(-E)阶段被移除- 编译器也就不会编译到
assert语句 - 生成的二进制文件中完全没有
assert相关的代码
在四种预定义的编译类型中,Debug类型下没有NDEBUG这个宏定义,其他3种类型下有。
4.3.1 修改源码
- calc.cpp
#include <cassert>
#include <iostream>
#include <stdexcept>
int divide(int a, int b) {
#ifdef NDEBUG
std::cout << "NDEBUG defined, assert() will be removed" << std::endl;
#endif
// 断言检查(仅 Debug 模式,辅助发现逻辑错误)
assert(b != 0);
if (b == 0) {
throw std::invalid_argument("Divisor is zero");
}
return a / b;
}
- main.cpp
int main() {
// ...
// 除法(包含异常处理)
try {
int result = divide(x, y);
std::cout << x << "/" << y << "=" << result << std::endl;
}
catch (const std::invalid_argument &e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
4.3.2 编译
# Debug编译
cmake -S . -B build/Debug -G "Ninja" -DCMAKE_C_COMPILER=gcc \
-DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Debug
cmake --build build/Debug
# Release编译
cmake -S . -B build/Release -G "Ninja" -DCMAKE_C_COMPILER=gcc \
-DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release
cmake --build build/Release
4.3.3 运行
- 运行Debug版本(除数不为零)
yinsh@coding4096 /f/cmake_demos/03_CmdArgs/02
$ ./build/Debug/hello.exe
Input two integers: 10 5
10+5=15
10-5=5
10*5=50
10/5=2
- 运行Debug版本(除数为零)
yinsh@coding4096 /f/cmake_demos/03_CmdArgs/02
$ ./build/Debug/hello.exe
Input two integers: 10 0
10+0=10
10-0=10
10*0=0
Assertion failed: b != 0, file F:/cmake_demos/03_CmdArgs/02/src/calc.cpp, line 27
- 运行Release版本(除数不为零)
yinsh@coding4096 /f/cmake_demos/03_CmdArgs/02
$ ./build/Release/hello.exe
Input two integers: 10 5
10+5=15
10-5=5
10*5=50
NDEBUG defined, assert() will be removed
10/5=2
- 运行Release版本(除数为零)
yinsh@coding4096 /f/cmake_demos/03_CmdArgs/02
$ ./build/Release/hello.exe
Input two integers: 10 0
10+0=10
10-0=10
10*0=0
NDEBUG defined, assert() will be removed
Error: Divisor is zero
5. 编译选项
可以在执行cmake命令时,在命令行中指定一个自定义的ENABLE_LOG宏,并且在代码中使用这个宏。
5.1 修改main.cpp
在main函数中,根据ENABLE_LOG这个宏是否定义,执行打印语句,如下:
int main() {
int x, y;
std::cout << "Input two integers: ";
std::cin >> x >> y;
#ifdef ENABLE_LOG
std::cout << "===Calc Begin===" << std::endl;
#endif
// 加法
std::cout << x << "+" << y << "=" << add(x, y) << std::endl;
// 减法
std::cout << x << "-" << y << "=" << subtract(x, y) << std::endl;
// 乘法
std::cout << x << "*" << y << "=" << multiply(x, y) << std::endl;
// 除法(包含异常处理)
try {
int result = divide(x, y);
std::cout << x << "/" << y << "=" << result << std::endl;
}
catch (const std::invalid_argument &e) {
std::cerr << "Error: " << e.what() << std::endl;
}
#ifdef ENABLE_LOG
std::cout << "===Calc End===" << std::endl;
#endif
return 0;
}
接下来,在Debug配置时,定义ENABLE_LOG宏,在Release配置时,不定义ENABLE_LOG宏
5.2 定义ENABLE_LOG宏
- 配置、构建
# Debug
cmake -S . -B build/Debug -G "Ninja" -DCMAKE_C_COMPILER=gcc \
-DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-DENABLE_LOG"
cmake --build build/Debug
- 运行
yinsh@coding4096 /f/cmake_demos/03_CmdArgs/03
$ ./build/Debug/hello.exe
Input two integers: 10 5
===Calc Begin===
10+5=15
10-5=5
10*5=50
10/5=2
===Calc End===
5.3 未定义ENABLE_LOG宏
- 配置、构建
cmake -S . -B build/Release -G "Ninja" -DCMAKE_C_COMPILER=gcc \
-DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release
cmake --build build/Release
- 运行
yinsh@coding4096 /f/cmake_demos/03_CmdArgs/03
$ ./build/Release/hello.exe
Input two integers: 10 5
10+5=15
10-5=5
10*5=50
NDEBUG defined, assert() will be removed
10/5=2









