首页 > 解决方案 > 使用 CMake 安装库时如何链接可能是共享库的目标

问题描述

我有一个可以构建为共享或静态的库,并使用系统上已经存在的另一个库,也可以是共享的或静态的。前者是后者的 C++ 包装器,后者是 C 库

正确的target_link_libraries调用是什么?

如果我这样做了,target_link_libraries(cpplib PUBLIC clib)那么我还将clib向消费者传播包含目录,cpplib但那些应该只使用 C++ 库提供的接口,该接口在其标头中没有提及 clib。

如果我这样做target_link_libraries(cpplib PRIVATE clib)了,那么消费者的包含路径就更清晰了,但是当我现在使用其配置文件安装 CMake 项目的 export-install-install_exports 舞蹈时,*targets.cmake我遇到了一个问题:如果两个库都是共享的,那么安装的目标cpplib 没有提及 clib 和链接,因此失败libc.so, needed by libcpp.so, not found并出现许多未定义的引用。

这两个库都使用目标,尤其是在 Windows 下,无法确定 clib 是否共享。

什么是惯用方式?

CMakeLists.txt

cmake_minimum_required(VERSION 3.8.0)
project(cpplib)

find_package(clib REQUIRED)
add_library(cpplib SHARED cpplib.cpp)
target_link_libraries(cpplib PRIVATE clib::clib)

target_include_directories(cpplib PUBLIC $<INSTALL_INTERFACE:include/cpplib>)

include(CMakePackageConfigHelpers)
set(PROJECT_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/cpplibConfig.cmake")
configure_package_config_file("Config.cmake.in" ${PROJECT_CONFIG_FILE} INSTALL_DESTINATION "lib/cmake")

install(
  TARGETS cpplib 
  EXPORT cpplibTargets
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib 
  RUNTIME DESTINATION bin 
)
install(FILES cpplib.h DESTINATION include/cpplib)
install(FILES ${PROJECT_CONFIG_FILE} DESTINATION "share/cpplib")
install(EXPORT cpplibTargets NAMESPACE "cpplib::" DESTINATION "share/cpplib")

配置文件

@PACKAGE_INIT@

find_package(BZip2 REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components("@PROJECT_NAME@")

“用户”项目 CMakeLists.txt

cmake_minimum_required(VERSION 3.8.0)
project(user)

find_package(cpplib REQUIRED)
add_executable(user main.cpp)
target_link_libraries(user cpplib::cpplib)

编辑:因为我发现它很奇怪,它可以工作,当我在与库相同的 CMakeLists 中添加可执行文件时(所以不使用已安装的版本)我挖得更深:我只是注意到 CMake 在安装时清除了 rpath:

-- Installing: /tmp/install/lib/cpplib.so
-- Set runtime path of "/tmp/install/lib/cpplib.so" to ""

ldd在比较已安装库的输出和构建树中后者能够解析 clib的输出时发现了这一点。这是为什么?

标签: c++cmakeinstallationshared-libraries

解决方案


推荐阅读