I've been working in a software project which used cmake, where the file structure looked something like this:
Each one of the folders contains one CMakeLists.txt, which basically adds more files to the source code files list that is defined in the CMakeLists.txt present in the src folder. The thing is, it wasn't practical to pass all these variables up all along the scope stack with PARENT_SCOPE, so we were using properties for that.
It was working well until we decided that to ease testing, it would be useful to have each one of the submodules built on an static library. And so I've been working in a macro that looks like this:
macro(define_build_unit unit_name unit_root)
function(${unit_name}_add_sources)
message(STATUS ${ARGN})
file(RELATIVE_PATH _relPath ${unit_root} "${CMAKE_CURRENT_SOURCE_DIR}")
foreach(_src ${ARGN})
if(_relPath)
list(APPEND ${unit_name}_SRCS "${_relPath}/${_src}")
else()
list(APPEND ${unit_name}_SRCS "${_src}")
endif()
endforeach()
if(_relPath)
set_property(GLOBAL APPEND PROPERTY ${unit_name}_SRCS ${${unit_name}_SRCS})
endif()
endfunction()
function(${unit_name}_add_link_deps)
foreach(_dep ${ARGN})
list(APPEND ${unit_name}_DEPS "${_dep}")
endforeach()
set_property(GLOBAL APPEND PROPERTY ${unit_name}_DEPS ${${unit_name}_DEPS})
endfunction()
function(${unit_name}_add_include_dirs)
foreach(_inc ${ARGN})
list(APPEND ${unit_name}_INC_DIRS "${_inc}")
endforeach()
set_property(GLOBAL APPEND PROPERTY ${unit_name}_INC_DIRS ${${unit_name}_INC_DIRS})
endfunction()
endmacro()
The problem is that ARGN is being substituted from the define_build_unit macro, and not from the corresponding function. I've tried all the combinations of macro/function and nothing seems to work.
So, the question is: is there a better way for variable arguments in cmake than the ARGN global variable? Something like macro(my_macro args...)? If not, does somebody know of an equivalent way to accomplish the same?
This question has already been accepted however, in my case I really did need to have the function definition inside of a macro. The reason? I wanted to programmatically generate specialized functions based on the macro parameters. This meant taking advantage of the text replacement functionality of macros, while producing a dynamically created function that could then be used in the rest of the build.
macro(build_my_func func_name)
message(${ARGV})
function(my_${func_name})
set(func_ARGV ARGV)
message(${${func_ARGV}})
endfunction()
endmacro()
The "trick" is to set a variable inside the function that contains the NAME of the variable you want to access, in this case ARGV. Then, it can be accessed as a variable-variable, ie: ${${func_ARGV}}. In this instance, the inner variable ${func_ARGV} is replaced with ARGV, ultimately resolving to ${ARGV}.
It's a little bit of a workaround but can be a useful way to access any variables that the outer macro may stamp out. It can also be used to cache macro parameters as values to be used in the function to customize its behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With