Установка CMake (ЦЕЛИ в подкаталогах)

Рассмотрим следующий файл CMakeLists.txt:

add_subdirectory(execA)
add_subdirectory(libB)

install(TARGETS execA libB
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)

Я получаю следующую ошибку:

install TARGETS given target "execA" which does not exist in this
  directory

execA и libB имеют свои собственные файлы CMakeList.txt и находятся в каталоге project, а также в каталоге компоновки, с которым я работаю cmake (cmake ..):

project
  |------ CMakeList.txt (the one with the code)
  |----execA
  |      \- .cpp, .hpp and CMakelist.txt
  |----libB
  |      \- .cpp, .hpp and CMakelist.txt
  |---- lib
  |---- bin
  \---- build (where I´m commanding: $ cmake ..

Как мне исправить эту ошибку?

Ответ 1

Согласно этому отчету об ошибках, поток команд install(TARGETS) принимает только цели , созданные в одном каталоге.

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

Начиная с CMake 3.13 install(TARGETS) может работать даже с целями, созданными в других каталогах.

install(TARGETS) может устанавливать цели, созданные в других каталогах. При использовании таких правил установки между каталогами запуск make install (или аналогичного) из подкаталога не гарантирует актуальность целей из других каталогов.

Ответ 2

Это все еще кажется проблемой в CMake 3.11.

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

Вот мое решение:

  • Перед вызовом add_subdirectory в корневом файле CMakeLists.txt создайте свойство GLOBAL с именами целей, которые вы хотите включить в свой установщик.
  • Оберните функции создания цели (add_executable и т.д.) В свои собственные пользовательские функции. В этих функциях проверьте, присутствует ли цель в глобальном свойстве, и соответственно вызовите install.

Такой подход позволяет централизовать настройку установщика.

Также: для поддержки создания нескольких установщиков мы заполняем наш глобальный список вместе с другими свойствами установщика в отдельных файлах .cmake. Когда мы вызываем cmake, мы передаем имя файла конфигурации установщика CMake в качестве аргумента командной строки. Наш корневой файл CMakeLists.txt просто вызывает include с этим файлом.

Ответ 3

Несмотря на то, что это поможет увидеть файлы CMakeLists.txt содержащиеся в подкаталогах, я предполагаю, что они содержат add_executable и/или add_library для создания ваших вещей.
Кроме того, из-за вашего примера, я думаю, вы используете то же имя своих каталогов для своих целей.
Тем не менее, вы должны знать, что символы, определенные в файле CMakeLists.txt в подкаталоге, по умолчанию не отображаются в контексте файла CMakeLists.txt в родительском каталоге. Из-за этого вы должны перенести свои инструкции install в файлы CMakeLists.txt в свои подкаталоги.
Это должно решить проблему, если мои мысли были правильными. В противном случае я настоятельно рекомендую вам опубликовать в своем вопросе также содержимое других файлов, упомянутых выше.

Во всяком случае, ошибка довольно ясна.
Файл, содержащий инструкцию install для объекта с именем X, не содержит оператора создания цели (add_executable и других), который рождает эту цель, поэтому он продолжает утверждать, что эта цель не существует в этом каталоге.