如何判断CMake是否使用了期权的初始值? [英] How to tell whether CMake used initial value for an option?

查看:101
本文介绍了如何判断CMake是否使用了期权的初始值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我在CMake中有一个选项 ENABLE_Foo:

  option(ENABLE_Foo告诉cmake启用软件包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也不要试图找到它



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

解决方案

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



仍然可以实现您描述的行为



主要问题是您不能仅使用一个标志来对所需的配置选项进行建模。您实际上正在处理两种不同的选择。



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

  if(REQUIRE_Foo)
#REQUIRE_Foo表示ENABLE_Foo
未设置(ENABLE_Foo CACHE)
endif()

选项(ENABLE_Foo告诉cmake启用对软件包Foo的支持)

if(ENABLE_Foo)
选项( REQUIRE_Foo如果未找到Foo,则中止构建。 OFF)
find_package(Foo)#假定FindFoo是行为良好的查找脚本,
#它将适当地设置Foo_FOUND
else( )
未设置(REQUIRE_Foo CACHE)
设置(Foo_FOUND FALSE)
endif()

if(REQUIRE_Foo AND NOT Foo_FOUND)
消息(FATAL_ERROR必需找不到库Foo)
endif()

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



假定其余构建系统已经准备好处理未发现Foo的情况(问题中的情况1b),它应该可以正常工作,而无需进行进一步的更改。



假定用户可以检测到它,则初始值 REQUIRE_Foo仅当在命令行上设置 ENABLE_Foo = ON 时,以上代码中的才会设置为true。隐式地执行此操作而不将 REQUIRE_Foo 添加到配置选项集是有问题的。即使构建选项相同,用户也会在CMake运行中遇到不同的行为。您应该避免这种魔术行为。



始终使依赖用户指定配置的构建选项对用户可见。



p>

Say I have an option "ENABLE_Foo" in CMake:

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

I want to detect whether the user specified -DENABLE_Foo=ON or -DENABLE_Foo=OFF, or whether the specified initial value ON is being used.

The reason I want to tell whether the user turned the option on or whether it is turned on by default is because Foo requires an additional package and I want to cover these cases:

1) User did not specify a value for the option ENABLE_Foo:
    a) Package Foo is found -> use Foo
    b) Package Foo is not found -> silently turn off Foo
2) User specified a value for the option ENABLE_Foo:
    a) User said -DENABLE_Foo=ON:
        i) Package Foo is found -> use Foo
        ii) Package Foo is not found -> fatal error message
    b) User said -DENABLE_Foo=OFF -> don't use Foo and don't try to find it

If there is no way to tell whether the option value came from user input or from the initial value, are there other ways to achieve what I have outlined above?

解决方案

If the user gives -DENABLE_Foo=ON on the command line, an entry for the respective option will be added to the CMake cache. While it is possible to inspect this value before invoking the option command, you cannot distinguish whether the value was originally set by the user on the command line, or by the option command itself on a previous CMake run.

Still, achieving the behavior you described is possible.

The main issue is that you cannot model the configuration options you want with just one flag. You are actually dealing with two different options.

The first is whether support for Foo is desired at all, the second is whether Foo is to be considered an optional or a mandatory dependency. Note that the value of the latter is irrelevant in case support for Foo is disabled. One way to handle this would be to remove the option completely in this case. This allows for the following approach:

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()

In case the user wants to require Foo support (your case 2a) they would invoke CMake with -DREQUIRE_Foo=TRUE. In case they want to disable Foo completely (your case 2b) they would use -DENABLE_Foo=FALSE. If the user specifies nothing, you get the behavior from your case 1.

Assuming that the rest of the build system is already prepared to handle the case where Foo was not found (case 1b from your question), this should just work without further changes.

Note that even if you could detect whether the flag was set by the user, it would still be undesirable to implement the original behavior from your question.

Assuming we could detect it, the initial value of REQUIRE_Foo in the above code would be set to true if and only if ENABLE_Foo=ON was set on the command line. Doing this implicitly without also adding the REQUIRE_Foo to the set of configuration options is problematic. A user would experience different behaviors on CMake runs even though the build options are the same. You should avoid magical behavior like this. It will only confuse users and give you a hard time debugging failing CMake runs.

Always make build options that depend on configuration given by the user visible to the user.

这篇关于如何判断CMake是否使用了期权的初始值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