How to set the global variable in a function for cmake?

Go To StackoverFlow.com

9

I'm writing a CMakeLists.txt to generate files and compile the generated files. I create a function to add some file path strings to a global list variable.

My CMakeLists.txt:

set(source_list "nothing")
function(test file_path)
    list(APPEND source_list ${file_path})
endfunction(test)
test(abc.txt)
test(def.txt)
message("At last, the source_list is:\"${source_list}\"")

The cmake output:

At last, the source_list is:"nothing"

Someone suggested that to use macro instead of function, but I do need use local variable, so I need to use the function instead of macro.

How can I correctly set the global variable source_list in the function test()? Can't cmake do it in a simple and normal way?

2012-04-05 15:59
by sean


13

You need to use set instead of list to affect the variable in the parent scope.

So replace your list command with:

set(source_list ${source_list} ${file_path} PARENT_SCOPE)
2012-04-05 16:25
by Fraser
It's not global though, siblings will not see - 0xbaadf00d 2017-04-04 06:32
@JoachimW: Why incorporate two answers into the single one? You seems to misunderstand Question/Answer model on Stack Overflow. We do NOT tend to have all solutions in the single accepted answer. Instead, having one answer per solution is perfect. And an answer's quality is primarily measured by the voting, good answers needn't to be marked with the green accept mark. Please, revert this answers merging - Tsyvarev 2018-10-01 10:37


15

PARENT_SCOPE is only for parent, it won't work if you have other non-parent script that want to see it as well.

You need cache for the true "global-like" variable. In your case, use:

SET(source_list  "${source_list}" CACHE INTERNAL "source_list")
2014-08-05 03:05
by Ding-Yi Chen
It doesn't work for second run of cmake, because value is already in cache. You must clean before build - Maxim Suslov 2016-02-25 07:23
INTERNAL implied FORCE, which means: Use the FORCE option to overwrite existing entries - Ding-Yi Chen 2016-02-25 22:49


6

Another approach is to use global properties. Once you set it:

set_property(GLOBAL PROPERTY source_list_property "${source_list}")

you can read it from everywhere:

get_property(source_list GLOBAL PROPERTY source_list_property)

I used in examples above the different names for property (source_list_property) and for variable (source_list). Maybe it is better to use the same name. But point is to use a property as global variables, and not about naming.

Such global properties aren't in cache.

2017-09-25 19:54
by Maxim Suslov


1

Building upon Maxim Suslov's answer, the following code worked for a similar problem I faced:

set_property(GLOBAL PROPERTY source_list)
function(add_source)
    get_property(tmp GLOBAL PROPERTY source_list)
    foreach(arg ${ARGV})
        set(tmp "${tmp} ${arg}")
    endforeach()
    set_property(GLOBAL PROPERTY source_list "${tmp}")
endfunction(add_source)

add_source(a_file)
add_source(b_file c_file)

get_property(local_prop GLOBAL PROPERTY source_list)
message("list: ${local_prop}")

Function add_source can be called from inside any sub-directory.

2017-11-29 10:30
by Marios V
Ads