[CMake] if(MATCHES) broken??

Bill Hoffman bill.hoffman at kitware.com
Wed Nov 19 22:50:12 EST 2008


Matthew Woehlke wrote:
> Can someone explain to me:
> - why this doesn't work (prints "CFLAGS match broken!!")
> - if it's supposed to work or if this is a bug
> - a great work-around to this problem ;-)
> 
> This is with cmake 2.6.2
> 
> ================================================
> macro(foo bar)
>   if("${bar}" MATCHES "CFLAGS")
>     message(STATUS "CFLAGS matched")
>   elseif("${bar}" STREQUAL "CFLAGS")
>     message(STATUS "CFLAGS match broken!!!")
>   endif()
> endmacro()
> 
> function(nonce)
>   foreach(arg ${ARGN})
>     foo("${arg}")
>   endforeach()
> endfunction()
> 
> set(CFLAGS happyjoy)
> 
> foo(CFLAGS)
>
OK, here is the explanation...

The problem is that if(something MATCHES something) works for either 
strings or variable names.  The way that works is by checking to see if 
there is a variable defined by the string given to if.  Even if that 
string is in quotes, it can still be treated like a variable.

So, in this case cmake looks up "CFLAGS" and finds that there is a 
variable of that name, and uses that value for the MATCHES statement. 
Basically ending up with if("happyjoy" MATCHES "CFLAGS").  You can 
verify this by commenting out set(CFLAGS happyjoy) so that CFLAGS does 
not have a definition, then your code works.

The only work around that I can think of is to change the macro to a 
function and unset the variable before the test.

function(foo bar)
   set(${bar} )  # unset the variable named "${bar}"
   if("${bar}" MATCHES "CFLAGS")
     message(STATUS "CFLAGS matched")
   elseif("${bar}" STREQUAL "CFLAGS")
     message(STATUS "CFLAGS match broken!!!")
   endif()
endfunction()

Use a function so bar does not get changed in the parent scope.  You 
could save the value into another variable if you need the value.

I agree this is confusing...  Perhaps there should be some new if 
arguments that are always string based, and never look up variables.

Something like:

if( string MATCHES_STRINGS string)
if( string STRLESS_STRINGS string)
if( string STREQUAL_STRINGS string)

-Bill


More information about the CMake mailing list