Ответ 1
Копирование нескольких файлов доступно из CMake 3.5
cmake -E copy <file>... <destination>
Я пытаюсь скопировать несколько файлов в формате ${CMAKE_COMMAND} -E copy <from> <to>
, но мне было интересно, есть ли способ предоставить несколько файлов для копирования в конкретный каталог. Кажется, что копия cmake позволяет копировать только один файл за раз. Я действительно не хочу использовать команду копирования повторно, когда я предпочел бы предоставить список файлов для копирования в качестве первого аргумента.
Я думаю, что самым простым решением является использование зависимой от платформы команды "cp". Хотя это определенно плохо для переносимости, наша система, как гарантируется, будет построена на Linux. Простое, независимое от платформы решение было бы лучше.
Копирование нескольких файлов доступно из CMake 3.5
cmake -E copy <file>... <destination>
Я сделал это с петлей
# 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_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 имеет решающее значение для функциональности здесь
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}>"
)
Я надеюсь, что это спасет кого-то день или около того, мне понадобилось, чтобы понять это.