ChatGPT解决这个技术问题 Extra ChatGPT

通过 CMake 定义预处理器宏?

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

等效代码为 #define foo


j
jww

很长一段时间以来,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 的回答中的说明对每个目标执行此操作。


从链接页面:“注意此命令已被替代命令取代:使用 add_compile_definitions() 添加预处理器定义。”也许这个答案需要编辑?
在 cmake 3.10.2 中,add_compile_definitions 抛出 CMake Error at CMakeLists.txt:6 (add_compile_definitions): Unknown CMake command "add_compile_definitions".。不得不改用 add_compile_options(-D <your-def>)
@mannygover 我不这么认为,但是您可以使用 -D 设置编译器标志,类似于 cmake -D CMAKE_CXXFLAGS='-DDEBUG_CHESSBOARD' (未经测试)
它真的很新……事实上它在更现代的 CMake (> 3.11) 中。很难知道何时引入了命令。
@Sandburg 您可以打开指向最后一个文档的链接:https://cmake.org/cmake/help/v3.17/command/add_compile_definitions.html#command:add_compile_definitions 并开始向下更改版本号,直到页面消失。那将是它尚不存在的版本。在下一步中,您可以转到 Whats new 部分来查找新的命令或功能。所以它不是那么难。
e
erenon

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

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)

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


@JimHunziker target_compile_definitions(my_target PRIVATE FOO=1)set_source_files_properties(foo.cpp PROPERTIES COMPILE_DEFINITIONS -DFOO=1) 有何不同?
@JohnStrood 区别在于范围级别。 target_compile_definitions 设置整个可执行文件/库的值,其中“set_source_files_properties”仅设置指定文件的值。后一个命令允许使用不同的语言编译文件;即:set_source_files_properties(compile_me_as_objc.c PROPERTIES -x objective-c。请注意,此处的 -x objective-c 是特定于 GCC/Clang 的标志。
L
Leos313

此页面上提出的其他解决方案对于某些版本的 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 才添加。”


根据 documentation,此解决方案实际上是更旧、更过时的方法。其他答案提供了更现代的解决方案。
当我写下答案时,我确实尝试了其他解决方案,但它们都不起作用。
@squareskittles,知道为什么其他答案的解决方案不能正常工作吗?如果我尝试,CMake 会出错
如果您使用 CMake 3.3.2,如您在回答中指出的那样,您必须使用 add_definitions()target_compile_definitions()。直到 CMake 3.12 才添加更现代的命令 add_compile_definitions()。 @Leos313
@squareskittles,对!用您的信息更新答案!
佚名

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)

如果您使用这种方法,如果您是 top level project,请小心。否则,如果用户使用 add_subdirectory 使用您的库,他们可能会遇到问题。

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

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

添加定义

CMAKE_LANG_FLAGS

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

CMake 代码的读者更清楚它是如何工作的。

如果需要,允许使用 PRIVATE/PUBLIC/INTERFACE。这可以使您图书馆的消费者的生活更轻松。

它更加模块化。

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

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


d
degawong

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


T
THor

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

标志,此处:BOOST(“真”或“假”)

软件版本字符串(例如:“1.0.0”)

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

在 CMakeLists.txt 中:

add_compile_definitions( BOOST="${BOOST}" Software_VERSION="${PROJECT_VERSION}" )

在您的 .cpp 代码中:

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

希望这可以帮助。问候。