View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0010719CMakeCMakepublic2010-05-16 03:352010-11-09 22:57
ReporterYevgen Muntyan 
Assigned ToDavid Cole 
PrioritynormalSeverityblockReproducibilityalways
StatusclosedResolutionno change required 
PlatformOSOS Version
Product VersionCMake-2-8 
Target VersionFixed in VersionCMake 2.8.3 
Summary0010719: IF("foo" MATCHES "foo") broken
DescriptionThe following script produces an error:

SET(foo FALSE)
IF(NOT "foo" MATCHES "foo")
  MESSAGE(FATAL_ERROR "oops")
ENDIF(NOT "foo" MATCHES "foo")

It treats "foo" as variable foo in this case (if you do SET(foo foo) in the beginning, the error goes away). There is no error if there is STREQUAL instead of MATCHES; no error if foo isn't set before.

This is particularly bad because cmake does it:

MACRO(CHECK_C_SOURCE_COMPILES SOURCE VAR)
  IF("${VAR}" MATCHES "^${VAR}$")
  ...
TagsNo tags attached.
Attached Files

 Relationships

  Notes
(0022293)
David Cole (manager)
2010-09-21 12:01

The behavior reported here is "by design."

When CMake does a comparison like this:
  IF("${VAR}" MATCHES "^${VAR}$")

...it is equivalent to:
  IF(NOT DEFINED VAR)

...but it works with ancient CMake versions that existed before IF DEFINED was supported.

Basically, the IF command takes a look at its args and tries to use variables of those names first, and then if the variable's not there, it uses it as a plain string value.

It is confusing, but that's the way it works for now. We cannot change this without breaking backwards compatibility for lots of projects without a quite complicated CMake policy to govern the behavior of if(VARIABLE commands.
(0022306)
Yevgen Muntyan (reporter)
2010-09-21 16:14

(Reopening because I can't make a comment otherwise).

Could you then document exact behavior of IF() and fix the bug caused by that particular IF() command in cmake code?
(0022307)
David Cole (manager)
2010-09-21 16:30

Please state what actually happens vs. what you expect to happen.

Your original report was this:
<original>
The following script produces an error:

SET(foo FALSE)
IF(NOT "foo" MATCHES "foo")
  MESSAGE(FATAL_ERROR "oops")
ENDIF(NOT "foo" MATCHES "foo")
</original>

There is no bug here. If you run this script, you will get a FATAL_ERROR. If you don't want a FATAL_ERROR, then change the script.

The documentation for IF command is quite detailed, but you must read it all the way to the bottom and pay very close attention to the details at the end of that documentation to understand this behavior and the reasons for maintaining it as is.
(0022308)
David Cole (manager)
2010-09-21 16:30

Online docs for "IF" are here:
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:if [^]
(0022314)
Yevgen Muntyan (reporter)
2010-09-21 23:24

I see, I assumed that if you quote a string then it is going to be treated as a string (as opposed to maybe-variable-maybe-string), I thought docs said that somewhere. Documentation for IF() command doesn't mention quotes at all, so I suppose that means quotes don't matter. I still think it's FUBAR, since we have CMAKE_REQUIRE which could turn off strange compatibility quirks, but that's not so important.

The bug I mentioned:

CHECK_C_SOURCE_COMPILES(SOURCE VAR) macro (as well as _RUNS and their CXX buddies) assumes that variable VAR is unique, but it shouldn't. I should be able to do

CHECK_C_SOURCE_COMPILES(some_source temp_bool_var)
if(temp_bool_var) ...
CHECK_C_SOURCE_COMPILES(some_other_source temp_bool_var)
if(temp_bool_var) ...

Now, I can see why these macros could assume uniqueness of the variable, but that's not documented, and combined with the IF() quirk I just assumed it was a bug caused by a bug in IF().
(0022316)
David Cole (manager)
2010-09-22 07:01

In the case of:
CHECK_C_SOURCE_COMPILES(some_source temp_bool_var)

"temp_bool_var" is not temporary. It is a cache variable so that the try compile only has to occur once in any given build tree. That variable should be unique in your whole build tree. Same for any other try_compile result.

I agree that the behavior of CMake IF is strange w.r.t. strings that happen to be variable names. Changing would be possible with a policy, but the differences are so subtle in some cases, it is definitely going to be a challenge...

I'll resolve this again now. Perhaps bringing up something like this on the mailing list would get more people interested in the idea of changing the IF command to "something better"...

 Issue History
Date Modified Username Field Change
2010-05-16 03:35 Yevgen Muntyan New Issue
2010-09-21 11:56 David Cole Status new => assigned
2010-09-21 11:56 David Cole Assigned To => David Cole
2010-09-21 12:01 David Cole Note Added: 0022293
2010-09-21 12:01 David Cole Status assigned => resolved
2010-09-21 12:01 David Cole Fixed in Version => CMake 2.8.3
2010-09-21 12:01 David Cole Resolution open => no change required
2010-09-21 16:14 Yevgen Muntyan Note Added: 0022306
2010-09-21 16:14 Yevgen Muntyan Status resolved => feedback
2010-09-21 16:14 Yevgen Muntyan Resolution no change required => reopened
2010-09-21 16:30 David Cole Note Added: 0022307
2010-09-21 16:30 David Cole Note Added: 0022308
2010-09-21 23:24 Yevgen Muntyan Note Added: 0022314
2010-09-22 07:01 David Cole Note Added: 0022316
2010-09-22 07:02 David Cole Status feedback => resolved
2010-09-22 07:02 David Cole Resolution reopened => no change required
2010-11-09 22:57 Philip Lowman Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team