如何为“ boost式”多组件库编写cmake模块?

时间:2019-04-29 14:18:37

标签: c++ cmake libraries git-submodules cmake-modules

我目前正在编写一个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。

我实现的大多数cmake东西,我都来自这个很棒的教程,网址为 https://pabloariasal.github.io/

并且基础部分按预期工作(这并不奇怪,因为它不依赖于其他任何东西)。

但是我的问题来自Ext部分。为了对此进行编译,我必须链接到Base库,这应该不难,并且通过反复试验,我确定我可以使它工作。

但是我想做正确的事。

我的方法是

find_package(TestLib COMPONENTS Base)
TestLib.Ext的CMakeLists.txt中的

。 但这找不到,因为它没有TestLibConfig.cmake。

这是有道理的,但我不知道该文件中要放什么。

我试图提供一些可以准确描述我的问题的代码,但是由于要在此处发布太多内容,因此我为此创建了一个github:

https://github.com/PowerSupplyTopologies/TestLib

其中应包含所有相关代码。

这对你们中的某些人来说可能是微不足道的,但是我敢打赌,会有更多的人可以从这种方法中受益。

预先感谢您的任何想法。

编辑:

在Base的CMakeLists.txt中创建的库是:

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::)

和外部:

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 :(得分:0)

在元项目TestLib中,您可以创建CMake文档中所述的TestLibConfig.cmake文件。

TestLibConfig.cmake

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