Discussion:
[CMake] Can an option enforce a default, even if cache is present?
Mario Emmenlauer
2018-11-27 13:49:46 UTC
Permalink
Dear all,

I've just discovered that option() behaves differently than I anticipated.
After reading the docs and searching with google I'm still confused how to
achieve my desired behaviour.

What I've just learned is that unspecified options take their cached value
and do *not* go back to their default value, if a cache exists. I assumed
that options take their default when not explicitly specified.

Now my problem: I could not find a way to get the behaviour I'd like. Is it
possible to enforce the default for an option when its not specified by the
user, even if a cache exists?

I tried to unset() the option from the cache but that does not do what I'd
like.

All the best,

Mario Emmenlauer
--
Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake
Roger Leigh
2018-11-27 14:33:40 UTC
Permalink
Post by Mario Emmenlauer
I've just discovered that option() behaves differently than I anticipated.
After reading the docs and searching with google I'm still confused how to
achieve my desired behaviour.
What I've just learned is that unspecified options take their cached value
and do *not* go back to their default value, if a cache exists. I assumed
that options take their default when not explicitly specified.
I think this is exactly what happens. For example, an example I quickly
dug out is this:

# Doxygen documentation
find_package(Doxygen)
set(DOXYGEN_DEFAULT OFF)
if (DOXYGEN_FOUND AND DOXYGEN_DOT_FOUND)
set (DOXYGEN_DEFAULT ON)
endif (DOXYGEN_FOUND AND DOXYGEN_DOT_FOUND)
option(doxygen "Enable doxygen documentation" ${DOXYGEN_DEFAULT})
set(BUILD_DOXYGEN ${doxygen})

which causes this to be set in the cache:

//Enable doxygen documentation
doxygen:BOOL=ON

In this case, doxygen and dot were installed. But if one was missing,
it would default to "OFF" and this would be set in the cache. If the
user noticed it was missing, installed it, then re-ran cmake, the cached
value would not be changed even though the default set with option()
changed in the meantime.

From the look of things, there's no metadata in the cache to say "this
was defaulted; the user did not specify it explicitly". If such
metadata did exist, the option() call could check it and overwrite the
cached value if the user had not explicitly set the option. This would
make cmake much more conveniently adaptable.

The cache already stored extra properties for ADVANCED. Could we add a
similar extra property for DEFAULTED? I.e.

//DEFAULTED property for variable: doxygen
doxygen-DEFAULTED:INTERNAL=1

Perhaps with a mark_as_defaulted() function to mirror
mark_as_advanced(). Or a DEFAULT option for set_property() and/or a
DEFAULT option as the opposite of FORCE for set(). This would only set
the cache value if unset, plus add the DEFAULTED property. The
difference in behaviour would that if DEFAULT is used AND DEFAULTED=ON
then the value would be overwritten if changed.


Regards,
Roger
--
Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake
Eric Noulard
2018-11-27 16:13:47 UTC
Permalink
Post by Mario Emmenlauer
Dear all,
I've just discovered that option() behaves differently than I anticipated.
After reading the docs and searching with google I'm still confused how to
achieve my desired behaviour.
What I've just learned is that unspecified options take their cached value
and do *not* go back to their default value, if a cache exists. I assumed
that options take their default when not explicitly specified.
The behavior of option() gained new behavior in CMake 3.13.
May be it could help in your particular case:
https://cmake.org/cmake/help/v3.13/policy/CMP0077.html#policy:CMP0077

you'll depend on latest CMake though.
Post by Mario Emmenlauer
Now my problem: I could not find a way to get the behaviour I'd like. Is it
possible to enforce the default for an option when its not specified by the
user, even if a cache exists?
You mean you did not manage to force the cache value?
You can:
set(VAR "default_value" CACHE FORCE)

or the problem is you cannot know whether if a value has been user-provided?
Post by Mario Emmenlauer
I tried to unset() the option from the cache but that does not do what I'd
like.
All the best,
Mario Emmenlauer
--
Powered by www.kitware.com
http://www.cmake.org/Wiki/CMake_FAQ
Kitware offers various services to support the CMake community. For more
CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
https://cmake.org/mailman/listinfo/cmake
--
Eric
Mario Emmenlauer
2018-11-27 20:14:51 UTC
Permalink
Post by Mario Emmenlauer
Dear all,
I've just discovered that option() behaves differently than I anticipated.
After reading the docs and searching with google I'm still confused how to
achieve my desired behaviour.
What I've just learned is that unspecified options take their cached value
and do *not* go back to their default value, if a cache exists. I assumed
that options take their default when not explicitly specified.
The behavior of option() gained new behavior in CMake 3.13.
https://cmake.org/cmake/help/v3.13/policy/CMP0077.html#policy:CMP0077
you'll depend on latest CMake though.
Now my problem: I could not find a way to get the behaviour I'd like. Is it
possible to enforce the default for an option when its not specified by the
user, even if a cache exists?
You mean you did not manage to force the cache value?
set(VAR "default_value" CACHE FORCE)
or the problem is you cannot know whether if a value has been user-provided?
Sorry, I was not very precise! Your last point is the problem. I fail to know
when the option was user-provided and when it was cache-provided.

