View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0015335CMakeCMakepublic2015-01-04 21:192015-06-01 08:38
ReporterBrian Chojnowski 
Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
StatusclosedResolutionno change required 
PlatformLinuxOSCentOSOS Version7
Product VersionCMake 3.1 
Target VersionFixed in Version 
Summary0015335: if () evaluates to FALSE for quoted constants/variables where the contents are non-null and not defined constants
DescriptionAn if statement should evaluate to TRUE if the variable is not-null and is not a defined false constant.

From the documentation:

if(<constant>)
True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number. False if the constant is 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, the empty string, or ends in the suffix -NOTFOUND. Named boolean constants are case-insensitive. If the argument is not one of these constants, it is treated as a variable.
if(<variable>)
True if the variable is defined to a value that is not a false constant. False otherwise. (Note macro arguments are not variables.)
Steps To Reproduceset(myvar "not a false constant")
message(STATUS "myvar=${myvar}")
if(myvar)
    message(STATUS "un quoted variable name = TRUE")
endif()
if(${myvar})
    message(STATUS "un quoted variable contents = TRUE")
endif()
if("${myvar}")
    message(STATUS "quoted variable = TRUE")
endif()

Output:

Eclipse version is set to 4.4 (). Adjust CMAKE_ECLIPSE_VERSION if this is wrong.
myvar=test string
un quoted variable name = TRUE
Configuring done
TagsNo tags attached.
Attached Files

 Relationships

  Notes
(0037633)
Brad King (manager)
2015-01-08 12:14

The if(<variable>) case refers to when <variable> is the name of a variable, not a reference to a variable.

For

 if(${myvar})

the if() command sees

 if(not\ a\ false\ constant)

which is not a defined variable or a true constant.

For

 if("${myvar}")

the if() command sees

 if("not a false constant")

which is not a defined variable or a true constant.
(0037635)
Brian Chojnowski (reporter)
2015-01-08 12:18

However, from the documentation of the if(<constant>) case:

If the argument is not one of these constants, it is treated as a variable.
if(<variable>)
(0037636)
Brian Chojnowski (reporter)
2015-01-08 12:21

So am I reading your notes correctly in that there is no defined rule for if(<not a true constant>) and if(<not a true variable>) ??

If so, seems like we should define the behavior. in this case.
(0037638)
Brad King (manager)
2015-01-08 12:29

Re 0015335:0037636: If it is not a defined constant or one of the later cases that involves a keyword then it is treated as the if(<variable>) case. That case defines the not-defined case as false (see text "False otherwise.").
(0037639)
Brian Chojnowski (reporter)
2015-01-08 12:45

if(<variable>)
True if the variable is defined to a value that is not a false constant. False otherwise. (Note macro arguments are not variables.)

This statement says that if the variable does not resolve to a false constant than the if() will evaluate true. The "False otherwise" sentence therefore applies to the case where the variable does resolve to a false constant.

Or said more plainly, anything that is not a false constant evaluates to TRUE.
(0037640)
Brad King (manager)
2015-01-08 12:51

Re 0015335:0037639: "False otherwise" is a separate sentence, meaning that the result is false if the case described in the first sentence is not true.
(0037641)
Brian Chojnowski (reporter)
2015-01-08 12:56

I have been trying to get the FindIce.cmake module to work correctly (CentOS 7 environment). The module is failing because the variable that contains the result of a find_library statement...

  foreach(component ${Ice_FIND_COMPONENTS})
    string(TOUPPER "${component}" component_upcase)
    set(component_cache "Ice_${component_upcase}_LIBRARY")
    set(component_found "${component_upcase}_FOUND")
    find_library("${component_cache}" "${component}"
      HINTS ${ice_roots}
      PATH_SUFFIXES ${ice_library_suffixes}
      DOC "Ice ${component} library")
    mark_as_advanced("${component_cache}")
    if("${component_cache}")

The if test evaluates to FALSE, even though it contains a non-empty path to the library.

I built this from source, if that matters.

Strangely, removing the quotes and issuing make clean;make; make install then makes this if () test evaluate TRUE... even though the minimal example in this bug report fails (this code was not in a module, just in the CMakeLists.txt file)
(0037642)
Brad King (manager)
2015-01-08 12:58

Re 0015335:0037640: Perhaps the wording can be clarified. How about

``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.)
(0037643)
Brad King (manager)
2015-01-08 13:03

Re 0015335:0037641: Please ask about the FindIce issue on the mailing list and CC the author of the module: Roger Leigh <rleigh@codelibre.net>
(0037644)
Brian Chojnowski (reporter)
2015-01-08 13:04

I agree the definition needs clarification of some sort. I am still confused as to why if (<string>) where string is not one of the false constants is evaluating as false.
(0037645)
Brian Chojnowski (reporter)
2015-01-08 13:06

if ("not a false constant")
    message(status "string is true")
endif()

