说我在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,也不要试图找到它
如果无法判断选项值是来自用户输入还是来自初始值,是否有其他方法可以实现我上面概述的内容?
答案 0 :(得分:2)
如果用户在命令行上提供-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),这应该可以正常工作而无需进一步更改。
请注意,即使您可以检测该标志是否由用户设置,仍然不希望从您的问题中实现原始行为。
假设我们可以检测到它,当且仅当在命令行上设置REQUIRE_Foo
时,上述代码中的ENABLE_Foo=ON
的初始值才会设置为true。在没有将REQUIRE_Foo
添加到配置选项集的情况下隐式执行此操作是有问题的。即使构建选项相同,用户也会在CMake运行中遇到不同的行为。你应该避免像这样的神奇行为。它只会让用户感到困惑,并且很难调试失败的CMake运行。
始终使构建选项依赖于用户可见的配置。