我有以下生成器表达式工作,/GS如果编译器是 MSVC,它会设置标志,并将它设置为构建配置RelWithDebInfo和Release:
target_compile_options(mytarget PRIVATE "$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>")
现在我还想让用户配置它,我添加了一个option:
option(MYTARGET_ENABLE_GS "Enable /GS" OFF)
所以现在,如果用户启用了此选项,我(显然)想要启用该/GS标志,如果他们启用了,我想添加它,如果编译器是MSVC,它应该被添加到Release和RelWithDebInfo配置。
这是非常嵌套的,我似乎无法正确理解。这是我得到的:
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(可以是开/关或真/假,0或1,生成器表达式需要。但是上面的行不起作用:它不添加(或不添加)添加)/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)”,我很想获得洞察力。
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 中构建的两种情况
| 归档时间: |
|
| 查看次数: |
4580 次 |
| 最近记录: |