Feature to disable empty parameters resolving into unset function arguments

I would love to see some progression in CMake syntaxt such that it gets more safe and better to use.

Such as to disable set(A ${var}) which accidentially unsets variable A if var is empty.
Instead the the set should always resolve into setting an empty string, and not unsetting a variable.
That would greatly improve errors, e.g.


set(var ${SOME_GLOBAL}) # global might be unset

if(var STREQUAL "")
  # this if is never reached if `SOME_GLOBAL` is empty...
endif()

Also it would be nice if any command evaluating a var-name argument would FATAL_ERROR when this variable is not defined. e.g.


if(missingVar STREQUAL "asd") # Direct error here: Variable `missingVar` is undefined.
endif()

You should use “${SOME_GLOBAL}” instead of ${SOME_GLOBAL}. So the value is set to the empty string instead of unsettling the value. In general it is good practice (and even sometimes necessary) to enclose variable access with “” (avoid splitting at white spaces resp. complete elimination if there are only white spaces)

You can check with if ( DEFINED ) if a variable is set.
Just check out:

set ( a )
set ( b “”)

if ( DEFINED a )
message ( “a defined” )
endif()

if ( DEFINED b )
message ( “b defined” )
endif()

You should use “${SOME_GLOBAL}”

This is not enough. For example:

function(ttt ret)
   set(inner "")
   set(${ret} "${inner}" PARENT_SCOPE) 
endfunction()

ttt(ttt_ret)
message(${ttt_ret})

Now play with different versions of this code. For example:

  • replace "${inner}" by ${inner}
  • initialize ret before using ttt; call ttt(${ret}). Vary:
    • set(ret "") # in principle an unset, with at times quite interesting ramifications
    • set(ret "x")
  • make ret a read parameter of ttt and call ttt("")
  • set inner to something not empty
  • embed the message parameter in quotes
  • combine all this in endless ways; nest your functions

More fun:

  • instead/additionally to function parameter passing use if
  • add string(JSON ...) to the game

Enjoy! (this is simply a big mud ball of incomprehensible corner cases)

p.s.: Did I mention lists?

Hm. Jeah it would be nice to close these mud holes such that devs do not get more frustrated about such basic things… Bit I habe no idea given the cirrcumstances about backward compat and policies. It needs a bold step to get rid of these akward scenarios…

if(var STREQUAL "")

It would be much better to do this instead:

if(NOT var)
    ...
endif()

That’s not equal, the latter also matches some possibly valid values of var.

You could also do

if(NOT DEFINED var)
...
endif()