Vince
Vince

Reputation: 4401

CMake macro : how to iterate over arguments

taking inspiration from : https://cmake.org/cmake/help/v3.0/command/macro.html

I do:

macro(ARGS_TEST)
  message(WARNING "\nARGN: ${ARGN}\n")
  foreach(arg IN LISTS ARGN)
     message(WARNING "\n ARG : ${arg} \n")
  endforeach()
endmacro()

ARGS_TEST(test 1 2 3)

which prints:

ARGN: test;1;2;3

but nothing after this, meaning iteration over ARGN does not seem to be happening.

Anything I am missing ?

Answer to following question: Passing a list to a cmake macro

shows how to print the arguments as a list, but not how to iterate over them

Upvotes: 5

Views: 9036

Answers (1)

Sqeaky
Sqeaky

Reputation: 1936

Macro argument aren't variables. So ARGN isn't treated like other lists in this context. I see two ways to work around this issue:

In my reworkings of your samples I made your messages STATUS messages to ease my testing. This should work with WARNING as well.

The first way is to make this a function:

function(ARGS_TEST_FUNCTION)
  message(STATUS "\nARGN: ${ARGN}\n")
  foreach(arg IN LISTS ARGN)
     message(STATUS "\n ARG : ${arg} \n")
  endforeach()
endfunction()

ARGS_TEST_FUNCTION(test 1 2 3)

Like this ARGN is a variable and is expanded as expected. If you were wanting to set values in this loop you will need to use set and PARENT_SCOPE. Using parent scope might not be possible if you are calling other macros and do not know every variables they intend to set.

Alternatively we can do the expansion ourselves and tell the foreach we are passing a list:

macro(ARGS_TEST)
  message(STATUS "\nARGN: ${ARGN}\n")
  foreach(arg IN ITEMS ${ARGN})
     message(STATUS "\n ARG : ${arg} \n")
  endforeach()
endmacro()

ARGS_TEST(test 1 2 3)

This came from the foreach page in the CMake documentation

Upvotes: 6

Related Questions