Cmake: add_custom_command argument based on variable content

陌路散爱 提交于 2020-01-24 06:55:27

问题


I'd like to have a Cmake function to copy some binaries to a specific location. Fo this I have the following function definition :

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 )

And the following usage :

collect_binaries( bin_copy ${PROJECT_BINARY_DIR}/out/ target_1 target_2 target3 )

I have target_1, target_2 and target_3 defined inside my project tree. With this in mind I got the following Cmake configure output :

CMake Warning (dev) at binary_copy.cmake:15 (add_custom_command):

Policy CMP0040 is not set: The target in the TARGET signature of add_custom_command() must exist. Run "cmake --help-policy CMP0040" for policy details. Use the cmake_policy command to set the policy and suppress this warning.

It seems that target in unknown in this context...but it does exist and there is no typo. What is the issue here?


回答1:


You are setting up the copy_cmd variable in the collect_binaries function as a CMake string. The add_custom_command however requires a CMake list to parse the arguments correctly, i.e.:

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 )



回答2:


Command flow add_custom_command(TARGET ...) is for library and executable targets only. It is not intended for targets, created with add_cusom_target.

You need to make your custom target to be depended from binaries copied, and create commands for copy that binaries. (Note, that list of arguments for any cmake command shouldn't be enclosed into quotes).

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 )

If you want to have only copied binaries, but original ones are not interested for you, it is simpler to tell CMake to create binaries where you need them. Either

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/out/)

before creating targets or

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

after creating targets is sufficient.



来源:https://stackoverflow.com/questions/33696412/cmake-add-custom-command-argument-based-on-variable-content

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!