Как я могу установить иерархию файлов с помощью CMake?
Я создал список файлов, используя:
file(GLOB_RECURSE DEPLOY_FILES "${PROJECT_SOURCE_DIR}/install/*")
Я хочу установить все эти файлы в /usr/myproject/
, но я хочу сохранить дерево файлов в установленной папке:
install/junk
install/other/junk2
install/other/junk3
Если я использую:
install(FILES ${DEPLOY_FILES} DESTINATION "usr/myproject")
Все файлы попадают в /usr/myproject как:
/usr/myproject/junk
/usr/myproject/junk2
/usr/myproject/junk3
Как сделать так, чтобы команда установки отслеживала относительные пути?
Я обошел проблему, выполнив ее вручную в цикле for
:
set(BASE "${PROJECT_SOURCE_DIR}/install")
foreach(ITEM ${DEPLOY_FILES})
get_filename_component(ITEM_PATH ${ITEM} PATH)
string(REPLACE ${BASE} "" ITEM_PATH ${ITEM_PATH})
install(FILES ${ITEM} DESTINATION "usr/myproject${ITEM_PATH}")
endforeach()
... но это раздражает. Конечно, есть более простой способ?
(Я не вижу ничего в документации по установке, хотя...)
Ответы
Ответ 1
Использование:
INSTALL( DIRECTORY <directory> DESTINATION usr/myproject )
(подробности см. здесь: http://www.cmake.org/cmake/help/v2.8.8/cmake.html#command:install)
INSTALL( DIRECTORY ... )
сохраняет структуру каталогов. Но если вы используете install
в качестве <directory>
, вы получите usr/myproject/install/....
, а это не то, что вам нужно.
Есть два способа сделать это:
Используйте INSTALL( FILES .... DESTINATION usr/myproject)
для установки файлов, которые лежат непосредственно в install/
, затем используйте INSTALL( DIRECTORY .... DESTINATION usr/myproject
) и вручную перечислите каталоги для установки.
Используйте команду globbing в исходном сообщении, а затем определите, какие записи являются файлами, которые являются каталогами, переместите записи каталога в отдельный список, передайте списки в INSTALL( FILES ...)
и INSTALL( DIRECTORY ...)
соответственно.
file(GLOB DEPLOY_FILES_AND_DIRS "${PROJECT_SOURCE_DIR}/install/*")
foreach(ITEM ${DEPLOY_FILES_AND_DIRS})
IF( IS_DIRECTORY "${ITEM}" )
LIST( APPEND DIRS_TO_DEPLOY "${ITEM}" )
ELSE()
LIST( APPEND FILES_TO_DEPLOY "${ITEM}" )
ENDIF()
endforeach()
INSTALL( FILES ${FILES_TO_DEPLOY} DESTINATION usr/myproject )
INSTALL( DIRECTORY ${DIRS_TO_DEPLOY} DESTINATION usr/myproject )
Примечание. В зависимости от типа устанавливаемых файлов другие команды INSTALL( ...)
могут быть более подходящими (например, INSTALL( TARGETS .... )
для установки ваших библиотек/исполняемых файлов).
Ответ 2
Самый простой способ установить все из заданного каталога:
install(DIRECTORY mydir/ DESTINATION dir/newname)
Трейлинг '/' имеет значение.
Без этого mydir
будет установлен на newname/mydir
.
Из документации CMake:
Последний компонент каждого имени каталога добавляется к месту назначения каталог, но косая черта может быть использована, чтобы избежать этого, потому что это оставляет последний компонент пустым.
Ответ 3
Я предполагаю, что у вас есть список файлов, скажем, INCLUDE_FILES
. Возможно выбор файлов, распределенных по нескольким подкаталогам, например, файлы заголовков по всему исходному дереву, в отличие от всего в одном подкаталоге, как в других ответах.
Вы можете перебрать список файлов и использовать get_filename_component()
для извлечения части каталога, а затем использовать это в последующем install()
для установки подкаталога DESTINATION
:
foreach ( file ${INCLUDE_FILES} )
get_filename_component( dir ${file} DIRECTORY )
install( FILES ${file} DESTINATION include/${dir} )
endforeach()
Готово. ;-)