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

等效的代码是#define foo。


当前回答

在很长一段时间里,CMake使用add_definitions命令来实现这个目的。然而,最近该命令已被一种更细粒度的方法所取代(用于编译定义、包括目录和编译器选项的单独命令)。

使用新的add_compile_definitions的示例:

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

Or:

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的回答中这样做。

其他回答

这里有一个例子,你可以将值从CMAKE传递到c++代码。比如说,你想通过:

BOOST ("true"或"false") 软件版本字符串(例如:"1.0.0")

我建议将它们作为字符串传递。 所以,当你用CMAKE构建软件时,你可以传递参数,例如,如果它是使用boost库构建的,从CMAKE变量中提取的软件版本(这样你只在一个地方改变这个数字) 见下文。

在CMakeLists.txt:

add_compile_definitions ( 提高= " ${提高}” Software_VERSION = " $ {PROJECT_VERSION}” )

在你的.cpp代码中:

std::cout << "软件版本为:" << Software_VERSION << " BOOST: " << BOOST << "\n";

希望这能有所帮助。的问候。

1) target_compile_definitions

如果您正在使用CMake 3。X您添加预处理器宏的第一选择应该是target_compile_definitions。

您应该选择这种方法而不是其他方法的原因是,它的粒度是基于目标的。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)。其他不太推荐的方法

这些方法真的不再被推荐了。由于不是模块化的,不能很好地伸缩,不支持生成器表达式等。

add_definitions CMAKE_LANG_FLAGS

为什么target_compile_definitions更好/首选?

对于CMake代码的读者来说,它是如何工作的要清楚得多。 如果需要,允许使用PRIVATE/PUBLIC/INTERFACE。这可以使您的图书馆的消费者的生活更容易。 它更加模块化。

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

从本质上讲,在C/ c++中将add_compile_definitions视为全局变量。有时你需要他们,但要小心。

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

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)

如果您有多个正在构建的目标,并且不希望它们都使用相同的标志,则应该这样做。请参阅有关target_compile_definitions的官方文档。

在很长一段时间里,CMake使用add_definitions命令来实现这个目的。然而,最近该命令已被一种更细粒度的方法所取代(用于编译定义、包括目录和编译器选项的单独命令)。

使用新的add_compile_definitions的示例:

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

Or:

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的回答中这样做。

本页上提出的其他解决方案适用于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,你必须使用add_definitions()或target_compile_definitions()。更现代的命令add_compile_definitions()直到CMake 3.12才被添加。”