【问题标题】:Easier/terser mechanism for translating CMake option into preprocessor definitions?将 CMake 选项转换为预处理器定义的更简单/更简洁的机制?
【发布时间】:2021-09-10 22:53:19
【问题描述】:

我发现自己在CMakeLists.txt 中重复了以下代码段:

option(SOME_OPT "Some option" ON)
if (SOME_OPT)
    target_compile_definitions(my_app SOME_IDENTIFIER_HERE_RELATED_TO_OPT)
endif()

(偶尔会有类似的东西,但带有 -D 的字符串值)。

CMake 中是否有一种机制(不管版本)使这更容易或更简洁?

【问题讨论】:

  • 你总是可以定义一个宏:macro(my_add_option OPTION DOC DEFAULT) option(${OPTION} ${DOC} ${DEFAULT}) if (${OPTION}) add_definitions(${ARGN}) endif() endmacro()my_add_option(SOME_OPT "Some option" ON -DSOME_IDENTIFIER_HERE_RELATED_TO_OPT) my_add_option(FOO_OPT "foo option" ON FOO=1 BAR=0)
  • @fabian - 最好将其作为一个函数来避免变量范围问题。

标签: cmake definition cmake-cache


【解决方案1】:

选项 1:使用生成器表达式

这是使用目标属性和生成器表达式的一个选项:

option(SOME_OPT1 "Some option 1" ON)
option(SOME_OPT2 "Some option 2" OFF)
option(SOME_OPT3 "Some option 3" ON)

target_compile_definitions(my_app PRIVATE
  $<$<BOOL:${SOME_OPT1}>:SOME_IDENTIFIER_HERE_RELATED_TO_OPT1>
  $<$<BOOL:${SOME_OPT2}>:SOME_IDENTIFIER_HERE_RELATED_TO_OPT2>
  $<$<BOOL:${SOME_OPT3}>:SOME_IDENTIFIER_HERE_RELATED_TO_OPT3>
)

$&lt;BOOL:${var}&gt; 舞蹈对于将真/假 CMake 值转换为 10 是必要的,正如生成器表达式迷你语言所期望的那样。

选项 2:生成的“配置文件”

如果您有很多这样的选项,另一种选择是使用configure_file 命令创建包含相关信息的标题。创建一个名为 config.h.in 的标头(作为示例),其内容如下:

#ifndef MYPROJ_CONFIG_H
#define MYPROJ_CONFIG_H

#cmakedefine SOME_IDENTIFIER_HERE_RELATED_TO_OPT1
#cmakedefine SOME_IDENTIFIER_HERE_RELATED_TO_OPT2
#cmakedefine01 SOME_IDENTIFIER_HERE_RELATED_TO_OPT3

#endif

#cmakedefine VAR 指令由 configure_file 处理以设置 VAR 如果在 CMakeLists.txt 中将 VAR 定义为真实值,则注释掉该行。 01 变体始终定义 VAR,但将其设置为 01

然后在你的 CMakeLists.txt 你可以写:

option(SOME_OPT1 "Some option 1" ON)
option(SOME_OPT2 "Some option 2" OFF)
option(SOME_OPT3 "Some option 3" ON)

# Setting these variables exposes them to configure_file below
set(SOME_IDENTIFIER_HERE_RELATED_TO_OPT1 "${SOME_OPT1}")
set(SOME_IDENTIFIER_HERE_RELATED_TO_OPT2 "${SOME_OPT2}")
set(SOME_IDENTIFIER_HERE_RELATED_TO_OPT3 "${SOME_OPT3}")

configure_file(config.h.in config.h)

target_include_directories(my_app PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")

然后您的源文件可以#include &lt;config.h&gt;,默认情况下是:

#ifndef MYPROJ_CONFIG_H
#define MYPROJ_CONFIG_H

#define SOME_IDENTIFIER_HERE_RELATED_TO_OPT1
/* #undef SOME_IDENTIFIER_HERE_RELATED_TO_OPT2 */
#define SOME_IDENTIFIER_HERE_RELATED_TO_OPT3 1

#endif

这两个选项每个选项都会花费一行开销,尽管第一种方法有点吵,而第二种方法会花费一个文件。但是,第二种方法允许您添加额外的预处理器代码,这些代码可能更好地放在配置文件中。它还可以通过 @VAR@ 语法替换 CMake 变量 values。有关详细信息,请参阅文档:https://cmake.org/cmake/help/latest/command/configure_file.html

【讨论】:

  • Alex - 我修改了问题,使其具有特定于目标的编译定义,因为我不想在这个问题上“搅浑水”。对于那个很抱歉;我只是问避免重复输入。
  • @einpoklum - 我已将我的答案编辑为我建议的两种方法。
猜你喜欢
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-08
  • 2014-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多