Copy all files with given extension to output directory using CMake

后端 未结 3 729
长情又很酷
长情又很酷 2020-12-24 11:26

I\'ve seen that I can use this command in order to copy a directory using cmake:

file(COPY \"myDir\" DESTINATION \"myDestination\")

(from t

相关标签:
3条回答
  • 2020-12-24 12:00

    this also works for me:

    install(DIRECTORY "myDir/" 
            DESTINATION "myDestination" 
            FILES_MATCHING PATTERN "*.h" )
    
    0 讨论(0)
  • 2020-12-24 12:02

    The alternative approach provided by jepessen does not take into account the fact that sometimes the number of files to be copied is too high. I encountered the issue when doing such thing (more than 110 files)

    Due to a limitation on Windows on the number of characters (2047 or 8191) in a single command line, this approach may randomly fail depending on the number of headers that are in the folder. More info here https://support.microsoft.com/en-gb/help/830473/command-prompt-cmd-exe-command-line-string-limitation

    Here is my solution:

    file(GLOB MY_HEADERS myDir/*.h)
    foreach(CurrentHeaderFile IN LISTS MY_HEADERS)
        add_custom_command(
                    TARGET MyTarget PRE_BUILD
                    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CurrentHeaderFile} ${myDestination}
                    COMMENT "Copying header: ${CurrentHeaderFile}")
    endforeach()
    

    This works like a charm on MacOS. However, if you have another target that depends on MyTarget and needs to use these headers, you may have some compile errors due to not found includes on Windows. Therefore you may want to prefer the following option that defines an intermediate target.

    function (CopyFile ORIGINAL_TARGET FILE_PATH COPY_OUTPUT_DIRECTORY)
        # Copy to the disk at build time so that when the header file changes, it is detected by the build system.
        set(input ${FILE_PATH})
        get_filename_component(file_name ${FILE_PATH} NAME)
        set(output ${COPY_OUTPUT_DIRECTORY}/${file_name})
        set(copyTarget ${ORIGINAL_TARGET}-${file_name})
    
        add_custom_target(${copyTarget} DEPENDS ${output})
        add_dependencies(${ORIGINAL_TARGET} ${copyTarget})
        add_custom_command(
                DEPENDS ${input}
                OUTPUT ${output}
                COMMAND ${CMAKE_COMMAND} -E copy_if_different ${input} ${output}
                COMMENT "Copying file to ${output}."
        )
    endfunction ()
    
    foreach(HeaderFile IN LISTS MY_HEADERS)
        CopyFile(MyTarget ${HeaderFile} ${myDestination})
    endforeach()
    

    The downside indeed is that you end up with multiple target (one per copied file) but they should all end up together (alphabetically) since they start with the same prefix ORIGINAL_TARGET -> "MyTarget"

    0 讨论(0)
  • 2020-12-24 12:23

    I've found the solution by myself:

    file(GLOB MY_PUBLIC_HEADERS
      "myDir/*.h"
    )
    file(COPY ${MY_PUBLIC_HEADERS} DESTINATION myDestination)
    
    0 讨论(0)
提交回复
热议问题