CMake 宏定义与条件编译
CMake 宏定义与条件编译 完整笔记
一、核心概念:什么是宏定义?
宏定义是 C/C++ 中通过 #define 定义的预处理指令,可用于:
- 控制代码是否编译(条件编译)
- 定义常量、开关、版本号等
- 调试/发布版本的差异化构建
在 CMake 中,我们可以通过 add_definitions() 向编译器传递宏定义,无需修改源码即可控制代码行为。
二、源码示例(条件编译)
test.c / test.cpp
#include <stdio.h>#define NUMBER 3int main()
{int a = 10;#ifdef DEBUGprintf("我是一个程序猿,我不会爬树...\n");
#endiffor(int i=0; i<NUMBER; i++){printf("hello, GCC!!!\n");}return 0;
}
#ifdef DEBUG:如果定义了DEBUG宏,才会执行printf语句,否则相当于注释。NUMBER:通过宏定义控制循环次数,可在编译时修改。
三、手动编译指定宏(gcc/g++ 方式)
语法
gcc test.c -DDEBUG -o app
-D参数:向编译器传递宏定义,相当于在代码中写#define DEBUG。- 运行时会输出调试信息,去掉
-DDEBUG则不会输出。
示例
# 带 DEBUG 宏编译
gcc test.c -DDEBUG -o app
./app
# 输出:
# 我是一个程序猿,我不会爬树...
# hello, GCC!!!
# hello, GCC!!!
# hello, GCC!!!# 不带 DEBUG 宏编译
gcc test.c -o app
./app
# 输出:
# hello, GCC!!!
# hello, GCC!!!
# hello, GCC!!!
四、CMake 中指定宏:add_definitions()
语法
add_definitions(-D宏名[=值])
- 功能:向编译器传递宏定义,和
gcc -D效果一致。 - 注意:宏名前必须加
-D,多个宏用空格分隔。
示例 CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(test)# 定义 DEBUG 宏
add_definitions(-DDEBUG)# 也可以定义带值的宏
add_definitions(-DNUMBER=5)add_executable(app test.cpp)
编译运行
mkdir build && cd build
cmake ..
make
./app
输出会包含调试信息,且循环次数为 5(由 NUMBER=5 控制)。
五、常用场景与扩展
1. 调试/发布版本控制
# 调试版本:定义 DEBUG 宏,开启日志
add_definitions(-DDEBUG -DLOG_LEVEL=3)# 发布版本:不定义 DEBUG 宏,关闭日志
# add_definitions(-DNDEBUG -DLOG_LEVEL=0)
2. 平台差异化构建
if(WIN32)add_definitions(-DPLATFORM_WINDOWS)
elseif(UNIX)add_definitions(-DPLATFORM_LINUX)
endif()
3. 版本号控制
add_definitions(-DVERSION_MAJOR=1 -DVERSION_MINOR=2)
六、预定义宏
CMake 提供了一些内置宏,可直接在代码中使用:
| 宏名 | 功能 |
|---|---|
PROJECT_SOURCE_DIR |
CMake 命令所在目录(工程根目录) |
PROJECT_BINARY_DIR |
执行 CMake 命令的目录(构建目录) |
CMAKE_BUILD_TYPE |
构建类型(Debug/Release) |
示例:
#include <stdio.h>int main()
{printf("Project source dir: %s\n", PROJECT_SOURCE_DIR);printf("Build type: %s\n", CMAKE_BUILD_TYPE);return 0;
}
七、完整示例输出
运行上述 CMake 项目后,终端会输出:
[ 50%] Building CXX object CMakeFiles/app.dir/test.cpp.o
[100%] Linking CXX executable app
[100%] Built target app./app
我是一个程序猿,我不会爬树...
hello, GCC!!!
hello, GCC!!!
hello, GCC!!!
hello, GCC!!!
hello, GCC!!!
Project source dir: /home/user/test
Build type: Debug
八、关键注意事项
- 宏定义作用域:
add_definitions()对所有目标生效,若只想对特定目标生效,建议使用target_compile_definitions()。 - 宏名冲突:避免定义与系统或第三方库同名的宏,防止意外覆盖。
- 条件编译调试:可通过
message(STATUS)在 CMake 中打印宏定义状态,方便调试。
