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

CMake指令:add_definitions

目录

1.简介

2.常见用法

3.与其他指令的对比

4.局限性

5.使用建议

6.总结


1.简介

        add_definitions 命令在CMake中用于向编译器添加预处理器宏定义‌,翻译成中文可以理解为“添加定义”或“添加预处理器定义”。这个命令通过添加-D标志来定义宏(如 g++ -DDEBUG)。这些宏可以在编译源文件时使用,以便在代码中进行条件编译或设置特定的编译选项‌。这些宏会作用于当前目录及所有子目录的所有目标(包括可执行文件和库)。
    基本语法:

add_definitions(-DDEFINITION1 -DDEFINITION2 ...)
  • -D 前缀:必须显式指定,用于定义宏(类似编译器命令行参数)。
  • 宏值:若未指定值,默认值为 1(如 -DDEBUG 等价于 #define DEBUG 1)。

2.常见用法

1.定义简单宏

add_definitions(-DDEBUG)  # 等价于 #define DEBUG 1
add_definitions(-DVERSION=\"1.0.0\")  # 等价于 #define VERSION "1.0.0"

2.条件定义

if(WIN32)add_definitions(-DWINDOWS)  # Windows 平台专用宏
elseif(APPLE)add_definitions(-DMACOS)    # macOS 平台专用宏
else()add_definitions(-DLINUX)    # Linux 平台专用宏
endif()

3.传递 CMake 变量到源代码

set(PROJECT_VERSION "1.2.3")
add_definitions(-DPROJECT_VERSION="${PROJECT_VERSION}")  # 将 CMake 变量传递给源码

源码中就可以这样引用:

#include <iostream>int main() {std::cout << "*** test begin ***" << std::endl;#ifdef PROJECT_VERSIONstd::cout << "PROJECT_VERSION= " << PROJECT_VERSION<< std::endl;
#endifstd::cout << "*** test end ***" << std::endl;return 0;
}

3.与其他指令的对比

指令作用范围推荐场景
add_definitions全局(当前目录及所有子目录)项目全局需要的宏(如平台相关定义)
target_compile_definitions仅针对指定目标为特定目标设置私有或公共宏
set(CMAKE_C_FLAGS ...)全局编译选项直接修改编译器标志(不推荐优先使用)

add_definitions与target_compile_definitions详细区别:

核心区别对比

特性add_definitionstarget_compile_definitions
作用范围全局(当前目录及所有子目录)仅针对指定目标(如 add_executable 或 add_library 定义的目标)
作用域控制无(所有目标强制继承)支持 PRIVATE/PUBLIC/INTERFACE 精细控制
传递性自动传递给所有依赖项仅 PUBLIC/INTERFACE 属性传递给依赖项
现代 CMake 推荐度不推荐(旧版指令)推荐(更灵活、更安全)
典型场景项目全局宏(如平台定义)为特定目标设置私有或公共宏

1.add_definitions:全局定义宏

  • 功能:为当前目录及所有子目录中的所有目标添加预处理器宏。
  • 缺点:缺乏作用域控制,可能导致宏冲突(如不同库需要同名但不同值的宏)。

示例:

add_definitions(-DDEBUG)  # 全局定义 DEBUG 宏add_executable(my_app main.cpp)
add_library(my_lib STATIC lib.cpp)# 结果:my_app 和 my_lib 都将定义 DEBUG 宏

2.target_compile_definitions:目标级宏控制

  • 功能:为特定目标添加预处理器宏,并支持通过 PRIVATE/PUBLIC/INTERFACE 控制宏的传递性。
  • 优势:避免全局污染,精确控制哪些宏被传递给依赖项。

示例:

add_library(my_lib STATIC lib.cpp)
target_compile_definitions(my_libPRIVATE -DENABLE_INTERNAL_LOGGING  # 仅 my_lib 可见PUBLIC -DUSE_MY_LIB_API=1          # my_lib 和依赖它的目标可见
)add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE my_lib)  # my_app 继承 USE_MY_LIB_API 宏# 结果:
# - my_lib 同时定义 ENABLE_INTERNAL_LOGGING 和 USE_MY_LIB_API
# - my_app 仅定义 USE_MY_LIB_API(不继承 ENABLE_INTERNAL_LOGGING)

3.传递性对比

add_definitions 的隐式传递

add_definitions(-DVERSION="1.0.0")  # 全局定义add_library(my_lib STATIC lib.cpp)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE my_lib)# 结果:
# - my_lib 和 my_app 都自动定义 VERSION 宏
# - 无法控制哪些依赖项继承该宏

target_compile_definitions 的显式传递

