Cmkae外部依赖管理

文章目录

  • 一、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(googletestGIT_REPOSITORY https://github.com/google/googletest.gitGIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)# 从网址下载代码
FetchContent_Declare(myCompanyIconsURL      https://intranet.mycompany.com/assets/iconset_1.12.tar.gzURL_HASH MD5=5588a7b18261c20068beabfb4f530b87
)
# 确保依赖项在这里已经完成下载和构建
FetchContent_MakeAvailable(googletest myCompanyIcons)

FetchContent_Declare命令会生成以下变量:

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

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

# 从GitHub上下载代码
FetchContent_Declare(googletestGIT_REPOSITORY https://github.com/google/googletest.gitGIT_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(googletestGIT_REPOSITORY https://github.com/google/googletest.gitGIT_TAG        703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0FIND_PACKAGE_ARGS NAMES GTest
)
FetchContent_Declare(Catch2GIT_REPOSITORY https://github.com/catchorg/Catch2.gitGIT_TAG        605a34765aa5d5ecbf476b4598a862ada971b0cc # v3.0.1FIND_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)# 依赖Gitfind_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.mzph.cn/news/193633.shtml

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

相关文章

Git Bash环境下用perl脚本获取uuid值

在Linux环境下&#xff0c;比如在ubuntu就直接有uuidgen命令直接获取uuid值。在Windows环境下常用的git bash中没有对应的命令&#xff0c;略有不便。这里用脚本写一个uuidgen&#xff0c;模拟Linux环境下的uuidgen命令。 #! /usr/bin/perl use v5.14; use Win32;sub uuidGen {…

6-13连接两个字符串

#include<stdio.h> int main(){int i0,j0;char s1[222],s2[333];printf("请输入第一个字符串&#xff1a;\n");gets(s1);//scanf("%s",s1);printf("请输入第二个字符串&#xff1a;\n");gets(s2);while(s1[i]!\0)i;while(s2[j]!\0)s1[i]s2…

1.1卷积的作用

上图解释了1∗1卷积如何适用于尺寸为H∗W∗D的输入层&#xff0c;滤波器大小为1∗1∗D&#xff0c;输出通道的尺寸为H∗W∗1。如果应用n个这样的滤波器&#xff0c;然后组合在一起&#xff0c;得到的输出层大小为H∗W∗n。 1.1∗1卷积的作用 调节通道数 由于 11 卷积并不会改…

webpack查找配置文件的策略

Webpack 在执行时会按照一定的策略来查找配置文件。以下是它查找配置文件的基本流程&#xff1a; 1.命令行指定&#xff1a; 如果在运行 Webpack 时通过 --config 或 -c 参数指定了配置文件的路径&#xff0c;那么 Webpack 将使用这个指定的配置文件。 2.默认查找顺序&…

Java研学-反射与内省

一 反射机制 1 含义 通过指定类的字节码文件获取对应的字节码对象;通过该对象调用类中的成员 2 获取类的真实类型的方式 ① 正射机制 – new关键字实例化对象 // Animal类 public class Animal{private String name;private int kg;...... }// 实例化对象 public class Tes…

程序员日常使用Shell命令:提高工作效率的实用技巧

作为程序员&#xff0c;我们每天都在与代码和工具打交道。其中&#xff0c;Shell是一个非常重要的工具&#xff0c;它可以帮助我们高效地完成各种任务。本文将列举一些程序员日常使用Shell提高效率的操作&#xff0c;帮助大家更好地利用Shell提高工作效率。 首先&#xff0c;让…

[递归] 平衡矩阵

平衡矩阵 题目描述 现在有一个n阶正整数方阵&#xff08;n<7&#xff09;&#xff0c;现在可以对矩阵的任意一行进行左移&#xff0c;具体操作为&#xff1a;每次对于某一行a_i1,a_i2,…,a_in进行一次左移&#xff0c;最左边的元素移动到这一行的末尾&#xff0c;其他元素…

LinuxBasicsForHackers笔记 --文本处理

查看文件 head <file name> – 如果只想查看文件的开头部分&#xff0c;可以使用 head 命令。默认情况下&#xff0c;此命令显示文件的前10行。如果您想查看多于或少于默认的 10 行的内容&#xff0c;请在 head 命令之后、文件名之前使用破折号 (-) 开关输入所需的数量。…

springboot centos集成 OpenOffice 实现 在线预览 doc excel docx 成pdf的 并且包含中文包和英文包和安装

我的资源里面有 springboot linux 集成 OpenOffice 实现在线预览 docx doc excel img等功能&#xff0c; 报问题 &#xff1a;no suitable windowing system found, exiting. 解决方案 yum groupinstall "X Window System"如果还是报这个错 执行 yum groupinstall …

Google Guava 数学工具使用详解

文章目录 数学数值运算取整范围值比较其他 数学 在 Guava 中&#xff0c;数学&#xff08;Math&#xff09;模块提供了一些常用的数学运算功能&#xff0c;包括数值运算、取整、范围值比较等。下面详细介绍一些 Guava 数学运算的使用方法和示例。 数值运算 IntMath 类提供了处…

App测试之App日志收集及adb常用命令

文章目录 前言一、adb是什么1.APP测试收集手机日志常用的工具2.adb下载与安装3.ADT/SDK/ADB是什么4.adb连接真机 二、adb常用命令三、android系统日志文件1.logcat日志文件2.logcat日志文件分析 四、分析crash & ANR 日志1.发生crash如何分析2.发生ANR如何分析 总结扩展&am…

前端组件库开发

通常我们会使用很多组件库&#xff0c;有时候我们会去看源码比如element&#xff0c;antd&#xff0c;然后发现多少是按需导出&#xff0c;和vue.use全局注册&#xff0c;依赖于框架的拓展。 组件库的开发依赖框架的版本和node的版本&#xff0c;这个是需要说明的&#xff0c;然…

【阅读论文】时间序列异常检测:综合评价

文章目录 摘要1 异常检测范围2 时间序列和异常3 异常检测技术3.1预测方法3.2重建方法3.3编码方法3.4距离方法3.5分布方法3.6隔离树方法 4 实验评估4.1环境和设置4.2结果质量4.3运行时和内存 5 讨论致谢参考文献 摘要 在金融应用中&#xff0c;检测时间序列数据中的异常子序列是…

解决浏览器缓存问题

1.index.html文件meta标签添加属性 <meta name"viewport" content"widthdevice-width,initial-scale1.0, maximum-scale1.0, minimum-scale1.0, user-scalableno" viewport-fitcover >2.提前main.html处理逻辑再跳转到index.html页 <script>…

ubuntu下QT搭建Android开发环境

一、前言 用QT开发android和直接使用android开发的区别 使用Qt开发Android应用和直接使用Android开发工具&#xff08;例如Android Studio&#xff09;有一些区别&#xff0c;主要体现在开发工具、语言、界面设计和性能等方面&#xff1a; 开发工具&#xff1a; Qt Creat…

Python----字典练习

相关链接&#xff1a;Python---字典的增、删、改、查操作_python中字典的增删改查-CSDN博客 Python---字典---dict-CSDN博客 Python---引用变量与可变、非可变类型-CSDN博客 重点&#xff1a; 字典中的 key &#xff08;就是键&#xff09;可以是很多数据类型&#xff08;…

jmeter下载地址

Jmeter安装教程【5.5】【Windows】jmeter详细安装配置教程&#xff0c;装不好你打我_一只莽夫的博客-CSDN博客

Java线程池的使用和最佳实践

第1章&#xff1a;引言 处理并发问题时&#xff0c;如果每次都新建线程&#xff0c;那系统的压力得有多大&#xff1f;这时候&#xff0c;线程池就像一个英雄一样出现了&#xff0c;它帮我们有效地管理线程&#xff0c;提高资源利用率&#xff0c;降低开销。那么&#xff0c;为…

代理模式介绍(静态代理、jdk动态代理、cglib代理)

一、静态代理 &#xff08;一&#xff09;定义 1、定义 为其他对象提供一种代理以控制对这个对象的访问&#xff1b; 2、涉及到的角色 &#xff08;1&#xff09;抽象主题角色&#xff1a;真实主题和代理主题的共同接口&#xff0c;便于在使用真实主题的地方都可以使用代理…

C#网络编程System.Net.WebClient 类vs System.Net.Http.HttpClient 类

目录 一、WebClient 类 1.WebClient 将数据上传到资源的方法 2.WebClient 从资源下载数据的方法 3.示例源码 4.生成效果 二、HttpClient 类 1.示例源码 2.生成效果 为什么要把两者拿出来pk呢&#xff1f;那是因为WebClient已经在.NET 6.0以后得版本被弃用了&#xff0c…