Как настроить проект с КОМПОНЕНТАМИ в cmake - PullRequest
0 голосов
/ 15 февраля 2019

Я хочу создать проект проектов с использованием cmake, который доступен аналогично тому, который используется в Poco.Я считаю, что использование Poco в качестве примера переполнено и ему трудно следовать, поэтому я пытаюсь создать минимальную версию без макросов, чтобы я мог видеть, что происходит.Я создал репозиторий для этого примера здесь.

https://github.com/markeastwood82/nomnoms

Это, и то, что написано ниже, в настоящее время является моим лучшим предположением о том, как решить эту проблему после нескольких дней чтения /борется с "современным CMake", за исключением того, что он не совсем работает.По сути, у меня есть библиотека noms с компонентами fruit и veg, которую я хочу динамически связать из приложения munch.Я могу установить библиотеку noms, но не могу найти ее с помощью munch.Может кто-нибудь помочь мне собрать эту штуку?

Два проекта структурированы следующим образом:

noms
|---- CMakeLists.txt
+---- fruit
|     |---- CMakeLists.txt
|     |---- fruit-config.cmake.in
|     +---- src
|     |     |----apple.cpp
|     |
|     +---- include/noms/fruit
|           |----apple.h
|
+---- veg
      |---- CMakeLists.txt
      |---- veg-config.cmake.in
      +---- src
      |     |---- asparagus.cpp
      |
      +---- include/noms/veg
            |---- asparagus.h
munch
|---- CmakeLists.txt
+---- src
      |---- main.cpp

Файл noms/CMakeLists.txt содержит следующее.

cmake_minimum_required(VERSION 3.0)
set(project noms)
set(version 1.0.0)

project(${project})

add_subdirectory(fruit)
add_subdirectory(veg)

# UPDATE: implement advice from Tsyvarev

configure_file(${project}-config.cmake
  "${CMAKE_BINARY_DIR}/${project}-config.cmake"
  @ONLY
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  "${CMAKE_BINARY_DIR}/${project}-config-version.cmake"
  VERSION ${version}
  COMPATIBILITY AnyNewerVersion
)

install(
  FILES
    "${CMAKE_BINARY_DIR}/${project}-config.cmake"
  DESTINATION lib/cmake/${project}
)

Файл noms/fruit/CMakeLists.txt (и почти идентичный для noms/veg/CMakeLists.txt) равен

set(component fruit)

add_library(${component} SHARED src/apple.cpp)

# namespaced alias
add_library(${project}::${component} ALIAS ${component})

target_include_directories(${component}
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)

install(TARGETS ${component} EXPORT ${component}-targets
  COMPONENT ${component}
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES DESTINATION include
)

install(EXPORT ${component}-targets
  FILE "${project}-${component}-targets.cmake"
  NAMESPACE ${project}::
  DESTINATION lib/cmake/${project}
  COMPONENT ${component}
)

# This seems like a kludge, but it does place the file in the correct location
# on my machine (Ubuntu 18.04). Idea taken from Poco
configure_file("${component}-config.cmake.in"
  "${CMAKE_BINARY_DIR}/${project}-${component}-config.cmake"
  @ONLY
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  "${CMAKE_BINARY_DIR}/${project}-${component}-config-version.cmake"
  VERSION ${version}
  COMPATIBILITY AnyNewerVersion
)

install(
  FILES
    "${CMAKE_BINARY_DIR}/${project}-${component}-config.cmake"
    "${CMAKE_BINARY_DIR}/${project}-${component}-config-version.cmake"
  DESTINATION lib/cmake/${project}
  COMPONENT ${component}
)

# DESTINATION will be automatically prefixed by ${CMAKE_INSTALL_PREFIX}
install(
  DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include
  COMPONENT ${component}
  DESTINATION ${CMAKE_INSTALL_PREFIX}
)

Наконец, файл для noms/fruit/fruit-config.cmake.in (и почти идентичный для noms/veg/veg-config.cmake) равен

include(${CMAKE_CURRENT_LIST_DIR}/noms-fruit-config-version.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/noms-fruit-config-targets.cmake)

Для проекта munch файл munch/CMakeLists.txt просто

cmake_minimum_required(VERSION 3.0)
set(project munch)

find_package(noms REQUIRED COMPONENTS fruit)

add_executable(${project} src/main.cpp)

target_include_directories(${project}
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:$include>
)

target_link_libraries(${project}
  PUBLIC
    noms::fruit
)

После установки noms я пытаюсь собрать munch, однако cmake не может найти noms-config.cmake файл.Я не знаю, что это должно содержать, и где я должен действительно поместить это.Я также не уверен, что метод использования configure_file в noms/<food-type>/CMakeLists.txt является подходящим, учитывая, что это не требуется в приведенном здесь примере

https://github.com/boostcon/cppnow_presentations_2017/blob/master/05-19-2017_friday/effective_cmake__daniel_pfeifer__cppnow_05-19-2017.pdf

Мой вопроспо сути то же самое, что и здесь, который в настоящее время остается без ответа (принятый ответ неверен, как я прокомментировал в этой теме).На самом деле, чтобы быть справедливым, так как этому потоку 6 лет, он мог быть правильным на момент написания, но, похоже, не использует метод xxx-config.cmake, который сейчас рекомендуется.

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

Пожалуйста, не стесняйтесь сообщать мне обо всех моих ошибках или о том, что можно сделать лучше.Спасибо

* ОБНОВЛЕНИЕ *

В дополнение к обновленному файлу noms/CMakeLists.txt, приведенному выше, я реализовал следующий файл noms/noms-config.cmake согласно совету @Tsyvarev ниже...

foreach(component ${noms_FIND_COMPONENTS})
    include(${CMAKE_CURRENT_LIST_DIR}/noms-${component}-config.cmake)
endforeach()

Полученный код теперь работает, спасибо!


1 Ответ

0 голосов
/ 15 февраля 2019

CMake не обрабатывает список COMPONENTS автоматически.Он оставляет эту миссию для скрипта noms-config.cmake, который ищется и выполняется, когда кто-то запускает команду

find_package(noms COMPONENTS fruit veg)

Из документации find_package :

ВРежим конфигурации find_package автоматически обрабатывает опции REQUIRED, QUIET и [version], но оставляет его в файле конфигурации пакета для обработки компонентов способом, который имеет смысл для пакета.

Внутри этого файла конфигурации вы можете извлечь список запрошенных компонентов (заданных с помощью опции COMPONENTS для find_package()) из переменной noms_FIND_COMPONENTS и выполнить соответствующие действия.Например:

noms-config.cmake :

foreach(component ${noms_FIND_COMPONENTS})
  # For requested component, execute its "config" script
  include(${CMAKE_CURRENT_LIST_DIR}/${component}-config.cmake)
endforeach()

Это означает, что вы установите скрипт подкаталога noms-config.cmake в lib/cmake/noms, рядом сдругие .cmake скрипты, которые вы уже установили в своем проекте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...