当前位置: 首页 > news >正文

CMake管理依赖实战:多仓库的无缝集成

随着软件复杂度的增加,单个项目可能需要依赖多个外部库或模块。这些依赖项可能是来自不同的代码仓库,如ATestBTest。为了实现高效的依赖管理,CMake提供了多种方式来处理这种多仓库的情况。下面我们将详细介绍几种常见的方法,并通过实例展示它们的应用场景。

方法一:使用 add_subdirectory(代码强绑定)

示例

假设我们有两个项目ATestBTest,其中BTestATest的一个子模块。

A的 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(ATest)

add_subdirectory(BTest)

add_executable(ATest main.cpp)

target_link_libraries(ATest PRIVATE BTest)

B的 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(BTest)

add_library(BTest STATIC btest.cpp btest.h)
优点与缺点
  • 优点: 简单直接,适合小型项目。
  • 缺点: 需要将BTest作为子目录包含在ATest中,不够灵活。
应用场景

适用于BTest作为ATest的一部分,且两者紧密耦合的情况。

方法二:使用 find_package(系统级安装)

示例

BTest是一个独立的库时,可以使用find_package来查找并链接它。

B的 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(BTest)

add_library(BTest STATIC btest.cpp btest.h)

install(TARGETS BTest DESTINATION lib)
install(FILES btest.h DESTINATION include)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
    "${PROJECT_BINARY_DIR}/BTestConfigVersion.cmake"
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY AnyNewerVersion
)
configure_package_config_file(
    "BTestConfig.cmake.in"
    "${PROJECT_BINARY_DIR}/BTestConfig.cmake"
    INSTALL_DESTINATION lib/cmake/BTest
)
install(FILES "${PROJECT_BINARY_DIR}/BTestConfig.cmake" "${PROJECT_BINARY_DIR}/BTestConfigVersion.cmake"
        DESTINATION lib/cmake/BTest)

A的 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(ATest)

find_package(BTest REQUIRED)

add_executable(ATest main.cpp)

target_link_lraries(ATest PRIVATE BTest::BTest)
优点与缺点
  • 优点: 灵活,适合复用,适合大型项目。
  • 缺点: 需要额外的配置步骤。
应用场景

适用于BTest是一个独立库,并且需要被多个项目复用的情况。

方法三:使用 FetchContent(现代源码集成)

示例

如果希望在构建时动态下载BTest,可以使用FetchContent

A的 CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(ATest)

include(FetchContent)
FetchContent_Declare(
    BTest
    GIT_REPOSITORY https://github.com/example/BTest.git
    GIT_TAG v1.0
)
FetchContent_MakeAvailable(BTest)

add_executable(ATest main.cpp)

target_link_libraries(ATest PRIVATE BTest::BTest)

B的 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(BTest)

add_library(BTest STATIC btest.cpp btest.h)

add_library(BTest::BTest ALIAS BTest)
优点与缺点
  • 优点: 自动化程度高,无需手动克隆。
  • 缺点: 构建时需要网络连接,依赖仓库可用性影响构建。
应用场景

适用于BTest是一个外部依赖,但不希望将其作为子模块或本地库的情况。

方法四:使用 ExternalProject(完全控制构建)

示例

对于复杂的构建过程,可以使用ExternalProject

A的 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(ATest)

include(ExternalProject)
ExternalProject_Add(
    BTest
    GIT_REPOSITORY https://github.com/example/BTest.git
    GIT_TAG v1.0
    PREFIX ${CMAKE_BINARY_DIR}/BTest
    INSTALL_DIR ${CMAKE_BINARY_DIR}/BTest/install
)

set(BTEST_INCLUDE_DIR ${CMAKE_BINARY_DIR}/BTest/install/include)
set(BTEST_LIBRARY ${CMAKE_BINARY_DIR}/BTest/install/lib/libBTest.a)

add_executable(ATest main.cpp)

target_include_directories(ATest PRIVATE ${BTEST_INCLUDE_DIR})
target_link_libraries(ATest PRIVATE ${BTEST_LIBRARY})

add_dependencies(ATest BTest)

B的 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(BTest)

add_library(BTest STATIC btest.cpp btest.h)

install(TARGETS BTest DESTINATION lib)
install(FILES btest.h DESTINATION include)
优点与缺点
  • 优点: 自动化程度高,可控制依赖的构建过程。
  • 缺点: 配置复杂,构建时间长。
应用场景

适用于BTest的构建过程复杂且需要自动化的情况。

方法五:使用 CPM.cmake(动态Git集成)

