Cmkae外部依赖管理

news2025/1/19 14:33:00

文章目录

  • 一、cmake依赖管理介绍
  • 二、源码依管理
    • 1. `FetchContent`
      • 与find_package进行集成
    • 2. CPM
    • 3. git submodule
    • 附加: address_sanitizer 和 undefined sanitizer

一、cmake依赖管理介绍

在这里插入图片描述

CMake 是跨平台的构建系统,支持 C/C++、Objective-C、Fortran 等多种语言。CMake 提供了丰富的依赖管理功能,可以帮助开发人员轻松地管理第三方库的依赖关系。

CMake 的依赖管理功能主要包括以下几点:

  • 支持多种依赖获取方式:CMake 支持 Git Clone、下载源码压缩包等多种方式获取第三方库。
  • 支持重复依赖处理:CMake 可以自动处理依赖树中存在的重复依赖。
  • 支持第三方库的 Find 脚本:CMake 官方为许多常用的第三方库提供了 Find 脚本,可以帮助开发人员快速地获取和配置这些库。

CMake 的依赖管理功能可以分为两种类型:

  • 源码依赖:这种依赖是指第三方库的源代码。CMake 可以使用 Git Clone 或下载源码压缩包的方式获取第三方库的源代码。
  • 二进制依赖:这种依赖是指第三方库的二进制文件。CMake 可以使用第三方库的包管理器(例如 Conda 或 Homebrew)来获取第三方库的二进制文件。

今天我们就主要介绍: 源码管理

二、源码依管理

  1. cmake自带的命令:FetchContent
  2. cmake三方社区支持的命令: CPM
  3. git的submodule

该如何选择何种方式作为依赖管理:
如果你的依赖不是cmake项目,那就推荐使用git submodule进行管理
如果你的依赖项目是cmake项目,那FetchContentCPM都能满足需要,但是CPM更为优雅,所以更加推荐

1. FetchContent

使用FetchContent是非常简单的,只需要三步:

  1. 引入头文件
  2. 定义依赖需要下载代码的地址和一些其它属性
  3. enable依赖

比如:

# 从GitHub上下载代码
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)

# 从网址下载代码
FetchContent_Declare(
  myCompanyIcons
  URL      https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
  URL_HASH MD5=5588a7b18261c20068beabfb4f530b87
)
# 确保依赖项在这里已经完成下载和构建
FetchContent_MakeAvailable(googletest myCompanyIcons)

FetchContent_Declare命令会生成以下变量:

  1. <lowercaseName>_POPULATED: 设置为TRUE
  2. <lowercaseName>_SOURCE_DIR: 设置依赖下载的位置
  3. <lowercaseName>_BINARY_DIR: 设置依赖构建的位置

在设置使用关键字定义依赖源的一些信息时候,有一些可供选择的设置:

# 从GitHub上下载代码
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
  
  # 先通过find_package命令,通过name Gtest来找库,找不到就调用Fetch下载依赖
  # FIND_PACKAGE_ARGS NAMES GTest
  
  # find_package不能从本地找库,要用Fetch下载下来的库
  # OVERRIDE_FIND_PACKAGE
  
  # 该依赖的cmakelist配置文件是在该项目cmake文件夹内。
  # SOURCE_SUBDIR  cmake
  
  # 设置下载的依赖存放路径
  # SOURCE_DIR firmware
  
  # 是否启用浅克隆,(只会克隆当前分支或标签的提交,以及这些提交所引用的所有父提交)
  # GIT_SHALLOW
)
# 确保依赖项在这里已经完成下载和构建
FetchContent_MakeAvailable(googletest myCompanyIcons)

有些情况下,想要对依赖的管理控制的颗粒度更加精细,我们可以:

# 检查是否依赖已经下载
FetchContent_GetProperties(depname)
# 如果还没有下载
if(NOT depname_POPULATED)
		# 执行下载
		FetchContent_Populate(depname	)
endif()

使用该方法进行下载安装依赖,该方法依赖FetchContent_Declare() 提前声明依赖。

