Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I wrap variables with ${...} in CMake?

Tags:

I wonder why often variables in CMake are wrapped with a dollar sign and curly brackets. For example, I saw this call in a CMake tutorial.

include_directories(${PROJECT_BINARY_DIR}) 

But from what I tried, this does the same thing.

include_directories(PROJECT_BINARY_DIR) 

When is the wrapping with ${...} needed and what does it mean? Why are variables often wrapped with this even if it makes no difference?

like image 847
danijar Avatar asked Sep 12 '14 13:09

danijar


People also ask

What is ${} in CMake?

Local Variables You access a variable by using ${} , such as ${MY_VARIABLE} . 1. CMake has the concept of scope; you can access the value of the variable after you set it as long as you are in the same scope. If you leave a function or a file in a sub directory, the variable will no longer be defined.

How do I set CMake cache variables?

You can use the command line to set entries in the Cache with the syntax cmake -D var:type=value , just cmake -D var=value or with cmake -C CMakeInitialCache. cmake .

What is Parent_scope in CMake?

If the PARENT_SCOPE option is given the variable will be set in the scope above the current scope. Each new directory or function creates a new scope. This command will set the value of a variable into the parent directory or calling function (whichever is applicable to the case at hand).

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.


1 Answers

Quoting the CMake documentation:

A variable reference has the form ${variable_name} and is evaluated inside a Quoted Argument or an Unquoted Argument. A variable reference is replaced by the value of the variable, or by the empty string if the variable is not set.

In other words, writing PROJECT_BINARY_DIR refers, literally, to the string "PROJECT_BINARY_DIR". Encapsulating it in ${...} gives you the contents of the variable with the name PROJECT_BINARY_DIR.

Consider:

set(FOO "Hello there!") message(FOO)     # prints FOO message(${FOO})  # prints Hello there! 

As you have probably guessed already, include_directories(PROJECT_BINARY_DIR) simply attempts to add a subdirectory of the name PROJECT_BINARY_DIR to the include directories. On most build systems, if no such directory exists, it will simply ignore the command, which might have tricked you into the impression that it works as expected.

A popular source of confusion comes from the fact that if() does not require explicit dereferencing of variables:

set(FOO TRUE) if(FOO)     message("Foo was set!") endif() 

Again the documentation explains this behavior:

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 constants, it is treated as a variable.

if(<variable>)

True if the variable is defined to a value that is not a false constant. False otherwise. (Note macro arguments are not variables.)

In particular, one can come up with weird examples like:

unset(BLA) set(FOO "BLA") if(FOO)     message("if(<variable>): True") else()     message("if(<variable>): False") endif() if(${FOO})     message("if(<constant>): True") else()     message("if(<constant>): False") endif() 

Which will take the TRUE branch in the variable case, and the FALSE branch in the constant case. This is due to the fact that in the constant case, CMake will go look for a variable BLA to perform the check on (which is not defined, hence we end up in the FALSE branch).

like image 117
ComicSansMS Avatar answered Oct 22 '22 10:10

ComicSansMS