适用场景
  • 需要灵活控制依赖版本。
  • 避免本地存储依赖代码。

CPM.cmake 是一个轻量级的CMake脚本,它利用了CMake内建的FetchContent模块,但提供了更多功能,如版本控制、缓存机制等关键特性。通过简单的命令,即可将CPM引入现有项目,立即享有强大的依赖管理功能。

实现步骤
BTest/CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(BTest LANGUAGES CXX VERSION 1.0.0)

add_library(BTest STATIC src/b.cpp)
target_include_directories(BTest PUBLIC include)
ATest/CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(ATest LANGUAGES CXX)

include(cmake/CPM.cmake)  # 下载CPM脚本

CPMAddPackage(
  NAME BTest
  GIT_REPOSITORY "https://github.com/your/BTest.git"
  GIT_TAG v1.0.0
)

add_executable(ATest src/main.cpp)
target_link_libraries(ATest PRIVATE BTest)
优点与缺点
  • 优点:

    • 版本灵活控制:可以精确指定依赖库的版本号或Git标签,确保项目的稳定性和可追溯性。
    • 轻量化和即插即用:无需安装额外工具,仅需下载一个CPM.cmake脚本文件即可使用。
    • 跨平台支持:适用于任何操作系统,无论是Windows、Linux还是macOS都能无缝工作。
  • 缺点:

    • 需要网络访问:所有依赖库最初都要从网上下载构建,如果离线使用则需设置环境变量CPM_SOURCE_CACHE来缓存依赖。
应用场景

适用于需要对依赖库进行精确版本控制,并且希望避免在本地存储依赖代码的场景。例如,在持续集成环境中,每次构建时都需要确保获取到确切版本的依赖,保证构建的可复现性。

比较与选择

方法优点缺点场景
add_subdirectory简单直接,易于实现需要将BTest放在ATest的目录下,不够灵活BTestATest的子模块或子目录的情况
find_package灵活,适合复用需要额外的配置步骤BTest是独立库,需要被多个项目复用的情况
FetchContent自动下载依赖,无需手动操作构建时需要网络连接,依赖仓库可用性影响构建BTest是外部依赖,但不希望将其作为子模块或本地库的情况
ExternalProject自动化程度高,可控制依赖的构建过程配置复杂,构建时间长BTest的构建过程复杂且需要自动化的情况
CPM.cmake版本灵活控制,轻量化,跨平台支持需要网络访问,初次构建可能较慢需要灵活控制依赖版本,避免本地存储依赖代码的场景

结论

选择合适的方法取决于具体的需求和项目规模。

  • 对于简单的项目,add_subdirectory可能是最简单的选择;
  • 而对于更复杂的项目,特别是当依赖项是独立的库时,find_packageFetchContent则更为适用。
  • 如果依赖项的构建过程特别复杂,则 CPMExternalProject可能是一个更好的选择。

相关文章:

  • 在windows下安装windows+Ubuntu16.04双系统(下)
  • go WEB框架
  • Git 合并冲突解决与状态分析笔记
  • 发现问题 python3.6.13+django3.2.5 只能以asgi启动server 如何解决当前问题
  • rust笔记1-学习资料推荐
  • C#设计模式 学习笔记
  • OpenProject项目管理系统
  • 如何在Windows 10操作系统中安装并配置PHP集成软件XAMPP
  • 微前端qiankun打包部署
  • js 跳出循环
  • Moonshot AI 新突破:MoBA 为大语言模型长文本处理提效论文速读
  • java项目引用sevenzipjbinding依赖报错问题
  • Linux基础开发工具的使用(apt、vim、gcc、g++、gdb、make、makefile)
  • 代码审计入门学习之sql注入
  • 持续记录FASTAI学习踩坑
  • 单片机 Bootloade与二进制文件的生成
  • 什么是电力交易员
  • 基于ffmpeg+openGL ES实现的视频编辑工具-添加滤镜(七)
  • Ecode在流程表单中插入自定义内容
  • 从CNN到Transformer:遥感影像目标检测的未来趋势
  • 秘鲁总统任命前司法部长阿拉纳为新总理
  • 陕西省安康市汉阴县县长陈永乐已任汉阴县委书记
  • 沙县小吃中东首店在沙特首都利雅得开业,首天营业额5万元
  • 生态环境保护督察工作条例对督察对象和内容作了哪些规定?有关负责人答问
  • 全国汽车以旧换新补贴申请量突破1000万份
  • 专访|西蒙·斯特朗格:以“辞典”的方式讲述二战家族史