CMake跨项目依赖问题:导入库的Threads目标未被传递识别
我有两个CMake项目A和B,其中B依赖于A。A是一个仅头文件库,其主CMakeLists.txt中链接了Threads:
# liba/CMakeLists.txt find_package(Threads REQUIRED) target_link_libraries(liba_liba INTERFACE Threads::Threads)
库A还通过以下方式生成包配置文件:
# liba/CMakeLists.txt install( TARGETS liba_liba EXPORT libaTargets ... ) install( EXPORT libaTargets NAMESPACE liba:: )
我执行以下命令安装A:
# 在liba/目录下执行 cmake --install build --prefix output
现在在库B中,我通过指定前缀路径来引用库A:
# 在libb/build目录下执行 cmake .. -DCMAKE_PREFIX_PATH=/home/user/dev/liba/output
此时似乎已找到相关目标,但出现以下错误:
The link interface of target "liba::liba" contains: Threads::Threads but the target was not found. Possible reasons include: * There is a typo in the target name. * A find_package call is missing for an IMPORTED target. * An ALIAS target is missing.
编辑:当我在库B中添加find_package(Threads REQUIRED)后,Threads目标可被找到且编译正常。这说明Threads目标在系统中可用,但为何liba无法自动传递该依赖?
CMake导出目标(EXPORT)仅会记录目标间的直接关联关系,不会自动导出依赖包的find_package调用逻辑。当你在A中链接Threads::Threads并导出libaTargets时,CMake只会把Threads::Threads这个目标名写入导出的配置文件,但不会自动帮下游的B项目添加find_package(Threads)的调用,导致B找不到该目标。
要让A自动传递Threads依赖,需要在A的包配置文件中显式引入依赖查找逻辑,具体可通过以下步骤实现:
创建包配置模板文件
在liba项目根目录下创建libaConfig.cmake.in模板:@PACKAGE_INIT@ # 显式查找Threads依赖 find_dependency(Threads REQUIRED) # 导入导出的目标文件 include("${CMAKE_CURRENT_LIST_DIR}/libaTargets.cmake")在A的CMakeLists.txt中生成并安装配置文件
添加以下代码,用于生成标准的包配置文件和版本文件:# liba/CMakeLists.txt include(CMakePackageConfigHelpers) # 生成libaConfig.cmake configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/libaConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libaConfig.cmake INSTALL_DESTINATION lib/cmake/liba ) # 生成版本文件 write_basic_package_version_file( ${CMAKE_CURRENT_BINARY_DIR}/libaConfigVersion.cmake VERSION ${PROJECT_VERSION} # 需确保已设置PROJECT_VERSION COMPATIBILITY SameMajorVersion ) # 安装配置文件 install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libaConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/libaConfigVersion.cmake DESTINATION lib/cmake/liba )重新安装A项目
重新编译并安装A后,当B项目执行find_package(liba)时,会自动调用find_dependency(Threads),从而自动找到Threads::Threads目标,无需B手动添加find_package(Threads)。
核心逻辑是:通过find_dependency函数,把依赖包的查找逻辑嵌入到A的包配置文件中,让下游项目在导入A时自动触发依赖查找,完成依赖传递。
内容的提问来源于stack exchange,提问作者glades

