CMake:如何根据选项(和编译器/构建配置)设置生成器表达式

Ela*_*782 6 cmake

我有以下生成器表达式工作,/GS如果编译器是 MSVC,它会设置标志,并将它设置为构建配置RelWithDebInfoRelease

target_compile_options(mytarget PRIVATE "$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>")

现在我还想让用户配置它,我添加了一个optionoption(MYTARGET_ENABLE_GS "Enable /GS" OFF)

所以现在,如果用户启用了此选项,我(显然)想要启用该/GS标志,如果他们启用了,我想添加它,如果编译器是MSVC,它应该被添加到ReleaseRelWithDebInfo配置。

这是非常嵌套的,我似乎无法正确理解。这是我得到的:

target_compile_options(mytarget PRIVATE "$<$<BOOL:MYTARGET_ENABLE_GS>:$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>>") 编辑:固定,见下文。

我不得不使用 the$<$<BOOL:...>>因为它“翻译”了option(可以是开/关或真/假,01,生成器表达式需要。但是上面的行不起作用:它不添加(或不添加)添加)/GS

我想知道:

1)我的错误在哪里?这该怎么做?和

2)像这样的东西会导致非常复杂的嵌套表达式,这真的很难阅读 - 想象一下 6 个月后再次阅读该行代码,即使它被记录在案。而且很容易把 a>或类似的东西放错地方。我可能可以使用 "manual"if来使这更具可读性,但想象一下有 5-10 个这样的选项 - 编写一个带有内部的if/结果就像 15-30 行/endtarget_compile_optionsifend代码,这看起来也不是很漂亮. 做到这一点的最佳方法是什么?

编辑:我快到了。变量必须包含${...}在生成器表达式中。所以它是例如: target_compile_options(mytarget PRIVATE "$<$<BOOL:${MYTARGET_ENABLE_GS}>:$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>>") 这很好用。

这仍然留下点“2)”,我很想获得洞察力。

Ant*_*ane 6

When you generate a MSVC solution, the build type (Release, Debug, etc.) is unknown until you actually run the build. Thus, using generator expression for that is correct.

But for the 2 other variables (does user set MYTARGET_ENABLE_GS to OFF and is generation performed for MSVC), they are resolved at configuration time. So, you don't have to check them in a generator expression. You could simply write:

if(MSVC AND MYTARGET_ENABLE_GS)
    target_compile_options(mytarget PRIVATE "$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:/GS>")
endif()
Run Code Online (Sandbox Code Playgroud)

此解决方案还使用$<OR:?[,?]...>生成器表达式在同一表达式下重新组合您在 Release OR RelWithDebInfo 中构建的两种情况