C++ 编译依赖管理系统分析以及 srcdep 介绍

如果用 C++ 写一个中小型软件,有要用到很多第三方库的话,相信不少人会觉得比较麻烦。很多新兴的语言都有了统一的依赖管理系统和构建系统,但是 C/C++ 界一直没有比较正统的。(也不奇怪,连统一的 string 都没有,怎么可能有统一的依赖、构建体系?)

在上一篇,我们尝试选择一个构建体系的时候,一开始觉得 CMake 比较接近事实标准了。同样,CMake 也正在尝试把手伸到依赖管理上面。CMake 的理念一开始起源于 makefile,其实是比较简单、干净的,一个包有 include_dir、lib_dir 等,然后就可以构建了。但我的观点还是,Moedern CMake 把这一切都搞复杂了,它尝试面向对象地解决依赖问题+构建问题。但是它在 include_dir、lib_dir 之上发明了很多新的概念,增加了学习成本,掩盖了底层细节——C++er 一般不喜欢被隐藏细节,你最好及解决问题也让我知道是怎么解决的。再加上 CMake 相对另类的语法以及看不懂的文档这两个 debuff,导致学习成本比起一般新事物高得多。所以,尽管它在市占率上可能ou 接近事实标准,我们还是把它当成一个普通的系统来看待,不给特殊待遇。何况,大家用 CMake 来构建的比例有多少、用来管理依赖的又有多少呢,说不清楚,我也没调查过。

C++ 领域,市面上是有一些的依赖管理系统的,但可能都没有形成大一统。我觉得可以按这几个角度去做分类:

  • 源代码依赖还是二进制依赖
  • 是否需要包仓库服务器
  • 是否与构建系统绑定
  • 依赖包跟系统还是跟项目
依赖管理系统 源代码依赖还是二进制依赖 是否需要包仓库服务器 是否与构建系统绑定 依赖包跟系统还是跟项目
git submodule
git subtree
源代码 跟项目
cmake 源代码 跟项目
vcpkg 二进制 否,但一般和 cmake 配合 跟系统
conan 二进制 否,但一般和 cmake 配合 跟项目
gclient 源代码 否,但 google 未做开放性适配 跟项目

见识有限,我知道的大概有这些,如果其他的大家可以补充,开阔开阔眼界。

然后怎么选呢?我想提出几条规则,然后做分析。

第一,要源代码依赖,不要二进制依赖。

因为 C++ 各平台编译方式不尽相同,即使同一平台,也可以有不同的编译器参数、宏定义等。同时,也不存在二进制兼容性。因此,二进制依赖会有很多问题。除非已选定特定平台特定参数,才能有效地实行二进制依赖。从通用性角度上讲,源代码依赖是合理的。

第二,不要自建仓库的。

首先,一般依赖系统想要自建仓库,形成生态,本来就非常难,需要由大厂牵头或者知名社区领军人物牵头。在 C++ 领域,牛人隐士颇多,一个人、一个组织或一家公司,想要一言九鼎进行宣传、号召,更难。

其次,自建仓库需要将每个包进行标准化。这是一项不可能完成的工作。很多代码的历史堪比计算机历史,尊重其原作者的编译方式是最兼容、风险最低的方式。

最后,从开发者角度来说,去每个软件的官网引用其代码是最安全、放心的做法。从某个依赖体系的中心化仓库去引用,总是会有担心。

从实际来看,即使现在生态最好的 vcpkg 和 conan,也只有一两千的包量,相比 npm、maven,实在是零头。

按这两条规则,排除了目前如日中天的 vcpkg 和 conan。剩下的里面,cmake 的 FetchContent 是和 cmake 强绑定的,如果都用 cmake 一条龙,那么选它。直接用 git submodule 或 subtree,也是能当依赖系统用的,只是可能没那么方便和直观,也不知道什么原因导致业界没这么用?gclient 其实是理念上最符合的,它没 cmake 那么晦涩、抽象,而是直截了当地配置什么包,从哪里下载,放到项目的哪里。但是 google 没有特意推广的意图,主要还是为 chrome 及其他周边项目服务。

所以呢,笔者按这个理念要自己写一个,只管从哪儿下载、放到本地哪里,把 gclient 的 runhook 也去掉,只有 sync。

起个名字,叫 srcdep,强调源代码依赖,项目地址为 https://github.com/Streamlet/srcdep

用法就是在项目跟目录建立一个 SRCDEP.yaml,内容为

DEPS:
path/to/local/directory: # 第一个包的目标目录
# GIT 依赖
# 需要配置 GET_REPO 和 GIT_TAG
GIT_REPO: url_of_git_repo
GIT_TAG: git_tag_or_branch_or_commit
path/to/another/directory: # 第二个包的目标目录
# 普通 URL 依赖
# 需要至少配置一个 URL
URL: package_url
# 如果 URL 不是一个正常的扩展名结尾,那么需要配一下 URL_FORMAT,以便知道怎么解压
URL_FORMAT: tar.gz
# 如果包解压出来是一个目录,但咱们需要把这个目录下面的文件直接丢到 path/to/another/directory
# 那么配置一下 ROOT_DIR,意思是包内的根目录名称,需要把这个目录视为包的根目录
ROOT_DIR: root_dir_in_archive
# 校验方式,支持 MD5、SHA1、SHA224、SHA256、SHA384、SHA512
URL_HASH:
SHA256: sha256_hash_of_the_package

然后用 python 实现,把 srcdep 的目录丢到 PATH 环境变量里,在项目里执行一把,就下载所有依赖包。

跟构建完全分离,构建可以走上一节的 gn+ninja。

