I am not sure the CMake if()
command will treat a symbol in the condition clause as a variable or a string literal. So I did some experiments.
Script1.cmake
cmake_minimum_required(VERSION 3.15)
set(XXX "YYY") #<========== HERE!!
if(XXX STREQUAL "XXX")
message("condition 1 is true") # If reach here, XXX is treated as string
elseif(XXX STREQUAL "YYY")
message("condition 2 is true") # If reach here, XXX is treated as variable
endif()
The output is:
condition 2 is true
So I come to below conclusion 1.
For a symbol in the condition clause:
Then I did another experiment.
set(ON "OFF")
if(ON)
message("condition 3 is true") # If reach here, ON is treated as a constant.
else()
message("condition 4 is true") # If reach here. ON is treated as a variable.
endif()
The output is:
condition 3 is true
So, though ON
is explicitly defined as a variable, the if
command still treat it as a constant of TRUE value. This directly contradicts to my previous conclusion 1.
So how can I know for sure the CMake if() command will treat a symbol as string or variable??
It seems the if(constant)
form precedes other forms of if()
statement. (src)
if(<constant>)
True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number. 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 and the following signature is used.
So for now, I have to refer to the above rule first before applying my conclusion 1. (This may be an answer, but I am not sure enough yet.)
Options and variables are defined on the CMake command line like this: $ cmake -DVARIABLE=value path/to/source You can set a variable after the initial `CMake` invocation to change its value. You can also undefine a variable: $ cmake -UVARIABLE path/to/source Variables are stored in the `CMake` cache.
The CMake cache may be thought of as a configuration file. The first time CMake is run on a project, it produces a CMakeCache. txt file in the top directory of the build tree. CMake uses this file to store a set of global cache variables, whose values persist across multiple runs within a project build tree.
Description. The “cmake” executable is the CMake command-line interface. It may be used to configure projects in scripts. Project configuration settings may be specified on the command line with the -D option. CMake is a cross-platform build system generator.
mark_as_advanced([CLEAR|FORCE] <var1> ...) Sets the advanced/non-advanced state of the named cached variables. An advanced variable will not be displayed in any of the cmake GUIs unless the show advanced option is on. In script mode, the advanced/non-advanced state has no effect.
Welcome to the wilderness of CMake symbol interpretation.
If the symbol exists as a variable, then the expression is evaluated with the value of the variable. Otherwise, the name of the variable (or literal, as you said) is evaluated instead.
The behavior becomes a little more consistent if you add the ${
and }
sequences. Then the value of the variable is used in the evaluation every single time. If the variable doesn't exist or has not been assigned a value, then CMake uses several placeholder values that evaluate to "false". These are the values you mentioned in the latter part to your post.
I believe this is done this way for backwards compatibility, which CMake is really good about. For most of the quirky things CMake does, it's usually in the name of backwards compatibility.
As for the inconsistent behavior you mentioned in the "ON" variable, this is probably due to the precedence in which CMake processes the command arguments. I would have to figure that the constants are parsed before the symbol lookup occurs.
So when it comes to knowing/predicting how an if
statement will evaluate, my best answer is experience. The CMake source tree and logic is one magnificent, nasty beast.
There's been discussions on adding an alternative language (one with perhaps a functional paradigm), but it's a quite large undertaking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With