[CMake] lexical scoping/closure of FUNCTION

Matt Darland matthew.darland at nyab.com
Fri Feb 11 11:22:17 EST 2011


In the example below it appears the ${${target}} is evaluating the
variable name in ${target} within the scope of the local function, not
in the context of the caller as I would have expected. This is
apparently caused by the fact that both functions have local variables
named _dest. It's easier to illustrate than to explain so:

<code>
#-- STRING_APPEND(target s [dest])
#-- Appends string 's' to string 'target'. Result is placed in 'target'
unless
#-- a destination is specified as the last parameter
FUNCTION(STRING_APPEND target s)
  IF(ARGN)
    SET(_dest ${ARGV2})
  ELSE()
    SET(_dest ${target})
  ENDIF()

  SET(${_dest} "${${target}}${s}" PARENT_SCOPE)
ENDFUNCTION()


#-- LIST_JOIN(src target [sep])
#-- Takes a cmake list and flattens it out into a string, separated by
space
#-- or optionally 'sep'
FUNCTION(LIST_JOIN src target)
  SET(_dest "")
  IF(ARGN)
    SET(_sep ${ARGV2})
  ELSE()
    SET(_sep " ")
  ENDIF()

  SET(_srcvals ${${src}})
  LIST(LENGTH _srcvals _srclen)
  IF(_srclen GREATER 0)
    #-- Handle first element special case
    LIST(GET _srcvals 0 _dest)
    LIST(REMOVE_AT _srcvals 0)

    FOREACH(_i ${_srcvals})
	  STRING_APPEND(_dest "${_sep}${_i}")
    ENDFOREACH()
  ENDIF()
  SET(${target} ${_dest} PARENT_SCOPE)
ENDFUNCTION()


SET(x "hello")
MESSAGE(STATUS "${x}") #-- prints 'hello'
STRING_APPEND(x " world")
MESSAGE(STATUS "${x}") #-- prints 'hello world'


SET(y a b c)
MESSAGE(STATUS "${y}") #-- prints 'a;b;c'
LIST_JOIN(y z "-")
MESSAGE(STATUS "${z}") #-- should print 'a-b-c', instead we get
'_dest-c'
</code>


Adding the following debug print before the last line in STRING_APPEND
  MESSAGE(STATUS "_dest = ${_dest}")
  MESSAGE(STATUS "*target = ${${target}}")

Yields the following output
-- hello
-- _dest = x
-- *target = hello
-- hello world
-- a;b;c
-- _dest = _dest
-- *target = _dest
-- _dest = _dest
-- *target = _dest
-- _dest-c

If I change the name of the var _dest in the LIST_JOIN to a var name
that doesn't exist in STRING_APPEND (e.g. _dest_foo), everything works.
It appears that STRING_APPEND doesn't know that the value in ${target}
is associated with the parent scope.

The question I have at this point is:
a) Is this by design?
b) Am I just brain damaged for doing this?
c) Should I file a bug?

Thanks


This transmission is intended solely for the addressee and contains confidential information.
If you are not the intended recipient, please immediately inform the sender and delete the message and any attachments from your system. 
Furthermore, please do not copy the message or disclose the contents to anyone unless agreed otherwise. To the extent permitted by law we shall in no way be liable for any damages, whatever their nature, arising out of transmission failures, viruses, external influence, delays and the like.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.cmake.org/pipermail/cmake/attachments/20110211/9bb1cc35/attachment-0001.htm>


More information about the CMake mailing list