在cmake中循环部分宏的参数

时间:2013-07-15 13:32:07

标签: cmake

受到this的启发,我试图创建一个macro,它会在构建时复制文件列表。

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)

正如您所看到的那样,有一条调试消息,不幸的是,当我打印它们时,${ARGV${I}}${MY_DESTINATION}${ARGV${DEST_INDEX}})都是空的。因此,似乎无法通过使用变量作为变量名的最后一部分来访问ARGV1,ARGV2等(请参阅macro documentation)。我现在将使用list命令实现一种解决方法,但我的问题是:

如果必须跳过某些元素(例如第一个和最后一个元素),是否有更简单的方法在ARGV0,ARGV1,ARGV2元素上循环?

修改

可悲的是,我发现即使是LIST命令也无法在ARGV上运行!但是如果我首先创建一个ARGV副本然后在其上执行LIST命令,它们就可以工作。

2 个答案:

答案 0 :(得分:2)

MACROS不支持

${ARGV${DEST_INDEX}})(至少根据我的经验)。您必须使用LIST(...)参数列表执行${ARGV}操作来处理MACRO参数。

使用:

  • LIST(REMOVE_AT, ...)或类似的列表操作,用于删除参数或
  • 使用FOREACH(loop_var IN ...)
  • 进行迭代

答案 1 :(得分:0)

这是我最终的实施,我愿意接受更好的解决方案! 注意:如果某些目标目录不存在,第二个函数(也复制目录的那个)可能更安全。

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)

如果我们想复制目录(注意:如果递归工作则不测试!)

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)