Создать цель CMake, которая копирует файлы / каталоги, но исключает некоторые элементы - PullRequest
0 голосов
/ 21 апреля 2020

Я пытаюсь сгенерировать цель CMake для проекта C ++, используя add_custom_target, который копирует содержимое каталога, в котором находится CMakeLists.txt, в ${CMAKE_BINARY_DIR}, , но исключает данный список файлов .

Хотя это выглядит довольно простой задачей, здесь я сталкиваюсь с проблемами. Мои попытки пока:

1) Создайте список всех файлов / каталогов, удалите элементы, которые нужно исключить, и используйте команду копирования CMake:

file(GLOB files_to_copy LIST_DIRECTORIES TRUE *)
list(REMOVE_ITEM files_to_copy
  ${CMAKE_CURRENT_SOURCE_DIR}/file_to_exclude.txt
  ${CMAKE_CURRENT_SOURCE_DIR}/dir_to_exclude
  # ...
)
add_custom_target(my-target
  COMMAND ${CMAKE_COMMAND} -E copy ${files_to_copy} ${CMAKE_BINARY_DIR}
)

Проблемы:

  • Удаление элементов таким способом работает на уровне сравнения строк, что может привести к проблемам при использовании символьных c ссылок, например
  • copy инструмент командной строки , очевидно, поддерживает копирование каталогов, однако на моем компьютере это не работает, поэтому каталоги не не копируются.

2) Используйте команду file для копирования файлов, за исключением некоторых файлов

file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/" DESTINATION ${CMAKE_BINARY_DIR}
  PATTERN "file_to_exclude.txt" EXCLUDE
  PATTERN "dir_to_exclude" EXCLUDE
)

Проблемы:

  • Это именно то, что я хочу, за исключением того, что команда не связана с цель и, следовательно, всегда выполняется. Но мне нужна только операция копирования, чтобы быть целью.

Есть ли возможность привязать команду file(COPY ...) к цели? Или любое другое простое решение для достижения того, чего я хочу?

Обратите внимание, что я хочу использовать только встроенные инструменты CMake, а не выполнять какие-либо специфичные для ОС команды c shell (работающие в кроссплатформенном проекте). ).

1 Ответ

0 голосов
/ 21 апреля 2020

CMake команды сценариев работают только в CMake контексте и выполняются немедленно .

Но COMMAND в add_custom_command ( или add_custom_target) выполняется в контексте инструмента сборки (например, Makefile), а не в контексте CMake.

Однако вы можете поместить команды сценариев CMake в отдельный CMake скрипт , и назовите этот скрипт из COMMAND. Это решение имеет те же независимые от платформы свойства, что и сам CMakeLists.txt.

Вы можете параметризовать отдельный скрипт либо:

  1. С помощью configure_file команды CMake.
  2. Передав -D параметров в CMake при вызове скрипта.

Первый подход довольно прост: вы пишете скрипт так же, как вы пишете CMakeLists.txt. Но он генерирует дополнительные файлы для каждого набора параметризации.

Второй подход полезен для многоцелевых (или многоразовых) сценариев, поскольку он не создает дополнительную копию сценария для каждого использования. Но это требует некоторого проектирования параметров.

Использование 'configure_file'

copy_sources.cmake.in (как если бы команды были написаны в CMakeLists.txt):

file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/" DESTINATION ${CMAKE_BINARY_DIR}
  PATTERN "file_to_exclude.txt" EXCLUDE
  PATTERN "dir_to_exclude" EXCLUDE

)

CMakeLists.txt :

# Instantiate the parameterized script in the binary directory.
configure_file(copy_sources.cmake.in copy_sources.cmake)

add_custom_target(my-target
  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/copy_sources.cmake

)

Использование параметров -D

copy_sources.cmake :

# Expect the script to be called from the source directory.
# This saves one parameter.
# 
# DEST_DIR denotes the directory for copy to.
file(COPY "${CMAKE_SOURCE_DIR}/" DESTINATION ${DEST_DIR}
  PATTERN "file_to_exclude.txt" EXCLUDE
  PATTERN "dir_to_exclude" EXCLUDE
)

CMakeLists.txt :

add_custom_target(my-target
  COMMAND ${CMAKE_COMMAND}
    -DDEST_DIR=${CMAKE_BINARY_DIR} # all '-D' options should preceed '-P' one
    -P ${CMAKE_CURRENT_SOURCE_DIR}/copy_sources.cmake
  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} # The script assumes proper current directory

)

...