[CMake] comparing strings

Matthew Woehlke matthew.woehlke at kitware.com
Thu Feb 14 17:20:00 EST 2013


On 2013-02-14 16:44, Shaun Williams wrote:
> I learned something very valuable today about cmake after getting an
> unexpected result with STREQUAL:
>
> set(foo bar)
> ...
> set(baz foo)
> ...
> if("${baz}" STREQUAL "bar") # This evaluates to true.
> ...
>
> I expected it to be false, because I was trying to get baz's value ("foo")
> to compare with "bar".  I thought that parameters explicitly quoted were
> treated as strings.
>
> Then I learned that the interpreter is the only one that sees quotes around
> parameters, for the sole purpose of string interpolation and preventing
> whitespace from splitting a parameter.  Cmake commands do not see these
> quotes. Therefore, STREQUAL can never know the difference between "baz" and
> baz.
>
> So, STREQUAL treats a parameter as a variable name if it is defined, but as
> a string value if it is not.  (I verified this in cmIfCommand.cxx)
>
> Is this quote behavior well-known among cmake users?  For others like me,
> I'd like this behavior to be emphasized in the cmake docs for STREQUAL.

Yes, it is :-/.

This is why I take a page from autotools and try to always write:
   if("x_${baz}" STREQUAL "x_bar")

(Or you can write 'if(baz STREQUAL'... er... well if your RHS for sure 
cannot be a variable name - e.g. is empty, contains spaces, etc. - then 
you can write your constructs assuming that auto-expansion will occur. 
Personally, I'm going to stick with explicit expansion - guaranteeing an 
empty value in case the variable is not set - and adding something to 
make it unlikely that either side expands to a variable name to prevent 
auto-expansion...)

-- 
Matthew



More information about the CMake mailing list