Reputation: 20266
Inspired by this, I was trying to create a macro that would copy at build time a list of files.
macro (copy_files_at_build_time targetname) #usage: copy_files_at_build_time(<targetname> <file> [<files>] <destination>)
if(ARGC LESS 3)
message(ERROR "copy_files_at_build_time called with less than 3 arguments")
endif(ARGC LESS 3)
MATH(EXPR LAST_INDEX "${ARGC}-2")
MATH(EXPR DEST_INDEX "${ARGC}-1")
set(MY_DESTINATION ${ARGV${DEST_INDEX}})
foreach(I RANGE 1 ${LAST_INDEX})
message (STATUS "${CMAKE_COMMAND} -E copy ${ARGV${I}} ${MY_DESTINATION}")
add_custom_command(TARGET ${targetname} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ARGV${I}} ${MY_DESTINATION})
endforeach(I)
endmacro(copy_files_at_build_time)
As you can see there is a debug message, and unfortunately both ${ARGV${I}}
and ${MY_DESTINATION}
(which is ${ARGV${DEST_INDEX}}
) are empty when I print them. So, it seems that is not possible to access to ARGV1, ARGV2 etc. (see macro documentation) by using a variable as last part of the variable name. I will now implement a workaround using the list commands, but my question is:
Is there an easier way to cycle on the ARGV0, ARGV1, ARGV2 elements, if some of the elements (e.g. the first and the last) have to be skipped?
Edit
Sadly enough, I am seeing that not even the LIST commands work on ARGV! But they work if first I create a copy of ARGV and then perform the LIST commands on it.
Upvotes: 0
Views: 1543
Reputation: 20266
This is the implementation I ended up with, I am open to better solutions!
Note: the second function (the one that copies also directories) is probably safer in case some of the destination directories did not exist.
macro (copy_files_at_build_time targetname) #usage: copy_files_at_build_time(<targetname> <file> [<files>] <destination>)
if(ARGC LESS 3)
message(ERROR "copy_files_at_build_time called with less than 3 arguments")
endif(ARGC LESS 3)
SET(ARGN_COPY ${ARGN})
MATH(EXPR DEST_INDEX "${ARGC}-2") #It should be "${ARGC}-1", but we are using ARGN that doesn't contain the first element of the list
list(GET ARGN_COPY ${DEST_INDEX} MY_DESTINATION)
list(REMOVE_AT ARGN_COPY ${DEST_INDEX})
foreach(MY_FILE ${ARGN_COPY})
# message (STATUS "${CMAKE_COMMAND} -E copy_if_different ${MY_FILE} ${MY_DESTINATION}")
add_custom_command(TARGET ${targetname} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${MY_FILE} ${MY_DESTINATION})
endforeach(MY_FILE)
endmacro(copy_files_at_build_time)
If we want to copy also directories (beware: not tested if it works recursively!)
macro (copy_at_build_time targetname) #usage: copy_at_build_time(<targetname> <file|directory> [<files|directories>] <destination>)
if(ARGC LESS 3)
message(ERROR "copy_files_at_build_time called with less than 3 arguments")
endif(ARGC LESS 3)
SET(ARGN_COPY ${ARGN})
MATH(EXPR DEST_INDEX "${ARGC}-2") #It should be "${ARGC}-1", but we are using ARGN that doesn't contain the first element of the list
list(GET ARGN_COPY ${DEST_INDEX} MY_DESTINATION)
list(REMOVE_AT ARGN_COPY ${DEST_INDEX})
foreach(MY_FILE ${ARGN_COPY})
get_filename_component(LEAF_NAME "${MY_FILE}" NAME)
if (IS_DIRECTORY ${MY_FILE})
add_custom_command(TARGET ${targetname} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${MY_FILE} ${MY_DESTINATION}/${LEAF_NAME})
else(IS_DIRECTORY ${MY_FILE})
add_custom_command(TARGET ${targetname} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${MY_FILE} ${MY_DESTINATION}/${LEAF_NAME})
endif(IS_DIRECTORY ${MY_FILE})
endforeach(MY_FILE)
endmacro(copy_at_build_time)
Upvotes: 0
Reputation: 21864
${ARGV${DEST_INDEX}})
is not supported in MACROS (at least form my experience). You must perform LIST(...)
operations to handle the MACRO arguments using the ${ARGV}
list of arguments.
Use either:
LIST(REMOVE_AT, ...)
or similar list operations to remove arguments orFOREACH(loop_var IN ...)
Upvotes: 2