Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake - How does the if() command treat a symbol? As string or as variable?

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:

  • If the symbol is defined as a variable before, CMake will treat it as variable and use its value for evaluation.
  • If the symbol is not defined as a variable before, CMake will treat it literally as a string.

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??

ADD 1 - 11:04 AM 7/11/2019

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

like image 376
smwikipedia Avatar asked Jul 11 '19 02:07

smwikipedia


People also ask

How do you define a variable in CMake?

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.

What is CMake cache variable?

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.

What is CMake command?

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.

What is Mark_as_advanced?

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.


1 Answers

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.

like image 68
tay10r Avatar answered Nov 15 '22 17:11

tay10r