cmake:常规 (SHARED) 库,依赖于仅标头 (INTERFACE) 库

cmake: regular (SHARED) library depending on a header-only (INTERFACE) library

提问人:playing4time 提问时间:10/8/2023 更新时间:10/9/2023 访问量:25

问:

包括仅标头依赖项的路径,这些依赖项不会传播到非仅标头库目标。

CMake 3.25.3,GCC 12.2.0。

  1. 我有一个仅标头的库,我们称之为:foo
# foo CMakeLists.txt
add_library(foo INTERFACE)

foo存在以提供一些 C++ 头文件

# foo CMakeLists.txt 

target_include_directories(foo INTERFACE
  $<INSTALL_INTERFACE:include>
  $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)

install(
  TARGETS foo
  EXPORT fooTargets
  LIBRARY DESTINATION lib COMPONENT Runtime
  ARCHIVE DESTINATION lib COMPONENT Development
  RUNTIME DESTINATION lib COMPONENT Runtime
  PUBLIC_HEADER DESTINATION include COMPONENT Development
  BUNDLE DESTINATION bin COMPONENT Runtime)
  1. foo生成+导出 .cmake 配置文件到驱动器find_package
# foo cmake/fooConfig.cmake.in
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/fooTargets.cmake")
check_required_components("@PROJECT_NAME@")

# foo CMakeLists.txt
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  "${PROJECT_BINARY_DIR}/fooConfigVersion.cmake"
  VERSION 1.0
  COMPATIBILITY AnyNewerVersion)
configure_package_config_file(
  "${PROJECT_SOURCE_DIR}/cmake/fooConfig.cmake.in"
  "${PROJECT_BINARY_DIR}/fooConfigVersion.cmake
  INSTALL_DESTINATION lib/cmake/foo)
install(
  EXPORT fooTargets
  DESTINATION lib/cmake/foo)
install(
  FILES
  "${PROJECT_BINARY_DIR}/fooConfigVersion.cmake"
  "${PROJECT_BINARY_DIR}/fooConfig.cmake"
  DESTINATION lib/cmake/foo)
  1. 我有一个共享库,我们称之为 .
    位于单独的代码库中
    barbar
# bar CMakeLists.txt
find_package(foo CONFIG REQUIRED)
add_library(bar SHARED bar.cpp)
target_include_directories(bar PUBLIC 
  $<INSTALL_INTERFACE:include>
  $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
  1. bar需要头文件来编译:foo
# bar CMakeLists.txt
target_link_libraries(bar INTERFACE foo)
  1. 问题编译不接收标头:bar.cppfoo
$ make VERBOSE=1 
g++ -Ipath/to/bar/include path/to/bar.cpp ...   # path/to/foo/include missing

这仅发生在 INTERFACE 依赖项上。 如果我将 foo 设置为 SHARED 目标 + 在 bar 中将其用作 PUBLIC 依赖项,那么 foo 标头 转发到编译器

  1. (丑陋)解决方法:当依赖于仅标头库时,请添加提示:
# bar CMakeLists.txt

get_target_property(tmp foo INTERFACE_INCLUDE_DIRECTORIES)
set_property(
  TARGET bar
  APPEND PROPERTY INCLUDE_DIRECTORIES ${tmp})

问题

有必要吗?我的仅标题包装有问题吗?
fooConfig.cmake.in 中缺少一些成分?

cmake 仅标头 查找包

评论

0赞 Tsyvarev 10/8/2023
target_link_libraries(bar INTERFACE foo)- 该行表示您不希望将 的属性附加到 .而是使用或链接。foobarPRIVATEPUBLIC
0赞 playing4time 10/8/2023
感谢您的回复!我试过了,但 cmake 似乎认为这不合适。CMake 3.25.3 给出以下错误:INTERFACE library can only be used with the INTERFACE keyword of target_link_libraries
0赞 Tsyvarev 10/8/2023
bar不是 INTERFACE 库,因此调用不会导致此类错误。target_link_libraries(bar PRIVATE foo)
0赞 playing4time 10/9/2023
谢谢,明白了。我报告的错误来自仅标头库,具体取决于另一个仅标头库;该错误适用于 的第一个参数,而不是第三个参数。target_link_libraries()

答:

0赞 playing4time 10/9/2023 #1

来自评论:

  1. 常规库取决于仅标头库:barfoo
target_link_libraries(bar PUBLIC foo)
  1. 仅标头库取决于仅标头库:quuxfoo
target_link_libraries(quux INTERFACE foo)