#cmake
#cmake
Вопрос:
У меня следующий макет проекта:
project/
├─ CMakeLists.txt
├─ main.cpp
╘═ my_lib/
├─ CMakeLists.txt
╞═ some_package1/
│ ├── header.hpp
│ └── impl.cpp
╘═ some_package2/
├── header.hpp
└── impl.cpp
my_lib
добавляется как подкаталог с помощью CMakeLists.txt
from project
.
Что я хотел бы иметь, так это цель, в my_lib
CMakeLists.txt
которой при сборке выполняется команда, которая копирует все заголовки в my_lib
каталог назначения, сохраняя при этом структуру каталогов. Целевой каталог будет определен project
CMakeLists.txt
.
В принципе, если бы я мог как-то add_custom_command
это сделать:
file(COPY ${CMAKE_SOURCE_DIR}/my_lib DESTINATION ${COPY_DEST_DIR} FILES_MATCHING PATTERN "*.hpp")
Я был бы очень рад. Но я не нашел способа сделать это. Это очень похоже на цель установки, за исключением того, что мне нужно это сделать до того, как что-либо будет скомпилировано.
Я попытался выполнить следующее:
set(MY_LIB_HEADER_FILES
some_package1/header.hpp
some_package2/header.hpp
)
add_custom_target(copy_headers)
add_custom_command(
TARGET copy_headers
COMMAND ${CMAKE_COMMAND} -E copy "${MY_LIB_HEADER_FILES}" ${COPY_DEST_DIR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/my_lib
)
Но это не сохраняет структуру каталогов, что только в этом примере приведет к перезаписи одного заголовка другим. Я не смог найти обходной путь для этого.
Единственное решение, которое я могу себе представить, — это хак, в котором я перебираю каждый файл ${MY_LIB_HEADER_FILES}
, удаляю все, что следует за последней косой чертой, создаю этот каталог, а затем копирую в него файл. Но на самом деле это не то, к чему я хочу прибегнуть и подумать об этом, я даже не уверен, как бы я это сделал, учитывая, что это должно быть сделано в add_custom_command
вызове.
Конечно, есть решение, верно?
Комментарии:
1. Вы пробовали
${CMAKE_COMMAND} -E copy_directories
вместоcopy
?2. В конечном итоге я бы скопировал исходные файлы вместе с заголовками, поскольку
copy_directories
не предлагает возможности сопоставления файлов вообще. Однако, как было предложено в ответе, которого, по-видимому, больше нет, я мог бы затем использоватьfile(GLOB_RECURSE)
для поиска исходных файлов в каталоге назначения и их удаления. Это далеко от идеала, но из-за отсутствия лучшего решения, вероятно, это то, что я в конечном итоге сделаю.3. Я надеюсь, что вы найдете хорошее решение. Но вы также можете рассмотреть возможность реорганизации своей структуры каталогов. Я считаю полезным иметь «внешние» заголовочные файлы (файлы, которые конечным пользователям необходимы для использования скомпилированного кода) в отдельном каталоге от исходных и внутренних заголовочных файлов. Это значительно упрощает использование чего-то вроде
copy_directories
их установки.4. @EricBackus это на самом деле то, чего я пытался достичь. Это может быть личным, но мне не нравится идея вручную сохранять отдельное местоположение для заголовков библиотеки (если я не неправильно понял, что вы имели в виду), поэтому я хочу, чтобы скрипт делал это автоматически. Однако к чему привела меня эта головоломка, так это к реорганизации всего моего кода, чтобы часть «копировать все, прежде чем что-либо будет скомпилировано» больше не требовалась. Несмотря на это, принятый ответ предоставляет хороший способ сделать это. 🙂
Ответ №1:
Один из способов добиться этого — написать файл «CMake script», который будет содержать вашу file(COPY ....)
команду, и выполнить ее внутри add_custom_command
. Вкратце, ваш фрагмент кода будет выглядеть следующим образом:
#create script file during configure phase...
file(WRITE ${CMAKE_BINARY_DIR}/cp.cmake
"file(COPY ${CMAKE_SOURCE_DIR}/my_lib DESTINATION ${COPY_DEST_DIR} FILES_MATCHING PATTERN *.hpp)n"
)
#execute the script during the build phase...
add_custom_command(
TARGET my_lib
POST_BUILD
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cp.cmake
)
file(WRITE ....
инструкция создаст новый файл сценария cmake в корневой папке сборки с именем cp.cmake
.
Примечание 1: $
Предыдущие переменные CMAKE_SOURCE_DIR
и COPY_DEST_DIR
не экранируются, что означает, что cp.cmake
они будут содержать их оцененные значения.
Примечание 2. Предполагается, что ваша библиотека создает цель с именем my_lib
и add_custom_command
добавляется как POST_BUILD
событие для этой цели.
В конце концов, вот документация cmake о add_custom_command, файловой команде и запуске CMake в режиме скрипта
Комментарии:
1. Это идеально. Спасибо, загружается. 👍