This produces no output.
(0037646)
Brad King (manager)
2015-01-08 13:14

Re 0015335:0037644: The behavior was defined that way for use cases like

 if(COOL_OPTION)
   message(STATUS "cool option enabled")
 endif()

where the COOL_OPTION variable may or may not be defined. This is just like the C preprocessor where code like

 #if COOL_OPTION

will be true only if the symbol is defined to a non-false value.

Does the wording proposed in 0015335:0037642 describe the behavior clearly? (It is not intended to describe the design choice or motivation, just the behavior.)
(0037647)
Brian Chojnowski (reporter)
2015-01-08 13:26

I think the clarification will help. But I still am struggling to see why this also does not work.

if ("not a false constant")
    message(status "string is true")
endif()

This if evaluates to false. "not a false constant" is a defined string and not one of the false constants correct? so I believe this should evaluate to TRUE.
(0037648)
Brad King (manager)
2015-01-08 13:34

Re 0015335:0037647: There is no

 set("not a false constant" 1)

line so "not a false constant" is not the name of a defined variable. Therefore the string does not name a variable that is defined to a value that is not a false constant.
(0037649)
Brian Chojnowski (reporter)
2015-01-08 13:39

Are you implying that if ("some text here") is not of the form: if(<constant>) ??

If so I understand why I am confused.
(0037650)
Brad King (manager)
2015-01-08 13:43

Re 0015335:0037649: The documentation of if(<constant>) says "If the argument is not one of these constants, it is treated as a variable".
(0037651)
Brad King (manager)
2015-01-08 13:45

I've revised the documentation:

 Help: Clarify if(<variable>) documentation
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7a2c3f0c [^]
(0037652)
Brian Chojnowski (reporter)
2015-01-08 13:50

Ok I see, so if ("sometext") is treated as if (sometext).

I think I found why FindIce.cmake worked in 2.8 and not 3.1. I will work with the FindIce developer to update the module.

this code placed in CMakeLists.txt (and not a module that might have the CMFoo54 policy set to NEW):

set(fooref "foo")
set ("${fooref}" "some string")
if ("${fooref}")
    message(status "string is true")
endif()

produces this output:

CMake Warning (dev) at CMakeLists.txt:3 (if):
  Policy CMP0054 is not set: Only interpret if() arguments as variables or
  keywords when unquoted. Run "cmake --help-policy CMP0054" for policy
  details. Use the cmake_policy command to set the policy and suppress this
  warning.

  Quoted variables like "foo" will no longer be dereferenced when the policy
  is set to NEW. Since the policy is not set the OLD behavior will be used.
This warning is for project developers. Use -Wno-dev to suppress it.

statusstring is true
(0037654)
Brad King (manager)
2015-01-08 14:15

Actually it looks like FindIce was fixed a few days ago for this. I've backported the change for inclusion in 3.1.1:

 FindIce: Port to work with CMP0054 NEW behavior
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cbaf0802 [^]
(0037655)
Brian Chojnowski (reporter)
2015-01-08 14:17

Fantastic. Thank you!
(0038831)
Robert Maynard (manager)
2015-06-01 08:38

Closing resolved issues that have not been updated in more than 4 months.

 Issue History
Date Modified Username Field Change
2015-01-04 21:19 Brian Chojnowski New Issue
2015-01-08 12:14 Brad King Note Added: 0037633
2015-01-08 12:14 Brad King Status new => resolved
2015-01-08 12:14 Brad King Resolution open => no change required
2015-01-08 12:18 Brian Chojnowski Note Added: 0037635
2015-01-08 12:21 Brian Chojnowski Note Added: 0037636
2015-01-08 12:29 Brad King Note Added: 0037638
2015-01-08 12:45 Brian Chojnowski Note Added: 0037639
2015-01-08 12:51 Brad King Note Added: 0037640
2015-01-08 12:56 Brian Chojnowski Note Added: 0037641
2015-01-08 12:58 Brad King Note Added: 0037642
2015-01-08 13:03 Brad King Note Added: 0037643
2015-01-08 13:04 Brian Chojnowski Note Added: 0037644
2015-01-08 13:06 Brian Chojnowski Note Added: 0037645
2015-01-08 13:14 Brad King Note Added: 0037646
2015-01-08 13:26 Brian Chojnowski Note Added: 0037647
2015-01-08 13:34 Brad King Note Added: 0037648
2015-01-08 13:39 Brian Chojnowski Note Added: 0037649
2015-01-08 13:43 Brad King Note Added: 0037650
2015-01-08 13:45 Brad King Note Added: 0037651
2015-01-08 13:50 Brian Chojnowski Note Added: 0037652
2015-01-08 14:15 Brad King Note Added: 0037654
2015-01-08 14:17 Brian Chojnowski Note Added: 0037655
2015-06-01 08:38 Robert Maynard Note Added: 0038831
2015-06-01 08:38 Robert Maynard Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team