cmake_minimum_required(VERSION 3.20)
set(on "OFF")
if(on)
message("ON")
else()
message("OFF")
endif()
if(${on})
message("ON")
else()
message("OFF")
endif()
$ cmake -P test.cmake
ON
OFF
True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number (including floating point numbers). False if the constant is 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, the empty string, or ends in the suffix -NOTFOUND. Named boolean constants are case-insensitive. If the argument is not one of these specific constants, it is treated as a variable or string (see Variable Expansion further below) and one of the following two forms applies.
My understanding of this problem is that
For predefined constants ON, it equivalent to on.
For if(on)
, on
will be parsed as predefined constant ON
.
For if(${on})
, ${on}
will be parsed as "OFF", which equivalent to OFF
.
I don't know if my understanding is correct.
What is on
?
What is
on
?
It's a string of two characters.
All CMake variables are strings (or lists, which are semi-colon separated strings).
How a variable is interpreted depends on the context.
You already cite the correct section from CMake's documentation on if
.
It states that if the argument is (among other things) ON
(case-insensitive), it's a constant and evaluates to "true".
If it's none of the magic constants, it's treated as a variable or a string.
Your examples never get there, though.
The section on variable expansion points out that ${}
evaluation happens before if
ever sees the arguments.
It also features an example that's pretty much like your example, only that it uses much less confusing variable names.
To wrap this up:
on
is interpreted as the constant ON
which makes the condition true.${on}
undergoes variable expansion to become the string OFF
.
This, in turn, is fed into the conditional to become if(OFF)
which evaluates to false because OFF
is one of the magic constants.on
will print "OFF" for both examples. It will be evaluated as a variable by if
or evaluated before if
, respectively, as explained above.Solution: don't use the names of constants for your variables.
A statement like set(on OFF)
looks like deliberate obfuscation.