So here is what I'd like:

#> grep MYOPT CMakeLists.txt
option(MYOPT "Description" OFF)
#> cmake # I want the option disabled, this works fine.
#> cmake -DMYOPT=ON # I want the option enabled, this works fine.
#> cmake # I want the option disabled (back to default),
# but I observe the option taken from cache, enabled.

Is there some way to achieve my desired behaviour? I tried without success
unset(MYOPT), unset(MYOPT CACHE), and set(MYOPT OFF) before option(), but
they all lead to different behaviour.

All the best,

Mario
--
Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailm
frodak
2018-11-27 20:41:30 UTC
Permalink
Post by Mario Emmenlauer
Post by Mario Emmenlauer
Dear all,
I've just discovered that option() behaves differently than I anticipated.
After reading the docs and searching with google I'm still confused how to
achieve my desired behaviour.
What I've just learned is that unspecified options take their cached value
and do *not* go back to their default value, if a cache exists. I assumed
that options take their default when not explicitly specified.
The behavior of option() gained new behavior in CMake 3.13.
https://cmake.org/cmake/help/v3.13/policy/CMP0077.html#policy:CMP0077
you'll depend on latest CMake though.
Now my problem: I could not find a way to get the behaviour I'd like. Is it
possible to enforce the default for an option when its not specified by the
user, even if a cache exists?
You mean you did not manage to force the cache value?
set(VAR "default_value" CACHE FORCE)
or the problem is you cannot know whether if a value has been user-provided?
Sorry, I was not very precise! Your last point is the problem. I fail to know
when the option was user-provided and when it was cache-provided.
#> grep MYOPT CMakeLists.txt
option(MYOPT "Description" OFF)
#> cmake # I want the option disabled, this works fine.
#> cmake -DMYOPT=ON # I want the option enabled, this works fine.
#> cmake # I want the option disabled (back to default),
# but I observe the option taken from cache, enabled.
Is there some way to achieve my desired behaviour? I tried without success
unset(MYOPT), unset(MYOPT CACHE), and set(MYOPT OFF) before option(), but
they all lead to different behaviour.
I've always used 'cmake -UMYOPT' to remove specific items from the
cache (or edit the cache file directly).
I don't think the notion of user-provided or cache-provided entries
exist because all user defined variables go into the cache.
Then you can test to see if MYOPT is set and then use the default
value when recreating the cache entry.
Also cmake cache variables are persistent between invocations so the
user doesn't need to keep specifying them at the command line every
time cmake needs to run.

Best regards...
--
Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
Petr Kmoch
2018-11-28 11:38:18 UTC
Permalink
Post by Mario Emmenlauer
Post by Mario Emmenlauer
Post by Mario Emmenlauer
Dear all,
I've just discovered that option() behaves differently than I
anticipated.
Post by Mario Emmenlauer
Post by Mario Emmenlauer
After reading the docs and searching with google I'm still
confused how to
Post by Mario Emmenlauer
Post by Mario Emmenlauer
achieve my desired behaviour.
What I've just learned is that unspecified options take their
cached value
Post by Mario Emmenlauer
Post by Mario Emmenlauer
and do *not* go back to their default value, if a cache exists. I
assumed
Post by Mario Emmenlauer
Post by Mario Emmenlauer
that options take their default when not explicitly specified.
The behavior of option() gained new behavior in CMake 3.13.
https://cmake.org/cmake/help/v3.13/policy/CMP0077.html#policy:CMP0077
you'll depend on latest CMake though.
Now my problem: I could not find a way to get the behaviour I'd
like. Is it
Post by Mario Emmenlauer
Post by Mario Emmenlauer
possible to enforce the default for an option when its not
specified by the
Post by Mario Emmenlauer
Post by Mario Emmenlauer
user, even if a cache exists?
You mean you did not manage to force the cache value?
set(VAR "default_value" CACHE FORCE)
or the problem is you cannot know whether if a value has been
user-provided?
Post by Mario Emmenlauer
Sorry, I was not very precise! Your last point is the problem. I fail to
know
Post by Mario Emmenlauer
when the option was user-provided and when it was cache-provided.
#> grep MYOPT CMakeLists.txt
option(MYOPT "Description" OFF)
#> cmake # I want the option disabled, this works fine.
#> cmake -DMYOPT=ON # I want the option enabled, this works fine.
#> cmake # I want the option disabled (back to default),
# but I observe the option taken from cache,
enabled.
Post by Mario Emmenlauer
Is there some way to achieve my desired behaviour? I tried without
success
Post by Mario Emmenlauer
unset(MYOPT), unset(MYOPT CACHE), and set(MYOPT OFF) before option(), but
they all lead to different behaviour.
You're forgetting one important aspect of CMake: that it can retrigger
itself when a CMake source file changes. Such a run of CMake is
indistinguishable from running it manually, and it's (a large part of) why
the cache exists in the first place. Imagine the following scenario:

User runs >cmake -DMYOPT=ON
User edits a CMakeLists.txt (or even just a file processed by
configure_file()).
User runs >make

As part of this make, CMake triggers to regenerate the buildsystem. If
MYOPT exhibited the behaviour you request, it would silently get disabled
again, even though this is most definitely not what the user expects. I
addressed a similar point in this StackOverflow answer:
https://stackoverflow.com/a/41361741/1782465

Petr
Post by Mario Emmenlauer
I've always used 'cmake -UMYOPT' to remove specific items from the
cache (or edit the cache file directly).
I don't think the notion of user-provided or cache-provided entries
exist because all user defined variables go into the cache.
Then you can test to see if MYOPT is set and then use the default
value when recreating the cache entry.
Also cmake cache variables are persistent between invocations so the
user doesn't need to keep specifying them at the command line every
time cmake needs to run.
Best regards...
--
Powered by www.kitware.com
http://www.cmake.org/Wiki/CMake_FAQ
Kitware offers various services to support the CMake community. For more
CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
https://cmake.org/mailman/listinfo/cmake
Mario Emmenlauer
2018-11-28 11:56:31 UTC
Permalink
Post by Mario Emmenlauer
     Dear all,
     I've just discovered that option() behaves differently than I anticipated.
     After reading the docs and searching with google I'm still confused how to
     achieve my desired behaviour.
     What I've just learned is that unspecified options take their cached value
     and do *not* go back to their default value, if a cache exists. I assumed
     that options take their default when not explicitly specified.
The behavior of option() gained new behavior in CMake 3.13.
https://cmake.org/cmake/help/v3.13/policy/CMP0077.html#policy:CMP0077
you'll depend on latest CMake though.
     Now my problem: I could not find a way to get the behaviour I'd like. Is it
     possible to enforce the default for an option when its not specified by the
     user, even if a cache exists?
You mean you did not manage to force the cache value?
set(VAR "default_value" CACHE FORCE)
or the problem is you cannot know whether if a value has been user-provided?
Sorry, I was not very precise! Your last point is the problem. I fail to know
when the option was user-provided and when it was cache-provided.
#> grep MYOPT CMakeLists.txt
option(MYOPT "Description" OFF)
#> cmake              # I want the option disabled, this works fine.
#> cmake -DMYOPT=ON   # I want the option enabled, this works fine.
#> cmake              # I want the option disabled (back to default),
                       # but I observe the option taken from cache, enabled.
Is there some way to achieve my desired behaviour? I tried without success
unset(MYOPT), unset(MYOPT CACHE), and set(MYOPT OFF) before option(), but
they all lead to different behaviour.
You're forgetting one important aspect of CMake: that it can retrigger itself when a CMake source file changes. Such a run of CMake is indistinguishable from
User runs >cmake -DMYOPT=ON
User edits a CMakeLists.txt (or even just a file processed by configure_file()).
User runs >make
As part of this make, CMake triggers to regenerate the buildsystem. If MYOPT exhibited the behaviour you request, it would silently get disabled again, even
though this is most definitely not what the user expects. I addressed a similar point in this StackOverflow answer: https://stackoverflow.com/a/41361741/1782465
Petr
 
I've always used 'cmake -UMYOPT'  to remove specific items from the
cache (or edit the cache file directly).
I don't think the notion of user-provided or cache-provided entries
exist because all user defined variables go into the cache.
Then you can test to see if MYOPT is set and then use the default
value when recreating the cache entry.
Also cmake cache variables are persistent between invocations so the
user doesn't need to keep specifying them at the command line every
time cmake needs to run.
Best regards...
Both of you make perfectly valid remarks, thanks for the explanation!
And I understand now that this is currently build deeply into cmake,
and I do not think my request is important enough to change it!

Still, if this would be re-evaluated at some point, then my personal
vote would be to change this behaviour. My user story is a variable that
can enable and disable packaging with cpack. I configure cmake for build,
run the build, run tests, and only then I configure for packaging. When
some time later the next build runs, it will actually execute packaging,
not building!

This was *not* requested, but happens due to caching. Since I re-run
configuration, it was not intuitive to me that it would not use *only*
the options I give, but additionally the ones I omitted but gave before.

I do not think that other configuration systems do this. In my example
from yesterday, I expect a configuration system to give the same result
when I invoke (1) or (3), since they are the same call:
#> cmake # I want the option disabled, this works fine.
#> cmake -DMYOPT=ON # I want the option enabled, this works fine.
#> cmake # I want the option disabled (back to default).


All the best,

Mario Emmenlauer
--
Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailm
Continue reading on narkive:
Loading...