Hi, On Monday, 14. April 2014, 19:23:19, Theodore Papadopoulo wrote: > > if ("${arg}" STREQUAL "TOTO") -> if ("TOTO" STREQUAL "TOTO") -> if > > (B STREQUAL B) > > What I do not follow is why there is an implicit evaluation of "TOTO" > into "B" (in both this case or the next I explicitely asked for a > string containing the content of the variable ${arg}, if I had > intended the content of the variable which name is in ${arg} I would > have written ${${arg}}.
If it is any consolence to you, this is one of the most-hated (anti-)features of cmake. The best you can do is to embrace this oddity (it's not going to go away soon), and use a different idiom: Instead of ``"${var}" STREQUAL "VALUE"'', write: IF ( var MATCHES "^VALUE$" ) -> The MATCHES expression only does string/variable expansion on the right side. Therefore you get a well-defined behaviour regardless of any possible aliasing effects on variable names and values. > Of course, you are right about what happened, it is just very unsafe. > That means that if I'm using as a variable name the name of a constant > used in some other module, there will be very unexpected failures.... You are totally right. I guess if there was a way to change this in a backwards-compatible way, cmake developers would not hesitate to do so. > For example taking /usr/share/cmake/Modules/FeatureSummary.cmake as an > example, if I set a variable PROPERTIES with a value might (untested) > provoke quite unexpected results (if(NOT "${_props}" STREQUAL > "PROPERTIES")). Or if I do set(0 1) before calling > CheckLanguage.cmake (if(CMAKE_${lang}_COMPILER AND "${result}" > STREQUAL "0")). You can have even more fun by redefining some version strings: set(MY_VERSION "2.8.15") set("2.8.15" hehehe) if (MY_VERSION VERSION_EQUAL "2.8.15" ) message("All as expected...") else() message("I'm so evil!") endif() # You can probably guess what this prints out ;-) IMO one thing that *could* be done would be to deprecate the unsafe expressions and replace them with some safe version. > I realize now that this is what probably means the > if(<variable|string> STREQUAL <variable|string>) > in the cmake manual. But in my reading that was meaning some > overloading so that > > TOTO is a variable so evaluated into ${TOTO} > but "TOTO" remains a string and is not evaluated any further. > > At least that what I thought (basically at some type system > differentiating variables and strings)... I'm clearly wrong as: > > set(TOTO B) > if ("B" STREQUAL "TOTO") > message("AhAh") > endif() What helped me to understand it was to see this as a two-step procedure: 1) Parsing: ${variable} gets replaced by its value 2) Execution: IF is called with the strings as argument. At step 2, the IF statement cannot possibly determine how its arguments looked before expansion. > > if ( "_ASDF_${arg}" STREQUAL "_ASDF_TOTO") > > Well I knew the technique, but thought it was mainly for protection > againts empty strings (which "${arg}" should be equivalent). Not sure > it makes the thing safer though. > > Well I guess I need to go and see cmake source code, as I cannot > understand cery well its evaluation rules. Sorry for my mistake in the first mail. I wrote my response rather quick, not pausing to think of better alternatives. Had I invested more time, I would've given you the solution using "MATCHES" that I explained above. Sorry for the inconvenience... Cheers, Johannes -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake