Copy all files with given extension to output dire

2020-05-18 06:48发布

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

file(COPY "myDir" DESTINATION "myDestination")

(from this post)

My problem is that I don't want to copy all of myDir, but only the .h files that are in there. I've tried with

file(COPY "myDir/*.h" DESTINATION "myDestination")

but I obtain the following error:

CMake Error at CMakeLists.txt:23 (file):
  file COPY cannot find
  "/full/path/to/myDIR/*.h".

How can I filter the files that I want to copy to a destination folder?

标签: copy cmake
3条回答
\"骚年 ilove
2楼-- · 2020-05-18 07:10

this also works for me:

install(DIRECTORY "myDir/" 
        DESTINATION "myDestination" 
        FILES_MATCHING PATTERN "*.h" )
查看更多
萌系小妹纸
3楼-- · 2020-05-18 07:13

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"

查看更多
乱世女痞
4楼-- · 2020-05-18 07:32

I've found the solution by myself:

file(GLOB MY_PUBLIC_HEADERS
  "myDir/*.h"
)
file(COPY ${MY_PUBLIC_HEADERS} DESTINATION myDestination)
查看更多
登录 后发表回答