Как писать модули cmake для «многоуровневой» многокомпонентной библиотеки? - PullRequest
3 голосов
/ 29 апреля 2019

В настоящее время я пишу библиотеку c ++, которая имеет несколько «подбиблиотек», как, например, библиотека boost.

Давайте назовем библиотеку «TestLib» и подбиблиотеки «Base» и «Ext», где Base содержит базовый материал, который не зависит ни от какой другой суббиблиотеки. Ext, однако, зависит от некоторых классов Base.

Каждая «подбиблиотека» должна компилироваться в отдельный файл .a или .so, но все они должны совместно использовать пространство имен (TestLib). Теперь я стремлюсь написать чистые скрипты cmake для достижения этой цели.

В конце я хочу сделать что-то подобное в cmake:

find_package(TestLib 0.1 REQUIRED COMPONENTS Base Ext)

или

target_link_libraries(someapplication
PUBLIC
    TestLib::Base
)

Я поместил каждую «суббиблиотеку» в отдельный репозиторий git и добавил их как субмодули в новый репозиторий, в котором есть только CMakeLists.txt. это просто вызывает add_subdirectory на каждом из репозиториев.

Большую часть вещей, которые я достиг, я получил из этого удивительного урока в https://pabloariasal.github.io/

А базовая часть работает так, как задумано (что неудивительно, поскольку больше ничего не зависит).

Но мои проблемы связаны с Ext частью. Для того, чтобы это скомпилировалось, мне нужно соединиться с базовой библиотекой, которая не должна быть слишком сложной, и с некоторыми пробами и ошибками я уверен, что заставлю ее работать.

Но я хочу сделать это правильно.

Мой подход был к

find_package(TestLib COMPONENTS Base)

в CMakeLists.txt из TestLib.Ext. Но это не может быть найдено, так как у него нет TestLibConfig.cmake.

Это имеет смысл, но я не знаю, что поместить в этот файл.

Я попытался предоставить некоторый код, который точно описывает мою проблему, но, так как это было бы слишком много для публикации здесь, я создал github для этой цели:

https://github.com/PowerSupplyTopologies/TestLib

Он должен содержать весь соответствующий код.

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

Заранее спасибо за любые ваши мысли.

EDIT:

Создание библиотеки в CMakeLists.txt из Base:

set(TARGET_NAME testlibbase)

add_library(${TARGET_NAME}
    src/ClassA.cpp
    src/ClassB.cpp
)

#Add an alias so that library can be used inside the build tree, e.g.     when testing
add_library(TestLib::${TARGET_NAME} ALIAS ${TARGET_NAME})

и

set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/TestLib)

install(TARGETS ${TARGET_NAME}
    EXPORT ${TARGET_NAME}-targets
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

#This is required so that the exported target has the name JSONUtils and not  jsonutils
set_target_properties(${TARGET_NAME} PROPERTIES EXPORT_NAME Base)

install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

#Export the targets to a script
install(EXPORT ${TARGET_NAME}-targets
  FILE
    TestLibBaseTargets.cmake
  NAMESPACE
    TestLib::
  DESTINATION
    ${INSTALL_CONFIGDIR}
)

#Create a ConfigVersion.cmake file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
    ${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseConfigVersion.cmake
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY AnyNewerVersion
)

configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/cmake  /TestLibBaseConfig.cmake.in
    ${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseConfig.cmake
    INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
)

#Install the config, configversion and custom find modules
install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseConfig.cmake
    ${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseConfigVersion.cmake
    DESTINATION ${INSTALL_CONFIGDIR}
)

##############################################
## Exporting from the build tree

export(EXPORT ${TARGET_NAME}-targets FILE ${CMAKE_CURRENT_BINARY_DIR}/TestLibBaseTargets.cmake NAMESPACE TestLib::)

и Ext:

set(TARGET_NAME testlibext)

add_library(${TARGET_NAME}
    src/ClassC.cpp
)

#Add an alias so that library can be used inside the build tree, e.g. when   testing
add_library(TestLib::${TARGET_NAME} ALIAS ${TARGET_NAME})

1 Ответ

0 голосов
/ 30 апреля 2019

В вашем метапроекте TestLib вы можете создать файл TestLibConfig.cmake, как описано в документации CMake.

TestLibConfig.cmake * * 1004

set(_supported_components Base Ext)

foreach(_comp ${Test_FIND_COMPONENTS})
  if (NOT ";${_supported_components};" MATCHES _comp)
    set(TestLib_FOUND False)
    set(TestLib_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}")
  endif()
  include("${CMAKE_CURRENT_LIST_DIR}/TestLib${_comp}Targets.cmake")
endforeach()

ref: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#creating-a-package-configuration-file

...