Cmake:基于变量内容添加自定义命令参数

8

我希望有一个Cmake函数,可以将一些二进制文件复制到特定的位置。为此,我有以下函数定义:

function ( collect_binaries TARGET_NAME DEST_DIR )
   set ( targetsToCopy ${ARGN} )

   set ( copy_cmd "COMMAND ${CMAKE_COMMAND} -E make_directory ${DEST_DIR}\n" )

   foreach ( target ${targetsToCopy} )
      LIST( APPEND copy_cmd "COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${target}> ${DEST_DIR}$<TARGET_FILE_NAME:${target}>\n")
   endforeach( target ${targetsToCopy} )

   #message( FATAL_ERROR ${copy_cmd} )
   add_custom_target( ${TARGET_NAME} )
   add_custom_command( TARGET ${TARGET_NAME} PRE_BUILD ${copy_cmd} )

endfunction( collect_binaries )

以下是使用方法:
collect_binaries( bin_copy ${PROJECT_BINARY_DIR}/out/ target_1 target_2 target3 )

我在项目树中定义了 target_1、target_2 和 target_3。考虑到这一点,我得到了以下的 Cmake 配置输出:

CMake 警告(dev):在 binary_copy.cmake 的第 15 行(add_custom_command 函数),policy CMP0040 没有设置:add_custom_command 函数 TARGET 签名中的目标必须存在。要查看政策详细信息,请运行“cmake --help-policy CMP0040”。使用 cmake_policy 命令来设置政策并按下面的示例抑制此警告。

在这里,似乎在该上下文中未知的目标...但它确实存在,并且没有拼写错误。问题在哪里?

我尝试使用自定义命令做了和你一样的事情,虽然可行但很丑陋。你真正想要做的是将二进制文件安装到一个位置,这样代码会更少,也更美观。 - CoffeDeveloper
2个回答

4
collect_binaries函数中,您正在设置copy_cmd变量作为CMake字符串。然而,add_custom_command要求一个CMake列表来正确解析参数,例如:
function ( collect_binaries TARGET_NAME DEST_DIR )
   set ( targetsToCopy ${ARGN} )

   set ( copy_cmd COMMAND ${CMAKE_COMMAND} -E make_directory ${DEST_DIR} )

   foreach ( target ${targetsToCopy} )
      LIST( APPEND copy_cmd COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${target}> "${DEST_DIR}$<TARGET_FILE_NAME:${target}>")
   endforeach( target ${targetsToCopy} )

   #message( FATAL_ERROR ${copy_cmd} )
   add_custom_target( ${TARGET_NAME} )
   add_custom_command( TARGET ${TARGET_NAME} PRE_BUILD ${copy_cmd} )

endfunction( collect_binaries )

非常感谢您的解决方案和解释 - 它有效! - Dmitry

0

命令流程add_custom_command(TARGET ...)仅适用于库和可执行目标。它不适用于使用add_cusom_target创建的目标。

您需要使自定义目标依赖于复制的二进制文件,并创建复制这些二进制文件的命令。(注意,任何cmake命令的参数列表都不应该用引号括起来)。

function ( collect_binaries TARGET_NAME DEST_DIR )
    set ( targetsToCopy ${ARGN} )

    set (create_directory_cmd COMMAND ${CMAKE_COMMAND} -E make_directory ${DEST_DIR})

    # Create one custom command per every file to be copied.
    # Also collect list of output files.
    set(output_files)
    foreach ( target ${targetsToCopy} )
        set(output_file "${DEST_DIR}/$<TARGET_FILE_NAME:${target}>")
        add_custom_command(OUTPUT ${output_file}
            ${create_directory_cmd}
            COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${target}> ${output_file})
        list(APPEND output_files ${output_file})
        # It is sufficient to create directory only once. Just clear corresponded variable.
        set(create_directory_cmd)
    endforeach( target ${targetsToCopy} )

    add_custom_target( ${TARGET_NAME} DEPENDS ${output_files})
endfunction( collect_binaries )

如果您只想要复制的二进制文件,而原始文件对您没有兴趣,那么更简单的方法是告诉CMake在需要它们的地方创建二进制文件。
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/out/)

创建目标之前或

set_target_properties(target_1 target_2 target3
    PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/out/)

创建目标后就足够了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接