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. 齐博x1如果把万能表单直接插入到内容中去

    很多时候,你创建了一个万能表单可能像下面这个情况,在文章中加一个链接叫别人点击填表,其实这个很不人性化,用户也容易忽略. 其实你完全可以像下面这样,把表单直接引用到文章中来.给用户更直观的感觉 那是如 ...

  2. 前端监控系列4 | SDK 体积与性能优化实践

    背景 字节各类业务拥有众多用户群,作为字节前端性能监控 SDK,自身若存在性能问题,则会影响到数以亿计的真实用户的体验.所以此类 SDK 自身的性能在设计之初,就必须达到一个非常极致的水准. 与此同时 ...

  3. Jquery中Trigger()方法

    1. $(selector).trigger(event,[param1,param2,...]) 方法触发被选元素标签的指定事件类型 为元素边赋值为true,并触发元素标签的change方法 $(' ...

  4. 现在入行Java真的还有出路吗?

    现在入行Java还来的及吗?未来该如何抉择? 最近有点迷茫了,互联网好像一夜之间进入了寒冬一样,到处都是就业难的样子,当然,不可否认的是,那些努力的大佬依旧是斩获多个offer,但是,窝就一个小镇做题 ...

  5. Codeforces Round #830 (Div. 2)D2. Balance (Hard version)(数据结构)

    题目链接 题目大意 维护一个集合的mex,每次有三种操作: '+' x:将数 x 插入集合中 '-' x:将数 x 移除集合 '?' k:询问满足mex的数是k的倍数 既集合中未出现的数中最小的数可以 ...

  6. Django开发汇总

    基本配置 # 设置数据库为使用的mysql DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'libr ...

  7. Electron是什么以及可以做什么

    新用户购买<Electron + Vue 3 桌面应用开发>,加小册专属微信群,参与群抽奖,送<深入浅出Electron>.<Electron实战>作者签名版. 1 ...

  8. 陪你去看 Lodash.js 起步

    lodash 起步(数组) Lodash 是一个较为流行的 JavaScript 的实用工具库. 在开发过程中如果能熟练使用一些工具库提供的方法,有利于提高开发效率. 笔者从 API 上入手,不分析其 ...

  9. Ant Design Pro:Layout 组件——嵌套布局

    在   BasicLayout.jsx   文件中修改 <ProLayout layout="topmenu" className="chenshuai2144&q ...

  10. css文字垂直展示的方法

    一.使用writing-mode(推荐使用) writing-mode:翻译过来是"写字 - 模式",文本在水平或垂直方向上如何排布 有以下几个属性值: horizontal-tb ...