通过cmake定义预处理器宏

Myt*_*hli 261 c++ cmake c-preprocessor

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

等效的代码是#define foo.

ypn*_*nos 361

很长一段时间,CMake都有add_definitions这个目的.但是,最近该命令已被更精细的方法取代(编译定义,包含目录和编译器选项的单独命令).

使用新的add_compile_definitions的示例:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION})
add_compile_definitions(WITH_OPENCV2)
Run Code Online (Sandbox Code Playgroud)

要么:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION} WITH_OPENCV2)
Run Code Online (Sandbox Code Playgroud)

关于这一点的好处是它绕开了CMake已经到位的破旧诡计add_definitions.CMake是一个如此破旧的系统,但他们终于找到了一些理智.

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

同样,你可以按照Jim Hunziker的回答中所解释的那样按目标执行此操作.

  • 在cmake 3.10.2中,“ add_compile_definitions”会在CMakeLists.txt:6(add_compile_definitions)上抛出“ CMake错误”:未知的CMake命令“ add_compile_definitions”。必须使用`add_compile_options(-D <your-def>)`。 (9认同)
  • 从链接页面:"注意此命令已被替代选项取代:使用add_compile_definitions()添加预处理程序定义." 也许这个答案需要编辑? (4认同)
  • @mannyglover我不这么认为,但是您可以使用-D来设置编译器标志,类似于`cmake -D CMAKE_CXXFLAGS ='-DDEBUG_CHESSBOARD'`(未经测试) (2认同)
  • 它真的很新……事实上它在更现代的 CMake (> 3.11) 中。很难知道何时引入命令的痛苦。 (2认同)

Jim*_*ker 228

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

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)
Run Code Online (Sandbox Code Playgroud)

如果您正在构建多个目标并且不希望它们都使用相同的标志,则应该执行此操作.

  • @JimHunziker `target_compile_definitions(my_target PRIVATE FOO=1)` 与 `set_source_files_properties(foo.cpp PROPERTIES COMPILE_DEFINITIONS -DFOO=1)` 有何不同? (2认同)

小智 19

1.) 目标编译定义

如果您使用 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() 
Run Code Online (Sandbox Code Playgroud)

2.) 添加编译定义

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)
Run Code Online (Sandbox Code Playgroud)

如果您使用此方法,并且您是顶级项目,请务必小心。否则,如果用户使用add_subdirectory使用您的库,他们可能会遇到问题。

3.) 其他不太推荐的方法

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

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

  • CMake 代码的读者可以更清楚地了解其工作原理。
  • 如果需要,允许使用私有/公共/接口。这可以让您的图书馆用户的生活更加轻松。
  • 它更加模块化。

全局应用预处理器标志(或任何编译器标志)可以在构建中创建隐藏的依赖项。

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


Leo*_*313 13

此页面上提出的其他解决方案仅适用于Cmake的旧版本.这是新版本的解决方案.使用$ cmake --version并选择符合您需求的解决方案,检查您的Cmake版本.该cmake的文档可在官方网页上找到.

使用CMake版本3.3.2,以便创建

#define foo
Run Code Online (Sandbox Code Playgroud)

我需要使用:

add_definitions(-Dfoo)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)
Run Code Online (Sandbox Code Playgroud)

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

#define foo=5
Run Code Online (Sandbox Code Playgroud)

这条线是如此修改:

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

  • 根据[文档](https://cmake.org/cmake/help/latest/command/add_definitions.html),这个解决方案实际上是更旧、更过时的方法。其他答案提供了更现代的解决方案。 (5认同)
  • 如果您使用的是 CMake 3.3.2,正如您在答案中指出的那样,您必须使用 `add_definitions()` 或 `target_compile_definitions()`。直到 CMake 3.12 才添加更现代的命令“add_compile_definitions()”。@Leos313 (3认同)
  • 当我写下答案时,我确实尝试了其他解决方案,但它们都不起作用。 (2认同)