Reputation: 3135
My hello.txt
cmake_policy(SET CMP0054 NEW)
set(VAR ON)
# VAR will be treated as a string
if("VAR")
message(TRUE)
else()
message(FALSE)
endif()
# output prints FALSE
From policy CMP0054:
To prevent ambiguity, potential variable or keyword names can be specified in a Quoted Argument or a Bracket Argument. A quoted or bracketed variable or keyword will be interpreted as a string and not dereferenced or interpreted. See policy CMP0054.
CMake documentation doesn't mention if(<string>)
:
if(<variable|string>)
True if given a variable that is defined to a value that is not a false constant. False otherwise. (Note macro arguments are not variables.)
Why does a non-empty string evaluate as FALSE
?
Upvotes: 2
Views: 1838
Reputation: 18313
You are looking in the right place in the documentation:
if(<variable|string>)
True if given a variable that is defined to a value that is not a false constant. False otherwise. (Note macro arguments are not variables.)
However, the documentation is not complete, as the <string>
case is not explicitly mentioned. The behavior for CMake if-statements simply containing a string is different than what is described here for variables. The documentation for strings should read:
True if given a string that does matches a true constant (
1
,ON
,YES
,TRUE
,Y
, or a non-zero number). False otherwise.
In other words, any string that doesn't match one of these CMake true constants will evaluate to False. As you already pointed out, the string "VAR"
:
if ("VAR")
message(TRUE)
else()
message(FALSE)
endif()
prints FALSE
. However, a true constant as a string (let's say "y"
):
if ("y")
message(TRUE)
else()
message(FALSE)
endif()
prints TRUE
.
This logic is verifiable in the CMake source code in a function called GetBooleanValue()
:
bool cmConditionEvaluator::GetBooleanValue(
cmExpandedCommandArgument& arg) const
{
// Check basic constants.
if (arg == "0") {
return false;
}
if (arg == "1") {
return true;
}
// Check named constants.
if (cmIsOn(arg.GetValue())) {
return true;
}
if (cmIsOff(arg.GetValue())) {
return false;
}
// Check for numbers.
if (!arg.empty()) {
char* end;
double d = strtod(arg.c_str(), &end);
if (*end == '\0') {
// The whole string is a number. Use C conversion to bool.
return static_cast<bool>(d);
}
}
// Check definition.
const char* def = this->GetDefinitionIfUnquoted(arg);
return !cmIsOff(def);
}
Upvotes: 4