28

I would like to create a CMake function as:

function(test src_list dst_list)
# do something
endfunction()

usage:

test(${my_list} chg_list)

It means, my_list is a list with several fields, and chg_list will receive a list modified inside test function.

How can I create a function in CMake to do that?

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
Alex
  • 3,301
  • 4
  • 29
  • 43
  • 7
    Problem is you don't provide the code of the function. Is there `set(${dst_list} PARENT_SCOPE);` in it? – julp Mar 18 '14 at 22:23

4 Answers4

45

In CMake, functions have their own scope, and by default, all modification of variables are local, unless you pass CACHE or PARENT_SCOPE as parameter to set. Inside a function, if you want to modify a variable in the scope of the caller, you should use:

set(${dst_list} <something> PARENT_SCOPE)

See documentation:

A function opens a new scope: see set(var PARENT_SCOPE) for details.

Antonio
  • 19,451
  • 13
  • 99
  • 197
lrineau
  • 6,036
  • 3
  • 34
  • 47
8

Check that inside your function you are set()ing not dst_list but ${dst_list}. You need this to return data to the parent scope.

arrowd
  • 33,231
  • 8
  • 79
  • 110
2

Here's how I solved a similar problem which was marked a duplicate of this question. This function takes a string BinaryName and adds it to the list OutVariable which is available in the parent scope. If the list is not defined it is created. I use this strategy for creating new test targets and adding the name of these targets to a list of targets in the main scope.

Thanks to @Tsyvarev for the comments that lead me to figure this out.

function(AddToListFromFunction BinaryName OutVariable)
    if ("${${OutVariable}}" STREQUAL "")
        message(STATUS "1")
        set(${OutVariable} ${BinaryName} PARENT_SCOPE)
        message(STATUS "OutVariable: ${OutVariable} ${${OutVariable}}")
    else ()
        message(STATUS "2")
        set(${OutVariable} "${${OutVariable}}" "${BinaryName}" PARENT_SCOPE)
    endif ()
endfunction()
AddToListFromFunction(MyBinary1 MyTests)
AddToListFromFunction(MyBinary2 MyTests)
message(STATUS "MyTests Variable:  ${MyTests}")
CiaranWelsh
  • 7,014
  • 10
  • 53
  • 106
  • 1
    While the name of the function `AddToListFromFunction` looks self-explanatory, it would be useful to provide a little description of your "similar problem" directly in this answer. – Tsyvarev Oct 27 '20 at 21:21
0

These days, with CMake 3.25 or later, you can do this with the PROPAGATE clause of the return statement, e.g. as in:

function(test dst_list)
  set(${dst_list} "12;34")
  return(PROPAGATE ${dst_list})
endfunction()

... which is nicer to read. See also the CMake documentation for me details.

einpoklum
  • 118,144
  • 57
  • 340
  • 684