通过CMake定义预处理器宏

问题描述 投票:0回答:6

如何通过 CMake 定义预处理器变量?

等效代码为

#define foo

c++ cmake c-preprocessor
6个回答
529
投票

很长一段时间以来,CMake 都有用于此目的的

add_definitions
命令。然而,最近该命令已被更细粒度的方法取代(用于编译定义、包含目录和编译器选项的单独命令)。

使用新的 add_compile_definitions 的示例:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION})
add_compile_definitions(WITH_OPENCV2)

或者:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION} WITH_OPENCV2)

这样做的好处是,它规避了 CMake 为

add_definitions
所采用的破旧伎俩。 CMake 是一个如此破旧的系统,但他们终于找到了一些理智。

在此处查找有关用于编译器标志的命令的更多说明:https://cmake.org/cmake/help/latest/command/add_definitions.html

同样,您可以按照 Jim Hunziker 的回答中的说明对每个目标执行此操作。


323
投票

要针对特定目标执行此操作,您可以执行以下操作:

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)

如果您正在构建多个目标并且不希望它们全部使用相同的标志,则应该执行此操作。另请参阅有关 target_compile_definitions 的官方文档。


38
投票

本页提出的其他解决方案对于 某些版本的 Cmake >

3.3.2
很有用。这是我正在使用的版本的解决方案(即
3.3.2
)。使用
$ cmake --version
检查 Cmake 的版本,然后选择适合您需求的解决方案。 cmake 文档可以在官方页面上找到。

使用CMake版本3.3.2,才能创建

#define foo

我需要使用:

add_definitions(-Dfoo)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)

并且,为了拥有像另一个这样的预处理器宏定义:

#define foo=5

线路如此修改:

add_definitions(-Dfoo=5)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)

请注意(正如 @squareskittles 在其中一条评论中建议的那样):“如果您使用

CMake 3.3.2
,则必须使用
use add_definitions()
target_compile_definitions()
。更现代的命令
add_compile_definitions()
直到
CMake 3.12
。”


18
投票

1.) target_compile_definitions

如果您使用 CMake 3.X,添加预处理器宏的首选应该是 target_compile_definitions

您应该比任何其他方法更喜欢这种方法的原因是因为它的粒度是基于

target
的。 IE 宏只会添加到您的 exe/库中。

这是一个常见的例子:

if (WIN32)
    target_compile_definitions(my_lib PRIVATE   
       # Prevents Windows.h from adding unnecessary includes    
       WIN32_LEAN_AND_MEAN  
       # Prevents Windows.h from defining min/max as macros 
       NOMINMAX 
    )   
endif() 

2.) add_compile_definitions

3.12版本新增功能。

在此处查找有关用于编译器标志的命令的更多说明:https://cmake.org/cmake/help/latest/command/add_definitions.html

add_compile_definitions 将宏应用于调用后定义的任何目标。

这里的逻辑与上面的 add_compile_definitions 相同。

add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX)
add_library(my_lib)

如果您使用此方法,如果您是“顶级项目”,请小心。 否则,如果用户使用 add_subdirectory 使用您的库,他们可能会遇到问题。 3.)其他不太推荐的方法

这些方法确实不再推荐了。由于不模块化、扩展性不好、不支持生成器表达式等

    添加定义
  • CMAKE_LANG_FLAGS
  • 为什么 target_compile_definitions 更好/更受欢迎?

对于 CMake 代码的读者来说,它是如何工作的更加清楚。
  • 如果需要,允许使用私有/公共/接口。这可以让您图书馆的消费者的生活更轻松。
  • 它更加模块化。
  • 全局应用预处理器标志(或任何编译器标志)可以在构建中创建隐藏的依赖项。

本质上将 add_compile_definitions 视为 C/C++ 中的全局变量。有时您需要它们,但要小心。


3
投票
target_***

操作而不是

add_***
操作。
    


3
投票

标志,此处:BOOST(“真”或“假”)
  • 软件版本字符串(例如:“1.0.0”)
  • 我建议将它们作为字符串传递。 因此,当您使用 CMAKE 构建软件时,您可以传递参数,例如如果它是使用 boost 库构建的,则从 CMAKE 变量中提取软件版本(以便您仅在一处更改该数字) 见下文。

在 CMakeLists.txt 中:

添加编译定义( 升压=“${升压}” Software_VERSION="${PROJECT_VERSION}" )

在您的 .cpp 代码中:

std::cout

希望这有帮助。问候。<< "Software version is: " << Software_VERSION << " BOOST: " << BOOST << "\n";

© www.soinside.com 2019 - 2024. All rights reserved.