这样,我们完成了 C++ 下快速开发小型组件和小型应用的基础设施的搭建。

C++ 编译依赖管理系统分析以及 srcdep 介绍的更多相关文章

  1. webpack模块依赖管理介绍

    http://webpack.github.io/docs/ webpack is a module bundler. 是一个模块管理器 webpack可以管理模块的依赖关系,并产生可以替代这些模块的 ...

  2. Java Gradle入门指南之依赖管理(添加依赖、仓库、版本冲突)

        开发任何软件,如何管理依赖是一道绕不过去的坎,软件开发过程中,我们往往会使用这样那样的第三方库,这个时候,一个好的依赖管理就显得尤为重要了.作为一个自动构建工作,Gradle对依赖管理有着很好 ...

  3. 用CocoaPods做iOS程序的依赖管理(转摘)

    转摘自:http://blog.devtang.com/blog/2014/05/25/use-cocoapod-to-manage-ios-lib-dependency/ 文档更新说明 2012-1 ...

  4. Gradle系列教程之依赖管理(转)

    转自Lippi-浮生志 :http://ezlippi.com/blog/2015/05/gradle-dependency-management.html 这一章我将介绍Gradle对依赖管理的强大 ...

  5. 用CocoaPods做iOS程序的依赖管理

    CocoaPods简介 每种语言发展到一个阶段,就会出现相应的依赖管理工具,例如Java语言的Maven,nodejs的npm.随着iOS开发者的增多,业界也出现了为iOS程序提供依赖管理的工具,它的 ...

  6. Gradle实战教程之依赖管理

    这是从我个人网站中复制过来的,原文地址:http://coolshell.info/blog/2015/05/gradle-dependency-management.html,转载请注明出处. 简要 ...

  7. iOS 用CocoaPods做iOS程序的依赖管理

    文档更新说明 2012-12-02 v1.0 初稿 2014-01-08 v1.1 增加设置 ruby 淘宝源相关内容 2014-05-25 v2.0 增加国内 spec 镜像.使用私有 pod.po ...

  8. Maven(六)之依赖管理

    前面讲了maven一些关于Maven的简单知识,今天我给大家分享一些Maven的依赖管理.我相信用过maven的人都知道,它很重要的功能就是通过依赖来添加jar包. 让我们领略一下Maven是怎么管理 ...

  9. 从初识Maven到使用Maven进行依赖管理和项目构建

    前些天就安装了Maven,以备自己以后整合项目用,尤其是我们的ssh,ssm项目.想必好多人在开始的时候并不清楚Maven是什么,它能够帮助我们干什么. 所以在学习Maven之前我们一定要知道它是什么 ...

  10. maven入门(8)maven的依赖管理

    我们项目中用到的jar包可以通过依赖的方式引入,构建项目的时候从Maven仓库下载即可. 1. 依赖配置    依赖可以声明如下: <project> ... <dependenci ...

随机推荐

  1. Qt Quick 用cmake怎么玩子项目

    以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」https://mp.weixin.qq.com/s/o-_aGqreuQda-ZmKktvxwA 以往在公司开发众多的项目中 ...

  2. SpringCloud整合分布式事务Seata 1.4.1 支持微服务全局异常拦截

    项目依赖 SpringBoot 2.5.5 SpringCloud 2020.0.4 Alibaba Spring Cloud 2021.1 Mybatis Plus 3.4.0 Seata 1.4. ...

  3. 【JavaSE】抽象类、接口

    接口的诞生 接口其实就是一种标准一种规范. 先从生活中的例子讲起,理解含义和概念后,再去理解程序会更容易理解一些. 生活中接口无处不在,比如著名的USB接口,大家可以试想一下,如果没有像USB这种统一 ...

  4. MySQL高可用集群MHA方案

    MySQL高可用集群MHA方案 爱奇艺在用的数据库高可用方案 MHA 是目前比较成熟及流行的 MySQL 高可用解决方案,很多互联网公司正是直接使用或者基于 MHA 的架构进行改造实现 MySQL 的 ...

  5. HTML躬行记(3)——WebRTC视频通话

    WebRTC 在创建点对点(P2P)的连接之前,会先通过信令服务器交换两端的 SDP 和 ICE Candidate,取两者的交集,决定最终的音视频参数.传输协议.NAT 打洞方式等信息. 在完成媒体 ...

  6. Istio Ambient Mesh七层服务治理图文详解

    摘要:本文主要集中剖析Ambient mesh七层服务治理相关内容. 本文分享自华为云社区<Istio Ambient Mesh七层服务治理图文详解>,作者:华为云云原生团队. 由于Amb ...

  7. 【深入浅出 Yarn 架构与实现】2-4 Yarn 基础库 - 状态机库

    当一个服务拥有太多处理逻辑时,会导致代码结构异常的混乱,很难分辨一段逻辑是在哪个阶段发挥作用的. 这时就可以引入状态机模型,帮助代码结构变得清晰. 一.状态机库概述 一)简介 状态机由一组状态组成: ...

  8. .NET刷算法

    BFS模板-宽度优先搜索(Breadth First Search) 1.模板 /// <summary> /// BFS遍历 /// </summary> /// <p ...

  9. cJson 学习笔记

    cJson 学习笔记 一.前言 思考这么一个问题:对于不同的设备如何进行数据交换?可以考虑使用轻量级别的 JSON 格式. 那么需要我们手写一个 JSON 解析器吗?这大可不必,因为已经有前辈提供了开 ...

  10. ubuntu 22.04安装多个gcc

    sudo apt install gcc-9 g++-9 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 - ...