CMake Gotchas
When working with CMake, never assume you know how something works. Guessing can easily lead you into a subtle “feature” trap.
Important Notes
Common Pitfalls When Testing Environment Variables or Strings
Refer to the official documentation section on
A quoted string always evaluates to false unless:
A quoted string always evaluates to false, unless:
- The string’s value is one of the true constants, or
- Policy CMP0054 is not set to
NEWand the string’s value happens to be a variable name that is affected by CMP0054’s behavior.
First, as the documentation states, strings are always treated as false. So if you need to check whether an environment variable is defined and non-empty, you should write:
| |
In this case, ENV{VAR} is an empty string, while $ENV{VAR} is the string value of the set environment variable — both are treated as false.
You need to use string comparison to handle this: "$ENV{VAR}" STREQUAL "".
As for why quotes are necessary, this relates to the exception case CMP0054 mentioned in the documentation. I won’t go into full detail here, but the gist is that older CMake versions had a feature where if the argument to if matched an existing variable name, it would be expanded and evaluated as a string — and this expansion was recursive, meaning if the result still matched a variable name it would keep expanding.
CMake 3.1 introduced a new policy: expansion only happens once. See CMake compare to empty string with STREQUAL failed for details.
Using CMAKE_TOOLCHAIN_FILE
See Tsyvarev’s answer in CMake ignore custom toolchain file.:
The variable CMAKE_TOOLCHAIN_FILE should be set before the first
project()call:
| |
When the first project() call is processed, CMake automatically calls the script specified in CMAKE_TOOLCHAIN_FILE.
Note that the preferred way is to not hardcode the path to the toolchain in the CMakeLists.txt, but to pass the -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain option to cmake.
In short:
- The toolchain must be set before calling
project() - The preferred method is to pass
-DCMAKE_TOOLCHAIN_FILE=/path/to/toolchaintocmake
Here is an example:
| |
Official documentation on CMAKE_TOOLCHAIN_FILE:
This is initialized by the
CMAKE_TOOLCHAIN_FILEenvironment variable if it is set when a new build tree is first created.The
CMAKE_TOOLCHAIN_FILEenvironment variable specifies a default value for theCMAKE_TOOLCHAIN_FILEvariable when there is no explicit configuration given on the first run while creating a new build tree. On later runs in an existing build tree the value persists in the cache asCMAKE_TOOLCHAIN_FILE.
If the CMAKE_TOOLCHAIN_FILE environment variable is set when a new build tree is first created, it is used for initialization.
When creating a new build tree, if no explicit configuration is provided on the first run, the CMAKE_TOOLCHAIN_FILE environment variable specifies the default value for the CMAKE_TOOLCHAIN_FILE variable. On subsequent runs in an existing build tree, the value is persisted in the cache as CMAKE_TOOLCHAIN_FILE.