问答中心分类: C++通过 CMake 定义预处理器宏?
0
匿名用户 提问 7小时 前

如何通过 CMake 定义预处理器变量?
等效的代码是#define foo.

5 Answers
0
Jim Hunziker 回答 7小时 前

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

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)

如果您要构建多个目标并且不希望它们都使用相同的标志,则应该这样做。另见官方文档目标编译定义.

John Strood 回复 7小时 前

@JimHunziker 怎么样target_compile_definitions(my_target PRIVATE FOO=1)不同于set_source_files_properties(foo.cpp PROPERTIES COMPILE_DEFINITIONS -DFOO=1)?

Julian Kirsch 回复 7小时 前

@JohnStrood 区别在于范围级别。target_compile_definitions设置整个可执行文件/库的值,其中“set_source_files_properties”仅为指定文件设置值。后一个命令允许使用不同的语言编译文件; IE:set_source_files_properties(compile_me_as_objc.c PROPERTIES -x objective-c.注意-x objective-c这是特定于 GCC/Clang 的标志。

0
Leos313 回答 7小时 前

此页面上提出的其他解决方案对某些版本的 Cmake >3.3.2.这是我正在使用的版本的解决方案(即,3.3.2)。使用检查您的 Cmake 的版本$ cmake --version并选择适合您需求的解决方案。这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。”

Kevin 回复 7小时 前

根据文件,这个解决方案实际上是更老、更过时的方法。其他答案提供了更现代的解决方案。

Leos313 回复 7小时 前

当我写下答案时,我确实尝试了其他解决方案,但它们都不起作用。

Leos313 回复 7小时 前

@squareskittles,知道为什么其他答案的解决方案不能正常工作吗?如果我尝试,CMake 会出错

Kevin 回复 7小时 前

如果您使用的是 CMake 3.3.2,正如您在回答中指出的那样,您必须使用add_definitions()或者target_compile_definitions().更现代的命令,add_compile_definitions(), 直到 CMake 3.12 才添加。 @Leos313

Leos313 回复 7小时 前

@squareskittles,对!用您的信息更新答案!

0
user15308163user15308163 回答 7小时 前

1.) target_compile_definitions
如果您使用的是 CMake 3.X,则添加预处理器宏的首选应该是目标编译定义.
您应该比任何其他方法更喜欢这种方法的原因是因为它的粒度是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)

如果您使用这种方法,请小心,如果您是顶级项目.否则,如果用户使用您的库使用添加子目录他们可能有问题。
3.) 其他不太推荐的方式
这些方法真的不再推荐了。由于不是模块化的,不能很好地扩展,不支持生成器表达式等。

为什么 target_compile_definitions 更好/更受欢迎?

  • CMake 代码的读者更清楚它是如何工作的。
  • 如果需要,允许使用 PRIVATE/PUBLIC/INTERFACE。这可以使您图书馆的消费者的生活更轻松。
  • 它更加模块化。

全局应用预处理器标志(或任何编译器标志)可以在您的构建中创建隐藏的依赖项。
本质上将 add_compile_definitions 视为 C/C++ 中的全局变量。有时你需要它们,但要小心。

0
degawong 回答 7小时 前

我想推荐使用target_***操作而不是add_***当您的解决方案包含许多项目时的操作。

0
THor 回答 7小时 前

这是一个示例,您可以将值从 CMAKE 传递到 C++ 代码。说,你想通过:

  • 标志,此处:BOOST(“真”或“假”)
  • 软件版本字符串(例如:“1.0.0”)

我建议将它们作为字符串传递。因此,当您使用 CMAKE 构建软件时,您可以传递参数,例如,如果它是使用 boost 库构建的,则从 CMAKE 变量中提取软件版本(以便您仅在一处更改该数字)见下文。
在 CMakeLists.txt 中:
add_compile_definitions( BOOST=&quot;${BOOST}&quot; Software_VERSION=&quot;${PROJECT_VERSION}&quot; )
在您的 .cpp 代码中:
std::cout &lt;&lt; &quot;软件版本为:&quot; &lt;&lt; Software_VERSION &lt;&lt; &quot; BOOST: &quot; &lt;&lt; BOOST &lt;&lt; &quot;\n&quot;;
希望这可以帮助。问候。