Подтвердить что ты не робот

CMake Custom Command копирует несколько файлов

Я пытаюсь скопировать несколько файлов в формате ${CMAKE_COMMAND} -E copy <from> <to>, но мне было интересно, есть ли способ предоставить несколько файлов для копирования в конкретный каталог. Кажется, что копия cmake позволяет копировать только один файл за раз. Я действительно не хочу использовать команду копирования повторно, когда я предпочел бы предоставить список файлов для копирования в качестве первого аргумента.

Я думаю, что самым простым решением является использование зависимой от платформы команды "cp". Хотя это определенно плохо для переносимости, наша система, как гарантируется, будет построена на Linux. Простое, независимое от платформы решение было бы лучше.

4b9b3361

Ответ 2

Я сделал это с петлей

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

Ответ 3

Относительно простым обходным путем было бы использовать ${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)

Ответ 4

Поскольку у меня была более или менее точно такая же проблема, и мне не нравились решения, описанные выше, я в конце концов придумал это. Он делает больше, чем просто копирует файлы, но я подумал, что я опубликую все это, поскольку он показывает гибкость техники в сочетании с выражениями генератора, которые допускают различные файлы и каталоги в зависимости от варианта сборки. Я считаю, что COMMAND_EXPAND_LISTS имеет решающее значение для функциональности здесь

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

Я надеюсь, что это спасет кого-то день или около того, мне понадобилось, чтобы понять это.