同一层级CMake项目依赖:第三方库构建顺序解决方案咨询
这个问题我之前也踩过坑,核心原因是find_package默认会去系统路径、已安装目录或者预配置的前缀路径里找库的CMake配置文件,但你的first_lib只是作为当前项目的子目录在本地构建,还没安装到系统,所以second_lib里的find_package(first_lib REQUIRED)自然找不到它。下面是几种最佳解决方式,按实用性排序:
1. 让first_lib导出本地构建的配置文件(最推荐)
这种方法既能保持second_lib的CMakeLists通用性(支持独立构建或作为子项目),又能让它在本地构建时找到first_lib的产物。步骤如下:
第一步:配置first_lib生成CMake包文件
在first_lib/CMakeLists.txt末尾添加以下代码,生成必要的配置文件和目标导出:
# 引入CMake包配置工具 include(CMakePackageConfigHelpers) # 生成版本配置文件 write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/first_libConfigVersion.cmake" VERSION ${PROJECT_VERSION} # 你需要先给first_lib设置PROJECT_VERSION COMPATIBILITY SameMajorVersion ) # 生成主配置文件(需要一个Config.cmake.in模板) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/first_libConfig.cmake" INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/first_lib ) # 导出本地构建的目标,让同项目的其他子目录能引用 export(EXPORT first_libTargets FILE "${CMAKE_CURRENT_BINARY_DIR}/first_libTargets.cmake" NAMESPACE first_lib::) # 可选:如果需要安装first_lib到系统,添加以下安装规则 install(EXPORT first_libTargets FILE first_libTargets.cmake NAMESPACE first_lib:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/first_lib) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/first_libConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/first_libConfigVersion.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/first_lib)
然后在first_lib目录下创建一个Config.cmake.in模板文件,内容如下:
@PACKAGE_INIT@ include("${CMAKE_CURRENT_LIST_DIR}/first_libTargets.cmake") check_required_components(first_lib)
第二步:在根CMakeLists中指定前缀路径
在根目录的CMakeLists.txt里,先构建first_lib,然后把它的构建目录加入CMAKE_PREFIX_PATH,这样second_lib的find_package就能找到本地生成的配置文件:
add_subdirectory(first_lib) # 将first_lib的构建目录加入前缀路径,让find_package能定位到它的配置文件 list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/first_lib") add_subdirectory(second_lib)
这样修改后,second_lib里的find_package(first_lib REQUIRED)就能正常找到本地构建的first_lib,不需要提前安装。
2. 直接引用first_lib的目标(最简单,适合内部项目)
如果second_lib只作为当前项目的子目录使用,不需要独立构建,那可以简化操作:直接修改second_lib/CMakeLists.txt,去掉find_package(first_lib REQUIRED),直接引用first_lib的目标。
比如在first_lib/CMakeLists.txt里你应该定义了库目标(比如add_library(first_lib ...)),并且可能设置了命名空间:
add_library(first_lib::first_lib ALIAS first_lib)
然后在second_lib/CMakeLists.txt里直接链接这个目标:
target_link_libraries(second_lib PRIVATE first_lib::first_lib)
这种方法不需要任何配置文件,直接利用CMake的全局目标可见性,缺点是second_lib无法脱离当前根项目独立构建。
3. 使用ExternalProject_Add(适合外部依赖库)
如果first_lib是外部仓库(比如需要从Git拉取),而不是你项目内的子目录,可以用ExternalProject_Add来控制构建顺序:
include(ExternalProject) ExternalProject_Add(first_lib SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/first_lib" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/first_lib" CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/install/first_lib ) # 让second_lib依赖first_lib的安装目标 ExternalProject_Add(second_lib SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/second_lib" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/second_lib" CMAKE_ARGS -DCMAKE_PREFIX_PATH=${CMAKE_CURRENT_BINARY_DIR}/install/first_lib DEPENDS first_lib )
不过这种方法会把first_lib安装到本地临时目录,对于项目内的子目录来说,第一种方案更轻量。
内容的提问来源于stack exchange,提问作者Abruzzo Forte e Gentile

