首页 > 解决方案 > CMake:如何构建通过 add_subdirectory() 为 find_package() 导出的多个项目

问题描述

我有一个导出的库项目,因此消费者可以像这样使用它:

find_package(myLibrary)
target_link_libraries(theirLibrary PUBLIC myNamespace::myLibrary)

MyLibrary 是主要产品,但它与我们存储库中的其他两个项目一起存在,布局如下所示:

MyRepository/
  MyLibrary/
    CMakeLists.txt
    include/ //public headers
    MyLibrary/ //sources and private headers
  MyDependentLibrary/ //another library project
    CMakeLists.txt
    etc..
  MyExample //executable project
    CMakeLists.txt
    etc..
    

每个项目的依赖关系如下:

MyLibrary: None
MyDependentLibrary: MyLibrary
MyExample: MyLibrary, MyDependentLibrary

MyLibrary 和 MyDependentLibrary 都设置了安装和构建目录导出以与 find_package() 命令兼容。所以要构建你的一切:

  1. 配置/构建 MyLibrary
  2. 提示时配置 MyDependantLibrary 设置MyLibrary_DIR,然后构建它
  3. 配置 MyExample 设置MyLibrary_DIR,并MyDependentLibrary_DIR在出现提示时构建它

这个工作流程很棒,大多数时候我们只想在发送给客户时打包 MyLibrary 而没有其他项目,但偶尔我们想给他们所有 3 个项目的源代码,以便他们有更多示例可供查看。

出于这个原因,我很想添加一个顶级CMakeLists.txt文件,我认为它看起来像这样:

   cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
    
   project(MyCombinedProject VERSION 1.0.0 LANGUAGES CXX)
    
   add_subdirectory(MyLibrary)
   add_subdirectory(MyDependentLibrary)
   add_subdirectory(MyExample)

但是,这不起作用。配置“组合”项目时,MyDependentLibrary 无法找到MyLibrary_DIR,这是有道理的,因为尚未构建 MyLibrary。

除了 find_package() 之外,有没有办法向每个库添加导出,以便在以这种方式添加时可以找到它们?我真的不想将构建 MyLibrary 所需的任何 CMake 代码移动到顶层CMakeLists.txt,因为 90% 的时间它将自行交付。

标签: cmake

解决方案


您可以使用伪配置文件发送库 (MyLibrary) 的源代码,该文件仅提供myNamespace::myLibrarytarget 作为myLibrary.

我的图书馆/CMakeLists.txt

# Assuming you create a library
add_library(mylibrary ...)
# Install and export it
install(TARGETS mylibrary EXPORT mylibraryTargets ...)
# and install the file which describes this installation
install(EXPORT mylibraryTargets NAMESPACE myNamespace ...)
# Then you install config file for your library:
install(FILES myLibrary.cmake ...)

# Then just set `MyLibrary_DIR` variable to point into in-source version of config file.
set(MyLibrary_DIR CACHE INTERNAL "A directory with the in-source config file"
    ${CMAKE_CURRENT_SOURCE_DIR}/cmake
)

并按如下方式编写该源配置文件:

MyLibrary/cmake/MyLibraryConfig.cmake

add_library(myNamespace::mylibrary ALIAS mylibrary)

这样,find_package(MyLibrary)如果在配置库的源 ( ) 之后发布它,它将起作用add_subdirectory(MyLibrary)


推荐阅读