You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake项目迁移:如何先构建依赖库再编译子项目?

从Autotools迁移到CMake的大型项目依赖库构建问题

我正在将一个大型项目从Autotools迁移到CMake,项目里有一批被其他代码依赖的库。但项目的部分模块要拆分到独立仓库,这导致引用这些库时没法直接用目标名称,只能通过find_library或包搜索等方式定位。

给定如下项目结构,如何让CMake先构建这些库,让子项目能找到它们?

main
  |- CMakeLists.txt (顶层)
  |- myLibs/
  |----CMakeLists.txt (目前仅执行 add_subdirectory(libX))
  |----lib (make install 的输出目录)
  |----include (make install 的公共头文件输出目录)
  |----mylibA  
  |-------CMakeLists.txt  
  |----mylibB
  |-------CMakeLists.txt
  |-projCollections/ (程序集合)
  |----CMakeLists.txt (依赖 mylibA 和 mylibB)
  |----projA  -> 无法直接引用任何 myLibs 库
  |------CMakeLists.txt (依赖 mylibA )
  |----projB
  |------CMakeLists.txt (依赖 mylibA 和 mylibB)

我目前想到几种解决方案:

  • 使用execute_process立即对myLibs执行cmake配置和make命令
  • 在projCollections上使用ExternalProject_add
  • 在myLibs上使用ExternalProject

ExternalProject看起来可行,但或许我可以暂时允许直接引用,等源码拆分完成后,再修改所有(100+个)CMakeLists.txt文件改用find_library...


当前基础CMake结构

顶层CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(main)
add_subdirectory(myLibs)
add_subdirectory(projCollections)

myLibs/CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(myLibs DESCRIPTION "myLibs")
add_subdirectory(mylibA)
add_subdirectory(mylibB)

projCollections/CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(projCollections DESCRIPTION "projCollections")
add_subdirectory(projA)
add_subdirectory(projB)

projA/CMakeLists.txt

project(projA )
find_library(MYLIBA NAMES mylibA HINTS ${CMAKE_SOURCE_DIR}/myLibs/libs/mylibA.so NO_DEFAULT_PATH)    
add_executable(projA)
target_link_libraries(projA myLibA)

解决方案推荐

方案1:临时允许直接引用(过渡最优)

既然拆分是未来计划,当前阶段最省心的方式就是保留直接引用,避免提前修改大量CMakeLists.txt。只需确保mylibA和mylibB的CMake配置正确导出目标,后续拆分时再替换为find_package或find_library:

  1. 在mylibA/CMakeLists.txt和mylibB/CMakeLists.txt中添加安装与导出配置(以mylibA为例):
add_library(mylibA ...)
# 配置公共头文件路径,兼容构建和安装两种场景
target_include_directories(mylibA PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>
)
# 安装目标文件和头文件
install(TARGETS mylibA
  EXPORT mylibA-targets
  LIBRARY DESTINATION lib
  INCLUDES DESTINATION include
)
install(DIRECTORY include/ DESTINATION include)
# 导出CMake配置文件,供拆分后find_package使用
install(EXPORT mylibA-targets
  FILE mylibAConfig.cmake
  DESTINATION lib/cmake/mylibA
)
  1. 修改projA/CMakeLists.txt,直接用目标名链接:
project(projA)
add_executable(projA ...)
# 直接引用目标,CMake自动处理依赖构建顺序
target_link_libraries(projA PRIVATE mylibA)

这种方式完全兼容未来拆分:拆分后只需在projA中替换为find_package(mylibA REQUIRED),其余链接逻辑不变,修改量极小。

方案2:用ExternalProject构建myLibs(模拟拆分后依赖)

如果想提前模拟拆分后的依赖模式,推荐在顶层CMake中用ExternalProject构建myLibs,确保projCollections只能通过安装路径查找库:

  1. 修改顶层CMakeLists.txt,替换add_subdirectory(myLibs)为ExternalProject_Add:
cmake_minimum_required(VERSION 3.14)
project(main)

include(ExternalProject)
ExternalProject_Add(
  myLibs_build
  SOURCE_DIR ${CMAKE_SOURCE_DIR}/myLibs
  BINARY_DIR ${CMAKE_BINARY_DIR}/myLibs_build
  CMAKE_ARGS
    -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/myLibs_install
  INSTALL_DIR ${CMAKE_BINARY_DIR}/myLibs_install
)

# 传递安装路径给projCollections
set(MYLIBS_INSTALL_DIR ${CMAKE_BINARY_DIR}/myLibs_install)
add_subdirectory(projCollections)
# 确保projCollections在myLibs构建完成后再编译
add_dependencies(projCollections myLibs_build)
  1. 更新projA/CMakeLists.txt的查找逻辑:
project(projA)
find_library(MYLIBA NAMES mylibA HINTS ${MYLIBS_INSTALL_DIR}/lib NO_DEFAULT_PATH)
find_path(MYLIBA_INCLUDE_DIR NAMES mylibA.h HINTS ${MYLIBS_INSTALL_DIR}/include NO_DEFAULT_PATH)

add_executable(projA ...)
target_include_directories(projA PRIVATE ${MYLIBA_INCLUDE_DIR})
target_link_libraries(projA PRIVATE ${MYLIBA})

这种方式完全模拟拆分后的依赖模式,但需要提前配置所有查找逻辑,适合需要提前验证拆分后兼容性的场景。

方案3:execute_process(不推荐)

execute_process会在CMake配置阶段直接执行构建命令,破坏CMake的依赖跟踪机制,容易导致并行构建失败、增量构建失效等问题,除非特殊场景,不建议使用。


内容的提问来源于stack exchange,提问作者Andrew S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:56:13