add_library(my_lib STATIC lib.cpp)
target_compile_definitions(my_libINTERFACE -DUSE_MY_LIB=1  # 仅传递给依赖项,不用于编译 my_lib 自身
)add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE my_lib)  # my_app 继承 USE_MY_LIB 宏# 结果:
# - my_lib 自身不定义 USE_MY_LIB
# - my_app 定义 USE_MY_LIB

总结

场景推荐指令
为特定目标设置私有宏target_compile_definitions(... PRIVATE ...)
为特定目标设置公共宏(传递给依赖项)target_compile_definitions(... PUBLIC ...)
定义纯接口库的宏target_compile_definitions(... INTERFACE ...)
项目全局宏(如平台定义)add_definitions(谨慎使用)

4.局限性

1.全局作用域

  • 宏会应用于所有目标,可能导致意外冲突(如不同库需要同名但不同值的宏)。

2.难以控制传递性

  • 无法区分宏是 PRIVATE(仅当前目标使用)还是 PUBLIC(传递给依赖方)。

3.现代替代方案

CMake 推荐使用 target_compile_definitions 替代,因为它支持更精确的作用域控制:

# 仅对 my_target 生效,不影响其他目标
target_compile_definitions(my_target PRIVATE -DDEBUG)# 对 my_target 生效,并传递给依赖 my_target 的目标
target_compile_definitions(my_target PUBLIC -DUSE_FEATURE_X)

5.使用建议

1.优先使用 target_compile_definitions

  • 避免全局污染,提高代码可维护性。

2.仅在必要时使用 add_definitions

  • 例如,定义整个项目都需要的平台相关宏(如 _WIN32__APPLE__)。

3.避免硬编码宏值

优先通过 CMake 变量传递值,如:

set(ENABLE_LOGGING ON)
if(ENABLE_LOGGING)add_definitions(-DENABLE_LOGGING)
endif()

示例:结合 option 使用

option(ENABLE_DEBUG "Enable debug mode" OFF)if(ENABLE_DEBUG)add_definitions(-DDEBUG)  # 全局定义 DEBUG 宏
endif()add_executable(my_app main.cpp)

在代码中使用:

#ifdef DEBUG#define LOG(msg) std::cout << "[DEBUG] " << msg << std::endl
#else#define LOG(msg)
#endif

6.总结

  • 功能:全局添加预处理器宏,等效于编译器的 -D 选项。
  • 缺点:作用域不可控,可能导致宏冲突。
  • 替代方案:优先使用 target_compile_definitions 实现更精细的宏管理。

通过合理使用 add_definitions 和 target_compile_definitions,可有效控制预处理器宏的作用范围,提高项目的模块化程度。

相关链接

  • CMake 官网 CMake - Upgrade Your Software Build System
  • CMake 官方文档:CMake Tutorial — CMake 4.0.2 Documentation
  • CMake 源码:https://github.com/Kitware/CMake
  • CMake 源码:Sign in · GitLab
http://www.xdnf.cn/news/12307.html

相关文章:

  • Profinet转CAN网关与西门子PLC的互联互通基础操作流程
  • 二叉树的遍历总结
  • 统信桌面专业版如何使用python开发平台jupyter
  • Kotlin 2.1 一元二次方程(顺序结构版)
  • three.js中使用tween.js的chain实现动画依次执行
  • 第09期_网站搭建_卡密验证 易如意1.71正式版 虚拟主机搭建笔记 软件卡密系统
  • 嵌入式学习 D33:系统编程--网路编程
  • dvwa12——XSS(Stored)
  • 回文数 - 力扣
  • Vue Router的核心实现原理深度解析
  • Python训练营打卡 Day45
  • RAID磁盘阵列
  • 算法:前缀和
  • 动态规划---股票问题
  • Job 运维类
  • JAVA数据库连接
  • Rocketmq消息队列 消息模型 详解
  • [蓝桥杯]全球变暖
  • Filebeat收集nginx日志到elasticsearch,最终在kibana做展示(二)
  • Next-AI聊天应用-复用chat组件
  • 数据炼金术:电商突围的智能决策革命
  • [闭源saas选项]Pinecone:为向量数据库而生的实时语义搜索引擎
  • OMS主动运维服务:赋能中小企业运维价值升级
  • Java类加载过程
  • 使用子树合并策略更新git项目的部分目录
  • ignore文件不生效的问题
  • 初识硬编码(x86指令描述)
  • 代码随想录算法训练营第九天| 151.翻转字符串里的单词、55.右旋转字符串 、字符串总结
  • CLIP多模态大模型的优势及其在边缘计算中的应用
  • 实时云渲染解决UE像素流送无法进行二次开发的问题