[CMake] Variable Containing "MSVC" and MATCHES

Matthew Woehlke mw_triad at users.sourceforge.net
Wed Mar 12 19:08:32 EDT 2014


On 2014-03-12 16:25, Marek Vojtko (Firaxis) wrote:
> I know that MSVC is a CMake keyword and it is therefore not a good
> idea to use the string "MSVC" as the value for any variable, e.g.
> set( compiler "MSVC" ), because if you aren't careful and interpret
> such a variable without surrounding it with quotes (e.g. ${compier}
> rather than "${compiler}") you will get 0 or 1 depending on whether
> you are using a Visual Studio generator or not. So far so good.

Actually, no. There is actually no difference between quoted and 
unquoted expansion. (This is a long-standing issue that tends to trip up 
even experienced people. The general consensus seems to be that we'd 
like to do something about it, but it's difficult due to implementation 
details.)

> However, I was caught off guard by the fact that the MATCHES
> directive (for regex matching) inside an IF() statement is apparently
> interpreting the strings passed to it.

Right. Variables in if() are subject to implicit expansion. Quotes make 
no difference.

> Consider the following code:
>
> if( "MSVC11" MATCHES "MSVC[0-9]+" )
>      message( STATUS "MSVC11 matches MSVC[0-9]+" )
> endif()

If either "MSVC11" or "MSVC[0-9]+" is the name of a variable, it will be 
expanded. (If the RHS is subject to expansion at all, which I would 
suspect it is, but am not 100% sure without testing. Similarly if 
implicit expansion is restricted to identifiers or not, which I suspect 
it isn't. And yes, "MSVC[0-9]+" really is a valid name for a variable in 
CMake :-(.)

(Note: *substrings* of arguments aren't implicitly expanded, but I 
suspect you have a variable named "MSVC11".)

> Putting either the string or the regex or both into variables doesn't help either.

Yes and no. If you rewrite to *rely* on implicit expansion, it would 
help. However, the result of an explicit expansion is still subject to 
implicit expansion.

> The only thing that prevents MSVC from being interpreted is putting
> extra quotes into both the string and the regexp, i.e. "\"MSVC11\""
> MATCHES "\"MSVC[0-9]+\"".

This is roughly how I usually deal with the issue. Note that the quote 
itself isn't special, it's just that you don't have a variable named 
'"MSVC11"'. You could equally write:

   if("#MSVC11" MATCHES "#MSVC[0-9]+")

...or any other set of non-special characters used to reduce the 
likelihood (e.g. autotools likes 'x').

>If this is by design, i.e. not a bug, what are the reasons for this?

I believe this is so that you can write e.g. 'if(VAR STREQUAL "VALUE")', 
which is arguably more natural. Unfortunately, both the LHS and RHS are 
really just strings in both cases.

-- 
Matthew



More information about the CMake mailing list