当前位置: 首页 > news >正文

CMake 宏定义与条件编译

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

八、关键注意事项

  1. 宏定义作用域add_definitions() 对所有目标生效,若只想对特定目标生效,建议使用 target_compile_definitions()
  2. 宏名冲突:避免定义与系统或第三方库同名的宏,防止意外覆盖。
  3. 条件编译调试:可通过 message(STATUS) 在 CMake 中打印宏定义状态,方便调试。
http://www.jsqmd.com/news/873385/

相关文章:

  • 2026年阿里云OpenClaw/Hermes Agent配置Token Plan集成新手必看
  • MATLAB文件读写避坑指南:从fopen到fprintf,搞定数据导入导出与日志记录
  • 告别建模苦手!用ContextCapture Center 10.20.1把航拍图变3D模型(附避坑指南)
  • 五家可承接OEM的尿布台生产工厂信息整理 - 品牌测评鉴赏家
  • 保姆级教程:用GetOrganelle组装叶绿体基因组后,如何用自研脚本搞定四分体结构鉴定与序列调整
  • 实战复盘:我们如何在管理后台优雅地给 Ant Design Vue 3.x 的 Table 加上分页合计行
  • PINN实战:为什么用Tanh激活函数?Burgers方程求解中的神经网络设计细节剖析
  • 2026年腾讯云OpenClaw/Hermes Agent配置Token Plan集成新手必看
  • E.位运算-异或:2588. 统计美丽子数组数目
  • 一文讲透AI时代的神器-Cursor
  • 西恩士液冷清洁度分析设备、检测设备与颗粒萃取设备 - 工业设备研究社
  • C++深入讲解类与封装的概念与使用
  • 2026年腾讯云OpenClaw/Hermes Agent配置Token Plan部署保姆级教程
  • YAML配置文件智能编辑技术方案:Red Hat专业工具提升开发效率
  • 2026年腾讯云OpenClaw/Hermes Agent配置Token Plan部署操作全解
  • 用LabVIEW和USRP玩转高阶QAM:从16QAM到1024QAM的星座图调试实战
  • 别再被Elsevier投稿系统坑了!手把手教你搞定LaTeX文件上传与elsarticle.cls版本兼容问题
  • 尿布台ODM领域的几家代表性生产企业 - 品牌测评鉴赏家
  • Midjourney复古出图率暴跌47%?紧急修复:V6.2新增--style retro v2.1底层协议兼容补丁(含3个必启开关)
  • 2026年京东云OpenClaw/Hermes Agent配置Token Plan部署操作全解
  • 范式锁定与认知殖民:全球AI大停滞时代的中国突围与“贾子之路”重构
  • 3个关键技巧:如何用SleeperX实现macOS智能睡眠管理的高效控制
  • 告别空引用恐慌:一份给C#开发者的Visual Studio编译器警告‘消警’保姆级清单
  • 认知主权视域下AI范式危机与中国突围:基于“贾子之路”的文明重构路径研究
  • 分享今日日常
  • 2026年京东云OpenClaw/Hermes Agent配置Token Plan搭建流程全公开
  • 别再死记硬背了!用ChatGPT当你的ReactJS私人教练,5天搞定组件和状态
  • 别再只用L.polygon了!用Leaflet + GeoJSON处理复杂行政区遮罩(含飞地、嵌套洞)
  • 6招搞定创新文化|干货必看
  • SpringBoot项目里,如何让ShardingSphere 5.x和dynamic-datasource和平共处?一个配置类搞定混合数据源