Policy CMP0077 docs misrepresent the OLD and NEW behavior
Demonstrator Project Example
cmake_minimum_required(VERSION 3.11)
if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
get_property(cacheValue CACHE SOMEVAR PROPERTY VALUE)
get_property(cacheType CACHE SOMEVAR PROPERTY TYPE)
message("Before: value = ${cacheValue}, type = ${cacheType}")
set(SOMEVAR NO)
message("Non-cache SOMEVAR set to: ${SOMEVAR}")
option(SOMEVAR "" OFF)
get_property(cacheValue CACHE SOMEVAR PROPERTY VALUE)
get_property(cacheType CACHE SOMEVAR PROPERTY TYPE)
message("After: value = ${cacheValue}, type = ${cacheType}")
message("Final var: ${SOMEVAR}")
project(Foo LANGUAGES NONE)
Results
Running cmake
for the first time with three different command line options results in the following sets of output:
CASE 1: No SOMEVAR set on command line
cmake ...
Original output | Output with !2155 (policy NEW)
------------------------------------------|-------------------------------
Before: value = , type = | Before: value = , type =
Non-cache SOMEVAR set to: NO | Non-cache SOMEVAR set to: NO
After: value = OFF, type = BOOL | After: value = , type =
Final var: OFF | Final var: NO
CASE 2: With SOMEVAR set on command line, but without type
cmake -DSOMEVAR=YES ...
Original output | Output with !2155 (policy NEW)
------------------------------------------|-------------------------------
Before: value = YES, type = UNINITIALIZED | Before: value = YES, type = UNINITIALIZED
Non-cache SOMEVAR set to: NO | Non-cache SOMEVAR set to: NO
After: value = YES, type = BOOL | After: value = YES, type = UNINITIALIZED
Final var: YES | Final var: NO
CASE 3: With SOMEVAR set on command line, including type
cmake -DSOMEVAR:BOOL=YES ...
Original output | Output with !2155 (policy NEW)
------------------------------------------|-------------------------------
Before: value = YES, type = BOOL | Before: value = YES, type = BOOL
Non-cache SOMEVAR set to: NO | Non-cache SOMEVAR set to: NO
After: value = YES, type = BOOL | After: value = YES, type = BOOL
Final var: NO | Final var: NO
Observations
The docs for the CMP0077
policy introduced in !2155 (merged) state that:
The
OLD
behavior for this policy is to clear any existing normal variables with the same name.
This is not an accurate description of the OLD behavior. As demonstrated by the results of the different cases above, the OLD behavior is much more complex:
- If a cache variable of the specified name exists and has been given a type, then the
option()
command changes nothing. - If a cache variable of the specified name exists but has NOT been given a type, the
option()
command will change the type toBOOL
and will remove any non-cache variable of the same name. The cached value is not changed. - If a cache variable of the specified name does not exist at all, the
option()
command will add a new cache variable of typeBOOL
and will remove any non-cache variable of the same name.
Similarly, the NEW
behavior is also not accurately documented:
The
NEW
behavior for this policy is to not create a cache entry or modify any existing normal variables if a normal variable with the same name already exists.
It should really say something more like:
The
NEW
behavior for this policy is to not create or modify a cache entry or modify any existing normal variables if a normal variable or a cache variable with the same name already exists.
The single line summary for CMP0077
is probably also an over-simplification:
option() honors normal variables
Perhaps it could be more accurately described as something like "option() does nothing if variable already defined"? This doesn't limit the statement to "normal variables", but instead allows for cache variables that might or might not have a type too.
Ultimately, the NEW behavior is indeed desirable and more intuitive, we should just make the docs align with the OLD and NEW behavior more accurately.