当前位置: 首页 > 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(BTestGIT_REPOSITORY https://github.com/example/BTest.gitGIT_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(BTestGIT_REPOSITORY https://github.com/example/BTest.gitGIT_TAG v1.0PREFIX ${CMAKE_BINARY_DIR}/BTestINSTALL_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 BTestGIT_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可能是一个更好的选择。

相关文章:

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

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

Touchgfx 编写下载算法文件(.stldr)

一)下载算法文件主要参考官方的STM32 ST-LINK Utility模板:(文件所在位置如下:) C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader\M25P64_STM3210E-EVAL\Project\MD…...

回不去的乌托邦

回不去的乌托邦 坐在电脑面前愣神间已至深夜,依然睡意不起。 相比于带着疲惫入睡,伏案发呆更令人惬意。想起最近在自媒体上看到的一句话“最顶级的享受变成了回不去的乌托邦”。 “这是兄弟们最后一次逛校园了,我拍个照”。我的记忆力总是用在…...

如何在 SpringBoot 项目使用 Redis 的 Pipeline 功能

本文是博主在批量存储聊天中用户状态和登陆信息到 Redis 缓存中时,使用到了 Pipeline 功能,并对此做出了整理。 一、Redis Pipeline 是什么 Redis 的 Pipeline 功能可以显著提升 Redis 操作的性能,性能提升的原因在于可以批量执行命令。当我…...

Linux----线程

一、基础概念对比 特性进程 (Process)线程 (Thread)资源分配资源分配的基本单位(独立地址空间)共享进程资源调度单位操作系统调度单位CPU调度的最小单位创建开销高(需复制父进程资源)低(共享进程资源)通信…...

实现rolabelimg对于dota格式文件的直接加载和保存

在本篇博客中,我们将讲解如何修改roLabelImg.py文件,使其能够直接加载和保存Dota格式的标注文件(txt)以替换掉复杂的xml文件。通过对源代码的修改,我们将实现支持加载并保存Dota格式标注数据,以便与roLabel…...

bboss v7.3.5来袭!新增异地灾备机制和Kerberos认证机制,助力企业数据安全

ETL & 流批一体化框架 bboss v7.3.5 发布,多源输出插件增加为特定输出插件设置记录过滤功能;Elasticsearch 客户端新增异地双中心灾备机制,提升框架高可用性;Elasticsearch client 和 http 微服务框架增加对 Kerberos 认证支持…...

华为昇腾服务器固件Firmware、驱动Drive、CANN各自的作用与联系?

文章目录 **1. 固件(Firmware)****2. 驱动(Driver)****3. CANN(Compute Architecture for Neural Networks)****三者关系****典型问题定位** 华为昇腾服务器的固件、驱动和CANN是支撑其AI计算能力的核心组件…...

MySQL 视图入门

一、什么是 MySQL 视图 1.1 视图的基本概念 在 MySQL 中,视图是一种虚拟表,它本身并不存储实际的数据,而是基于一个或多个真实表(基表)的查询结果集。可以把视图想象成是一个预定义好的查询语句的快捷方式。当你查询…...

算法很美笔记(Java)——动态规划

解重叠子问题(当前解用到了以前求过的解) 形式:记忆型递归或递推(dp) 动态规划本质是递推,核心是找到状态转移的方式,也就是填excel表时的逻辑(填的方式),而…...

C++ ——继承

体现的是代码复用的思想 1、子类继承父类,子类就拥有了父类的特性(成员方法和成员属性) 2、已存在的类被称为“基类”或者“父类”或者“超类”;新创建的类被称为“派生类”或者“子类” 注意: (1&#…...

LeetCode 热题 100 283. 移动零

LeetCode 热题 100 | 283. 移动零 大家好,今天我们来解决一道经典的算法题——移动零。这道题在LeetCode上被标记为简单难度,要求我们将数组中的所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。下面我将详细讲解解题思路,…...

游戏引擎学习第116天

回顾昨天的工作 本次工作内容主要集中在游戏开发的低级编程优化,尤其是手动优化软件渲染。工作目的之一是鼓励开发者避免依赖外部库,而是深入理解代码并进行优化。当前阶段正进行SIMD(单指令多数据)优化,使用Intel推荐…...

react(9)-redux

使用CRA快速创建react项目 npx create-react-app react-redux 安装配套工具 npm i reduxjs/toolkit react-redux 启动项目 在创建项目时候会出现一个问题 You are running create-react-app 5.0.0, which is behind the latest release (5.0.1). We no longer support…...

Linux内核实时机制7 - 实时改造机理 - 软中断优化下

Linux内核实时机制7 - 实时改造机理 - 软中断优化下 https://blog.csdn.net/u010971180/article/details/145722641以下分别以Linux4.19、Linux5.4、Linux5.10、Linux5.15 展开分析,深入社区实时改造机理的软中断优化过程。https://blog.csdn.net/weixin_41028621/article/det…...

企业知识管理平台重构数字时代知识体系与智能服务网络

内容概要 现代企业知识管理平台的演进呈现出全生命周期管理与智能服务网络构建的双重特征。通过四库体系(知识采集库、加工库、应用库、评估库)的协同运作,该系统实现了从知识沉淀、结构化处理到价值释放的完整闭环。其中,知识图…...

大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(3)

Paimon的下载及安装,并且了解了主键表的引擎以及changelog-producer的含义参考: 大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(1) 利用Paimon表做lookup join,集成mysql cdc等参考: 大数据组件(四)快速入门实时数据…...

SVN把英文换中文

原文链接:SVN设置成中文版本 都是英文,换中文 Tortoise SVN 安装汉化教程(乌龟SVN) https://pan.quark.cn/s/cb6f2eee3f90 下载中文包...

Ubuntu 的RabbitMQ安装

目录 1.安装Erlang 查看erlang版本 退出命令 2. 安装 RabbitMQ 3.确认安装结果 4.安装RabbitMQ管理界面 5.启动服务并访问 1.启动服务 2.查看服务状态 3.通过IP:port 访问界面 4.添加管理员用户 a)添加用户名:admin,密码&#xff1…...

基于WebRTC与AI大模型接入EasyRTC:打造轻量级、高实时、强互动的嵌入式音视频解决方案

随着物联网和嵌入式技术的快速发展,嵌入式设备对实时音视频通信的需求日益增长。然而,传统的音视频解决方案往往存在体积庞大、实时性差、互动体验不佳等问题,难以满足嵌入式设备的资源限制和应用场景需求。 针对以上痛点,本文将介…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

数据链路层的主要功能是什么

数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...