CMake中外部库依赖内部库后向其他项目暴露的报错解决
问题分析与解决方案
问题根源
你用PRIVATE将libInternal链接到libExternal,但libInternal是OBJECT库,而libExternal是静态库。CMake在导出静态库目标时,会保留其对OBJECT库的依赖关系——因为静态库需要把OBJECT库的目标文件合并进去。当MainProgram通过find_package(libExternal)导入目标时,CMake找不到libInternal的导入目标,因此报错。
另外,当前libInternal的安装导出路径不规范,libExternalConfig.cmake也没有正确引入libInternal的配置,导致MainProgram环境无法识别libInternal目标。
解决方案
1. 修复libInternal的CMakeLists.txt
调整安装路径与配置文件,让find_package能自动识别:
cmake_minimum_required(VERSION 3.9) project(libInternal) add_library(Internal OBJECT files included) target_link_libraries(Internal PRIVATE lib included) target_include_directories(Internal INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public/include/internal>) # 安装TARGET与EXPORT,统一路径规范 install(TARGETS Internal EXPORT ${PROJECT_NAME} OBJECTS DESTINATION lib ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) # 将EXPORT安装到cmake子目录,与libExternal保持一致 install(EXPORT ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} FILE ${PROJECT_NAME}.cmake) # 生成Config.cmake和ConfigVersion.cmake,支持find_package识别 include(CMakePackageConfigHelpers) write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake COMPATIBILITY SameMajorVersion) # 创建基础Config.cmake文件 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake "include(\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}.cmake)") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) export(TARGETS Internal FILE ${PROJECT_NAME}.cmake)
2. 修改libExternal的CMakeLists.txt与配置文件
2.1 调整CMakeLists.txt的链接与导出逻辑
cmake_minimum_required(VERSION 3.9) project(libExternal VERSION 0.0.1) add_library(External STATIC files included) # 链接Internal,确保导出时能关联到libInternal的配置 target_link_libraries(External PRIVATE Internal) target_include_directories(External INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public/include/external>) install(TARGETS External EXPORT ${PROJECT_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(EXPORT ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} FILE ${PROJECT_NAME}.cmake) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/public/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) include(CMakePackageConfigHelpers) write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake COMPATIBILITY SameMajorVersion) # 在Config.cmake中显式引入libInternal的配置 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake "find_package(libInternal REQUIRED) include(\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}.cmake)") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) export(TARGETS External FILE ${PROJECT_NAME}.cmake)
3. MainProgram的CMake配置
只需要正常引入libExternal即可,依赖会自动传递:
find_package(libExternal REQUIRED) add_executable(MainProgram main.cpp) target_link_libraries(MainProgram PRIVATE External)
关键说明
- OBJECT库的依赖在静态库导出时无法被隐藏,因为静态库需要整合OBJECT的目标文件,必须让MainProgram环境能找到
libInternal的导入目标。 - 统一两个库的CMake配置文件路径,确保
find_package能自动定位到它们。 - 在
libExternalConfig.cmake中显式调用find_package(libInternal)是核心修复步骤——之前尝试无效大概率是因为libInternal的安装路径不规范,导致find_package无法识别。
内容的提问来源于stack exchange,提问作者Pagorek
相关产品推荐
相关产品推荐

