使用 add-subdirectory 访问外部项目导致 CMake Error related to export set

Accessing an external project with add-subdirectory results in CMake Error related to export set

我有一个依赖spdlog的项目A。这是结构:

|--- dir A
...|---src
......|---CMakeLists.txt
...|---include
...|---CMakeLists.txt
|---external/3rd_party/spdlog

我正在尝试通过添加子目录来访问项目 A 中的 spdlog。这是我的 A/CMakeLists.txt 的样子:

cmake_minimum_required(VERSION 3.9.3 FATAL_ERROR)
project(GLOBAL CXX)
add_subdirectory(../external/3rd_party/spdlog   ${CMAKE_BINARY_DIR}/spdlog  EXCLUDE_FROM_ALL)
add_subdirectory(src)

这是我的 A/src/CMakeLists.txt 的样子:

cmake_minimum_required(VERSION 3.9.3 FATAL_ERROR)
project(Alib CXX)

if(NOT TARGET spdlog)
   # Stand-alone build
   find_package(spdlog_header_only REQUIRED)
endif()
add_librray(A A.cpp)
target_link_libraries(A PUBLIC spdlog_header_only)

install(TARGETS A
   EXPORT ATargets
   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
   ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(EXPORT ATargets
    NAMESPACE A::
    FILE ATargets.cmake
    DESTINATION ${INSTALL_CONFIGDIR})

install(FILES AConfig.cmake DESTINATION ${INSTALL_CONFIGDIR})

当我尝试构建它时,出现以下错误:

CMake Error: install(EXPORT "ATargets" ...) includes target "A" which requires target "spdlog_header_only" that is not in the export set.

你能建议我如何解决吗?

出于某种原因,我需要保持与上面所示相同的目录结构。 这是一个相关问题,但没有答案:here

错误的含义

由于您在 link 您的库 (A) 中使用 spdlog_header_only 时使用 PUBLIC 关键字,CMake 预计此 linking 也需要用于您图书馆的 用户 。因此,当您为库创建配置文件时(使用 install(EXPORT)),CMake 也会将带有 spdlog_header_only 目标的 linking 添加到配置文件中。喜欢

# [ATargets.cmake]
target_link_libraries(A::A PUBLIC spdlog_header_only)

与目标链接意味着存在该目标,但您未安装 spdlog_header_only 目标。因此,为您的库创建的配置文件将不起作用。这是 CMake 在错误消息中告诉您的内容。

简单修复

最简单的修复方法是将 PRIVATE linking 与 spdlog_header_only 目标一起使用,这样 linking 就不会成为配置文件的一部分。请注意,在这种情况下,您(已安装)库的用户将无法访问 spdlog 的 header 文件。 (但用户可以通过其他方式获得这些 header。)

硬修复

但是,如果您希望图书馆的用户能够访问 spdlog header(或者更糟的是 public headers of your library use #include for headers from spdlog), then you cannot drop PUBLIC linking.在这种情况下,您还需要 install spdlog_header_only 目标。例如。通过启用 SPDLOG_INSTALL 选项

set(SPDLOG_INSTALL ON)

之前

add_subdirectory(../external/3rd_party/spdlog   ${CMAKE_BINARY_DIR}/spdlog  EXCLUDE_FROM_ALL)

(请注意,除了启用 SPDLOG_INSTALL 选项外,还需要进行其他几项调整才能使您的库的配置文件正常工作。)