Я хочу скопировать определенные файлы в папку, а затем перезаписать некоторые из них. Но похоже file(COPY ..)
не перезаписывает существующие файлы.
Вот что я пытаюсь сделать:
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/common/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tmp/ FILES_MATCHING PATTERN "*.xml")
if (MY_OPTION)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/custom/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tmp/ FILES_MATCHING PATTERN "*.xml")
Я могу поменять местами приведенные выше строки - сначала скопировать custom
, а затем common
, после чего копия common
не перезапишет существующую из custom
.
Это отлично работает, но немного запутано, и я ищу лучшее решение (с копированием/установкой, а не пользовательской командой).
Я не вижу возможности явно перезаписать...file(COPY_FILE ...)
это вариант, но я не хочу указывать каждый файл...
Обновлено: из комментария Цыварева - вероятно, это связано с одинаковыми временными метками для файлов. К сожалению, я застрял с одинаковыми временными метками.
Спасибо, да, я думаю, это проблема, но я застрял с одинаковыми временными метками.
Одним из вариантов может быть использование пользовательской команды, вызывающей ${CMAKE_COMMAND} -E copy ...
AFAIK, это безоговорочно скопирует файлы. Обновлено: просто прочитайте, что вас не интересует пользовательское командное решение. Я оставлю комментарий, но не стесняйтесь игнорировать :)
Как вы уже поняли, в file(COPY ...)
нет возможности форсировать операцию. Кроме того, он не будет перезаписывать файлы с теми же (или более новыми, я думаю) временными метками, см. CMake doc.
Более новый file(COPY_FILE ...)
, с другой стороны, перезапишет существующие файлы, если не вызывается с флагом ONLY_IF_DIFFERENT
. Чтобы избежать перечисления всех XML-файлов в CMakeLists.txt, мы можем зациклить их и позволить CMake перебирать все XML-файлы в цикле. Это не отличается от указания FILES_MATCHING PATTERN
.
Вот пример кода:
# Create target dir if it does not already exist
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/tmp)
# Existing line, copy everything from common
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/common/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tmp/ FILES_MATCHING PATTERN "*.xml")
# Glob all XML files in custom
file(GLOB xml_files custom/*.xml)
# Loop over all the XML files that were found
foreach(in_file IN LISTS xml_files)
# Get just the file name, w/o path
get_filename_component(out_file ${in_file} NAME)
# Do the actual copy
file(COPY_FILE ${in_file} ${CMAKE_BINARY_DIR}/tmp/${out_file})
endforeach()
Другой способ сделать это — просто поменять местами две строки и добавить комментарий о том, что CMake не будет перезаписывать существующие файлы. Вы уже написали это в своем вопросе, и я думаю, что это уже может быть самое элегантное решение.
Из документации команды
file(COPY)
: «При копировании сохраняются временные метки входного файла и оптимизируется файл, если он существует в месте назначения с такой же временной меткой». То есть копирование не выполняется, если конечный файл имеет ту же метку времени, что и исходный.