但是下载依赖只会下载一次,如果二次调用则会因为错误而停止,

所以项目在调用FetchContent_Populate之前,应该先调用FetchContent_GetProperties()方法,获得当前的状态

使用保存的内容详细信息时,对 FetchContent_MakeAvailable()FetchContent_Populate() 的调用会在全局属性中记录可以随时查询的信息。该信息可以包括与内容相关联的源目录和二进制目录,以及内容填充是否已在当前配置运行期间被处理。

与find_package进行集成

include(FetchContent)
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
  FIND_PACKAGE_ARGS NAMES GTest
)
FetchContent_Declare(
  Catch2
  GIT_REPOSITORY https://github.com/catchorg/Catch2.git
  GIT_TAG        605a34765aa5d5ecbf476b4598a862ada971b0cc # v3.0.1
  FIND_PACKAGE_ARGS
)

# This will try calling find_package() first for both dependencies
FetchContent_MakeAvailable(googletest Catch2)

对于 Catch2 ,不需要为 find_package() 提供额外的参数,因此在 FIND_PACKAGE_ARGS 关键字之后不需要提供额外的参数。对于 googletest ,其包通常称为 GTest ,因此添加参数以支持通过该名称找到它。

OVERRIDE_FIND_PACKAGE : find_package应该只使用FetchContent_Declare里的信息
FIND_PACKAGE_ARGS: 如果find_package成功在本地找到二进制文件,则不需要FetchContent_Declare里的信息。
SOURCE_SUBDIR cmake: 指定依赖的项目cmakelist文件的地址, 该实例配置在项目跟路径下的cmake文件夹。
SOURCE_DIR firmware:指定下载依赖后存放的路径,该设置配置在项目跟路径下的firmware 文件夹

2. CPM

非官方的cmake依赖管理工具: CPM GitHub

使用方法: 直接到release页面,将cmake脚本文件下载,导入到自己的代码中。

image-20231203103400676

include(CPM)
# 使用GitHub用户nlohmann的仓库的json仓的3.11.2版本代码
cpmaddpackage("gh:nlohmann/json#v3.11.2")
  1. gh: : github
  2. nlohmann: 用户名
  3. json: 仓库名
  4. #v3.11.2: tag版本

3. git submodule

cmake demo

如果依赖是cmake项目,不太推荐使用该方法,将该方法封装为一个函数。可以参考:


