【发布时间】:2012-02-19 12:20:30
【问题描述】:
如何通过 CMake 定义预处理器变量?
等效代码是#define foo。
【问题讨论】:
标签: c++ cmake c-preprocessor
如何通过 CMake 定义预处理器变量?
等效代码是#define foo。
【问题讨论】:
标签: c++ cmake c-preprocessor
很长一段时间以来,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 Error at CMakeLists.txt:6 (add_compile_definitions): Unknown CMake command "add_compile_definitions".。不得不改用add_compile_options(-D <your-def>)。
cmake -D CMAKE_CXXFLAGS='-DDEBUG_CHESSBOARD'(未测试)
https://cmake.org/cmake/help/v3.17/command/add_compile_definitions.html#command:add_compile_definitions 并开始向下更改版本号,直到页面消失。那将是它尚不存在的版本。在下一步中,您可以转到Whats new 部分以查找新命令或功能。所以这并不难。
要针对特定目标执行此操作,您可以执行以下操作:
target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)
如果您要构建多个目标并且不希望它们都使用相同的标志,则应该这样做。另请参阅target_compile_definitions 上的官方文档。
【讨论】:
target_compile_definitions(my_target PRIVATE FOO=1) 与 set_source_files_properties(foo.cpp PROPERTIES COMPILE_DEFINITIONS -DFOO=1) 有何不同?
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 的标志。
本页提出的其他解决方案对某些版本的 Cmake >
3.3.2很有用。这是我正在使用的版本的解决方案(即3.3.2)。使用$ cmake --version检查您的 Cmake 版本,然后选择适合您需求的解决方案。 cmake documentation可以在官网找到。
使用 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()。更现代的命令,@ 987654333@,直到CMake 3.12 才添加。”
【讨论】:
add_definitions() 或 target_compile_definitions()。直到 CMake 3.12 才添加更现代的命令 add_compile_definitions()。 @Leos313
当您的解决方案包含许多项目时,我建议使用 target_*** 操作而不是 add_*** 操作。
【讨论】:
如果您使用的是 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()
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 使用您的库,他们可能会遇到问题。
这些方法真的不再推荐了。由于没有模块化,扩展性不好,不支持生成器表达式等。
全局应用预处理器标志(或任何编译器标志)可以在您的构建中创建隐藏的依赖关系。
基本上将 add_compile_definitions 视为 C/C++ 中的全局变量。有时您需要它们,但要小心。
【讨论】:
这是一个示例,您可以将值从 CMAKE 传递到 C++ 代码。说,你想通过:
我建议将它们作为字符串传递。 因此,当您使用 CMAKE 构建软件时,您可以传递参数,例如,如果它是使用 boost 库构建的,则从 CMAKE 变量中提取软件版本(这样您只能在一个地方更改该数字) 见下文。
在 CMakeLists.txt 中:
add_compile_definitions( 升压=“${升压}” Software_VERSION="${PROJECT_VERSION}" )
在您的 .cpp 代码中:
std::cout
希望这会有所帮助。问候。
【讨论】: