簡體   English   中英

CMake Custom Command復制多個文件

[英]CMake Custom Command copy multiple files

我試圖使用${CMAKE_COMMAND} -E copy <from> <to>格式復制多個文件,但我想知道是否有辦法提供一些文件復制到特定目錄。 似乎cmake副本只允許一次復制一個文件。 當我寧願提供要復制的文件列表作為第一個參數時,我真的不想重復使用復制命令。

我認為最簡單的解決方案是使用平台相關的“cp”命令。 雖然這對於便攜性肯定不好,但我們的系統保證在Linux上構建。 一個簡單的,獨立於平台的解決方案會更好。

我做了一個循環

# 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 )

可以從CMake 3.5獲得復制多個文件

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

“cmake -E copy”支持多個文件

命令行工具模式

一個相對簡單的解決方法是使用${CMAKE_COMMAND} -E tar捆綁源,移動tarball並將其解壓縮到目標目錄中。

如果您的源分散在許多不同的目錄中,這可能比它的價值更麻煩,因為提取將保留原始目錄結構(與使用cp不同)。 但是,如果所有文件都在一個目錄中,則只需2次add_custom_command調用即可實現復制。

假設您要移動的源都在${CMAKE_SOURCE_DIR}/source_dir ,目標是${CMAKE_SOURCE_DIR}/destination_dir ,您的文件名列表(不是完整路徑)在${FileList} 你可以這樣做:

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)

由於我或多或少完全相同的問題,並且不喜歡上面的解決方案,我最終想出了這個。 它不僅僅是復制文件,但我想我會發布整個事情,因為它顯示了該技術的靈活性,結合生成器表達式,允許不同的文件和目錄,具體取決於構建變體。 我相信COMMAND_EXPAND_LISTS對這里的功能至關重要。 此函數不僅將某些文件復制到新目錄,而且還在每個文件上運行命令。 在這種情況下,它使用microsoft signtool程序為每個文件添加數字簽名。

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}>"
)

我希望這一天可以拯救某人,這讓我想出了這個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM