Подтвердить что ты не робот

Как я могу установить иерархию файлов с помощью 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()

... но это раздражает. Конечно, есть более простой способ?

(Я не вижу ничего в документации по установке, хотя...)

4b9b3361

Ответ 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/...., а это не то, что вам нужно.

Есть два способа сделать это:

  1. Используйте INSTALL( FILES .... DESTINATION usr/myproject) для установки файлов, которые лежат непосредственно в install/, затем используйте INSTALL( DIRECTORY .... DESTINATION usr/myproject) и вручную перечислите каталоги для установки.

  2. Используйте команду 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()

Готово. ;-)