【问题标题】:How to tell whether CMake used initial value for an option?如何判断 CMake 是否使用了选项的初始值?
【发布时间】:2014-12-08 02:36:42
【问题描述】:

假设我在 CMake 中有一个选项“ENABLE_Foo”:

option(ENABLE_Foo "Tell cmake to enable the package Foo" ON)

我想检测用户是否指定了-DENABLE_Foo=ON或-DENABLE_Foo=OFF,或者是否正在使用指定的初始值ON。

我想告诉用户是打开选项还是默认打开的原因是因为 Foo 需要额外的包,我想涵盖这些情况:

1) 用户没有为选项 ENABLE_Foo 指定值:
a) 找到包 Foo -> 使用 Foo
b) 未找到包 Foo -> 静默关闭 Foo
2) 用户为选项ENABLE_Foo 指定了一个值:
a) 用户说-DENABLE_Foo=ON:
i) 找到包 Foo -> 使用 Foo
ii) 未找到包 Foo -> 致命错误消息
b) 用户说-DENABLE_Foo=OFF -> 不要使用 Foo 也不要试图找到它

如果无法判断选项值是来自用户输入还是来自初始值,是否还有其他方法可以实现我上面概述的内容?

【问题讨论】:

    标签: cmake


    【解决方案1】:

    如果用户在命令行中输入-DENABLE_Foo=ON,则相应选项的条目将被添加到 CMake 缓存中。虽然可以在调用option 命令之前检查此值,但您无法区分该值最初是由用户在命令行上设置的,还是由option 命令本身在之前的 CMake 运行。

    不过,实现您描述的行为是可能的。

    主要问题是您无法仅使用一个标志来模拟您想要的配置选项。您实际上是在处理两种不同的选择。

    第一个是是否需要对 Foo 的支持,第二个是是否将 Foo 视为可选依赖项或强制依赖项。请注意,如果禁用对 Foo 的支持,则后者的值无关紧要。处理此问题的一种方法是在这种情况下完全删除该选项。这允许采用以下方法:

    if(REQUIRE_Foo)
        # REQUIRE_Foo implies ENABLE_Foo
        unset(ENABLE_Foo CACHE)
    endif()
    
    option(ENABLE_Foo "Tell cmake to enable support for package Foo" ON)
    
    if(ENABLE_Foo)
        option(REQUIRE_Foo "Abort the build if Foo is not found." OFF)
        find_package(Foo)  # assuming that FindFoo is a well-behaving find script,
                           # which will set Foo_FOUND appropriately
    else()
        unset(REQUIRE_Foo CACHE)
        set(Foo_FOUND FALSE)
    endif()
    
    if(REQUIRE_Foo AND NOT Foo_FOUND)
        message(FATAL_ERROR "Required library Foo could not be found")
    endif()
    

    如果用户需要 Foo 支持(您的情况 2a),他们将使用 -DREQUIRE_Foo=TRUE 调用 CMake。如果他们想完全禁用 Foo(您的情况 2b),他们将使用-DENABLE_Foo=FALSE。如果用户没有指定任何内容,您会从案例 1 中获得行为。

    假设构建系统的其余部分已经准备好处理未找到 Foo 的情况(您的问题中的情况 1b),这应该可以在没有进一步更改的情况下工作。

    请注意,即使您可以检测到该标志是否由用户设置,仍然不希望实现您问题中的原始行为。

    假设我们可以检测到它,当且仅当在命令行上设置了ENABLE_Foo=ON 时,上述代码中REQUIRE_Foo 的初始值才会设置为true。在不将REQUIRE_Foo 添加到配置选项集的情况下隐式执行此操作是有问题的。即使构建选项相同,用户在 CMake 运行时也会遇到不同的行为。你应该避免这样的神奇行为。它只会让用户感到困惑,并且很难调试失败的 CMake 运行。

    始终使依赖于用户提供的配置的构建选项对用户可见。

    【讨论】:

    • 感谢您的周到和详细的回答。你能修正REQUIRE_foo 和ENABLE_foo 的大写,让[REQUIRE|ENABLE]_Foo 无处不在吗? (我无法修复它,因为它是少于 6 个字符的编辑...)
    猜你喜欢
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多