CMake Custom Command copy multiple files

前端 未结 4 1562
清歌不尽
清歌不尽 2020-12-17 09:15

I am attempting to copy multiple files using the ${CMAKE_COMMAND} -E copy format, but I was wondering if there was a way to provide a nu

相关标签:
4条回答
  • 2020-12-17 09:57

    Copying multiple files is available from CMake 3.5

    cmake -E copy <file>... <destination>
    

    "cmake -E copy" support for multiple files

    Command-Line Tool Mode

    0 讨论(0)
  • 2020-12-17 09:57

    A relatively simple workaround would be to use ${CMAKE_COMMAND} -E tar to bundle the sources, move the tarball and extract it in the destination directory.

    This could be more trouble than it's worth if your sources are scattered across many different directories, since extracting would retain the original directory structure (unlike using cp). If all the files are in one directory however, you could achieve the copy in just 2 add_custom_command calls.

    Say your sources to be moved are all in ${CMAKE_SOURCE_DIR}/source_dir, the destination is ${CMAKE_SOURCE_DIR}/destination_dir and your list of filenames (not full paths) are in ${FileList}. You could do:

    add_custom_command(
        TARGET MyExe POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E tar cfj ${CMAKE_BINARY_DIR}/temp.tar ${FileList}
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/source_dir)
    
    add_custom_command(
        TARGET MyExe POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_BINARY_DIR}/temp.tar temp.tar
        COMMAND ${CMAKE_COMMAND} -E tar xfj temp.tar ${FileList}
        COMMAND ${CMAKE_COMMAND} -E remove temp.tar
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/destination_dir)
    
    0 讨论(0)
  • 2020-12-17 10:12

    I did it with a loop

    # create a list of files to copy
    set( THIRD_PARTY_DLLS
       C:/DLLFOLDER/my_dll_1.dll
       C:/DLLFOLDER/my_dll_2.dll
    )
    
    # do the copying
    foreach( file_i ${THIRD_PARTY_DLLS})
        add_custom_command(
        TARGET ${VIEWER_NAME}
        POST_BUILD
        COMMAND ${CMAKE_COMMAND}
        ARGS -E copy ${file_i} "C:/TargetDirectory"
    )
    endforeach( file_i )
    
    0 讨论(0)
  • 2020-12-17 10:13

    Since I had more or less exactly the same issue and didn't like the solutions above I eventually came up with this. It does more than just copy files, but I thought I would post the whole thing as it shows the flexibility of the the technique in conjunction with generator expressions that allow different files and directories depending on the build variant. I believe the COMMAND_EXPAND_LISTS is critical to the functionality here. This function not only copies some files to a new directory but then runs a command on each of them. In this case it uses the microsoft signtool program to add digital signatures to each file.

    cmake_minimum_required (VERSION 3.12)
    
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
    
    SET(ALL_3RD_PARTY_DLLS_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/file1.dll" "${CMAKE_CURRENT_SOURCE_DIR}/file2.dll")
    SET(ALL_3RD_PARTY_DLLS_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/file3.dll" "${CMAKE_CURRENT_SOURCE_DIR}/file4.dll")
    
    STRING(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" ";${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ALL_OUTPUT_3RD_PARTY_DLLS_DEBUG ${ALL_3RD_PARTY_DLLS_DEBUG})
    LIST(REMOVE_AT ALL_OUTPUT_3RD_PARTY_DLLS_DEBUG 0)
    STRING(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" ";${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ALL_OUTPUT_3RD_PARTY_DLLS_RELEASE ${ALL_3RD_PARTY_DLLS_RELEASE})
    LIST(REMOVE_AT ALL_OUTPUT_3RD_PARTY_DLLS_RELEASE 0)
    
    FILE(TO_NATIVE_PATH "C:\\Program\ Files\ (x86)\\Windows\ Kits\\10\\bin\\10.0.17763.0\\x86\\signtool.exe" SIGNTOOL_COMMAND)
    
    add_custom_target(Copy3rdPartyDLLs ALL
                    COMMENT "Copying and signing 3rd Party DLLs"
                    VERBATIM
                    COMMAND_EXPAND_LISTS
                    COMMAND ${CMAKE_COMMAND} -E
                        make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/"
                    COMMAND ${CMAKE_COMMAND} -E
                        copy_if_different 
                                "$<$<CONFIG:Release>:${ALL_3RD_PARTY_DLLS_RELEASE}>" 
                                "$<$<CONFIG:Debug>:${ALL_3RD_PARTY_DLLS_DEBUG}>"
                                "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/"
                    COMMAND ${SIGNTOOL_COMMAND} sign 
                                "$<$<CONFIG:Release>:${ALL_OUTPUT_3RD_PARTY_DLLS_RELEASE}>" 
                                "$<$<CONFIG:Debug>:${ALL_OUTPUT_3RD_PARTY_DLLS_DEBUG}>"
    )
    

    I hope this saves someone the day or so it took me to figure this out.

    0 讨论(0)
提交回复
热议问题