# 函数add_git_submodule, 接受一个参数dir
function(add_git_submodule dir)
		# 依赖Git
    find_package(Git REQUIRED)

		# 如果指定的文件夹不存在,则调用git submodule的方法拉取最新代码
    if (NOT EXISTS ${CMAKE_SOURCE_DIR}/${dir}/CMakeLists.txt)
        execute_process(COMMAND ${GIT_EXECUTABLE}
            submodule update --init --recursive -- ${CMAKE_SOURCE_DIR}/${dir}
            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
    endif()

		# 拉取下来后将项目进行编译
    if (EXISTS ${CMAKE_SOURCE_DIR}/${dir}/CMakeLists.txt)
        message("Adding: ${dir}/CMakeLists.txt")
        add_subdirectory(${CMAKE_SOURCE_DIR}/${dir})
    else()
        message("Could not add: ${dir}/CMakeLists.txt")
    endif()
endfunction(add_git_submodule)
  • 使用方法:
# 设置cmake模块的路径
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
# 引入cmake的模块(xx.txt, xx就是模块名字)
include(AddGitSubmodule)

add_git_submodule(external/json)

附加: address_sanitizer 和 undefined sanitizer

option(ENABLE_SANITIZE_ADDR "Enable address sanitizer" ON)
option(ENABLE_SANITIZE_UNDEF "Enable undefined sanitizer" ON)

function(add_sanitizer_flags)
    if (NOT ENABLE_SANITIZE_ADDR AND NOT ENABLE_SANITIZE_UNDEF)
        message(STATUS "Sanitizers deactivated.")
        return()
    endif()

    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
        add_compile_options("-fno-omit-frame-pointer")
        add_link_options("-fno-omit-frame-pointer")

        if(ENABLE_SANITIZE_ADDR)
            add_compile_options("-fsanitize=address")
            add_link_options("-fsanitize=address")
        endif()

        if(ENABLE_SANITIZE_UNDEF)
            add_compile_options("-fsanitize=undefined")
            add_link_options("-fsanitize=undefined")
        endif()
    elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
        if(ENABLE_SANITIZE_ADDR)
            add_compile_options("/fsanitize=address")
        endif()

        if(ENABLE_SANITIZE_UNDEF)
            message(STATUS "Undefined sanitizer not impl. for MSVC!")
        endif()
    else()
        message(STATUS "Sanitizer not supported in this environment!")
    endif()
endfunction(add_sanitizer_flags)

  • 参考:

  • CPP的项目脚手架

  • FetchContent官网文档

  • UdemyCmake(https://github.com/franneck94/UdemyCmake/tree/master)

  • UdemyCmkae vedeo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1280451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++基础 -36- 模板之模板函数

模板函数格式 template <class T> void allexchange(T a,T b) {T c;c*a;*a*b;*bc; }模板函数可以增强函数的通用性 举例说明&#xff0c;使用一个模板函数实现了两个的函数的功能 #include "iostream"using namespace std;void myexchangeint(int* a,int* …

Grafana部署与Zabbix集成,搭建开源IT监控平台

Grafana部署与Zabbix集成 目前在一家公司主要是网络、运维、IT支持&#xff0c;每次需要检查服务器状态都是需要手动登录系统进行查看&#xff0c;因此想着部署一套监控系统&#xff0c;功能上需要实现监控、可视化、告警等。由于预算没有&#xff0c;服务器资源倒是有空闲的&a…

【hacker送书活动第7期】Python网络爬虫入门到实战

第7期图书推荐 内容简介作者简介大咖推荐图书目录概述参与方式 内容简介 本书介绍了Python3网络爬虫的常见技术。首先介绍了网页的基础知识&#xff0c;然后介绍了urllib、Requests请求库以及XPath、Beautiful Soup等解析库&#xff0c;接着介绍了selenium对动态网站的爬取和S…

电容和电感

一、电感 1&#xff09;图片 2&#xff09;作用 a&#xff09;储存容量 例如dcdc转换器的原理,将一个电压值转换成另外一个电压值 b&#xff09;选择信号 比如空气中弥漫着很多信号&#xff0c;我们应该怎么选取我们所需要的信号。 电感和电容可以看成一个电阻&#xff0c;当电…

Redis ziplist源码解析

area |<---- ziplist header ---->|<----------- entries ------------->|<-end->|size 4 bytes 4 bytes 2 bytes ? ? ? ? 1 byte--------------------------------------------------------------- comp…

MySQL进阶部分

存储引擎 MySQL体系结构图&#xff1a; 连接层&#xff1a; 最上层是一些客户端连接服务&#xff0c;主要完成一些类似于连接处理 &#xff0c;授权认证及相关的安全方案。服务器也会为安全接入的每个用户端验证它所具有的操作权限。 服务层&#xff1a; 第二层架构主要完成大…

数据科学:Matplotlib、Seaborn笔记

数据科学&#xff1a;Numpy、Pandas、Matplotlib、Seaborn 三、Matplotlib1.Matplotlib subplots函数2.tight_layout()函数3.Matplotlib grid()设置网格格式4.fill_between()函数示例设置x轴为时间刻度热力图 四、Seaborn1.set2.seaborn.scatterplot 参考 数据科学&#xff1a;…

github打不开,全网最简单解决方法,没有之一

下载watt toolkit&#xff0c; 选择‘github’&#xff0c;点击‘一键加速’&#xff0c; 具体步骤如下&#xff1a;去电脑微软商店下载watt toolkit&#xff0c;或者直接打开网址https://apps.microsoft.com/detail/9MTCFHS560NG?hlen-us&glUS 如图&#xff0c;点击安装i…

Sun Apr 16 00:00:00 CST 2023格式转换

Date date new Date(); log.info("当前时间为:{}",date); //yyyy-MM-dd HH:mm:ss SimpleDateFormat sdf new SimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS); String dateTime s…

Android11适配已安装应用列表

Android11适配已安装应用列表 之前做过已安装应用列表的适配&#xff0c;最近国内版SDK升级到33和隐私合规遇到很多问题&#xff0c;于是把已安装应用列表记录一下&#xff1a; 1、在Android11及以上的适配&#xff1a; package com.example.requestinsttallapplistdemoimpo…

电磁兼容EMC理论基础汇总

目录 0. 序言 1. EMC的基础介绍 1.1 EMC电磁兼容的定义 1.2 EMC的重要性 1.3 EMC的三要素 2. 库仑定律 3. 趋肤效应与趋肤深度 4. 电阻抗公式 4.1 电阻 4.2 容抗 4.3 感抗 4.4 电路元件的非理想性 5. 麦克斯韦方程组 5.1 高斯磁定律 5.2 高斯定律 5.3 法拉…

一文讲透Python函数的创建和调用

1.Python提供了函数作为完成某项工作的标准化代码块 Python本质上是一种编程语言&#xff0c;通过编写运行代码的方式实现工作目标。读者可以想象&#xff0c;如果针对机器学习或数据统计分析的每种方法或统计量计算都要用户自行编写代码&#xff0c;那么显然在很多情况下是无…

Rust 语言:认识 Rust

本心、输入输出、结果 文章目录 Rust 语言&#xff1a;认识 Rust前言Rust的特点Rust LOGO Rust 在IT行业的应用前景Rust 是一门系统级编程语言相关链接花有重开日&#xff0c;人无再少年实践是检验真理的唯一标准 Rust 语言&#xff1a;认识 Rust 编辑&#xff1a;简简单单 Onl…

多级缓存自用

1.什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,如图: 存在下面的问题: •请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈 •Redis缓存失效时,会对数据库产生冲击 多级缓存就是充分利用请求处理的每个环节,添加缓…

python系统调用执行ping命令无法检测到超时情况(破案了:ping命令-W参数单位为s,我写了个1000)

文章目录 问题描述破案了&#xff1a;ping命令-W参数单位为s&#xff0c;我写了个1000。。。,,ԾㅂԾ,, 问题描述 我用了系统调用去执行ping&#xff0c;一开始用os.system()&#xff0c;有问题&#xff0c;后面用subprocess问题还是存在&#xff0c;后来我把这个改了&#xff…

VMware17 下载、安装、成功安装效果、完整卸载

VMware17 下载、安装、卸载 下载 VMware17 安装 更改安装路径 去掉这两个复选框&#xff0c;点击安装。 安装结束&#xff0c;点击许可证。 输入序列号&#xff0c;点击【输入】 序列号&#xff1a;MC60H-DWHD5-H80U9-6V85M-8280D 点击完成 测试安装效果 永不过期&am…

Linux 编译安装colmap

COLMAP可以作为独立的app&#xff0c;通过命令行或者图形交互界面使用&#xff0c;也可以作为一个库被包含到其他源代码中。 这里记录一下编译安装colmap的过程&#xff0c;首先需要安装好CUDA&#xff0c;CUDA具体安装过程这里就不赘述了。在GitHub上下载源代码&#xff0c;我…

Stream API 方法使用总结

文章目录 1.1、Stream介绍1.2、Stream创建对象&#xff08;1&#xff09;empty()方法&#xff08;2&#xff09;of()方法&#xff08;3&#xff09;Arrays.stream()方法&#xff08;4&#xff09;list.stream()方法 1.3、Stream中间方法&#xff08;1&#xff09;filter()方法&…

100W用户、8000W流量在线贺卡应用架构如何优化?

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容&#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作…

Trie字符串统计(字典树的插入与查找)

题目&#xff1a; 插入模拟&#xff1a;假如现在要依次插入cat,car,busy,cate,bus,car 查找&#xff1a; 代码&#xff1a; import java.util.Scanner;public class Main {public static int[][] chnew int[100010][26];public static int[] cntnew int[100010];public static…