Except when it does… If you don’t provide the type on the command line, it can lead to different behavior between the first and subsequent CMake runs. The situation arises because of a quirk where if the project sets a cache variable that was already set but didn’t yet have a type associated with it, this will discard any non-cache variable of the same name. Consider the following test project:
cmake_minimum_required(VERSION 3.4)
project(var_test)
set(SOMEVAR local_value)
set(SOMEVAR cache_value CACHE STRING "")
message(STATUS "SOMEVAR = ${SOMEVAR}")
Consider firstly if you don’t try to set SOMEVAR
on the command line at all. On the first CMake run, this prints SOMEVAR = cache_value
and on subsequent runs, it prints SOMEVAR = local_value
. On the first run, the cache variable isn’t set, so setting the variable results in clearing any non-variable of the same name. On subsequent runs, the cache variable exists and has a type, so it doesn’t touch the non-cache variable, which then still takes precedence over the cache variable when we print ${SOMEVAR}
at the end.
Now consider if you set the cache variable on the command line. If you set it without any type, like so:
cmake -D SOMEVAR=cmdline ...
On the first run, the cache variable doesn’t initially have a type, even though we’ve given it a value. When the project sets the cache variable, it sees the cache variable has no type, so it clears the non-cache variable (yes, this is quite surprising and probably not widely understood). On subsequent runs, the cache variable does have a type and the local variable is not cleared.
But if on the first run we do provide a type like so:
cmake -D SOMEVAR:STRING=cmdline ...
When we reach the line that sets the cache variable, it already has a type and so the non-cache variable’s value is used even on the first run.
Now, the above all likely sounds horribly unintuitive. And you’re right. This was fixed in CMake 3.21, subject to a new policy CMP0126. If we changed the first line of our example such that the new policy is always used:
cmake_minimum_required(VERSION 3.21)
Now the local variable’s value is left alone and will always be used whether it is the first run or not, whether we set the cache variable on the command line or not, and whether we include the type with the variable on the command line or not. In other words, the new behavior is what people expect.
For completeness, there is a similar situation for the option()
command, but that was fixed back in CMake 3.13 with policy CMP0077.