6

我需要一个不依赖于特定语言或构建系统的依赖管理器。我研究了几个优秀的工具(Gradle、Bazel、Hunter、Biicode、Conan 等),但没有一个能满足我的要求(见下文)。我还使用了 Git 子模块和 Mercurial Subrepos。

Daniel Pfeifer 在 Meeting C++ 2014 的演讲中很好地描述了我的需求。总结这个依赖工具的目标(在链接视频的 @18:55 讨论):

  • 不仅仅是一个管理器
  • 支持预构建或源依赖项
  • 可以在本地下载或查找 - 没有不必要的下载
  • 使用多种方法获取(即下载或 VCS 克隆等)
  • 与系统安装程序集成 - 可以检查是否安装了 lib
  • 无需以任何方式调整源代码
  • 无需调整构建系统
  • 跨平台

我要补充的进一步要求或说明:

  • 适用于第三方和/或版本化依赖项,但也能够指定非版本化和/或共同开发的依赖项(可能由 git/mercurial 哈希或标记指定)。
  • 提供一种机制来覆盖指定的获取行为以使用我选择的一些替代依赖版本。
  • 无需手动设置依赖存储。我不反对将中央依赖位置作为避免冗余或循环依赖的一种方式。但是,我们需要简单地克隆一个 repo 并执行一些顶级构建脚本,该脚本调用依赖管理器并构建所有内容。
  • 尽管要求我不必修改我的构建系统,但显然某些顶级构建必须使用依赖管理器,然后将这些依赖提供给各个构建。该要求意味着各个构建不应该知道依赖管理器。例如,如果将 CMake 用于 C++ 包,我应该不需要修改它的 CMakeLists.txt 以使其特殊用于定位依赖项的函数调用。相反,顶级构建管理器应该调用依赖管理器来检索依赖关系,然后提供 CMake 可以以传统方式使用的参数(即 find_package 或 add_subdirectory)。换句话说,我应该始终可以选择手动执行顶级构建和依赖管理器的工作,而单个构建不应该知道其中的区别。

很高兴有:

  • 一种事后询问依赖管理器以查找依赖放置位置的方法。这将允许我创建 VCS 挂钩以自动更新共同开发的源代码库依赖项的依赖元数据中的哈希。(就像子模块或子存储库一样)。
4

1 回答 1

5

在彻底搜索了可用的技术,与各种语言(即 npm)的包管理器进行比较,甚至在我自己的依赖管理器工具上运行之后,我选择了 Conan。在深入了解柯南之后,我发现它开箱即用地满足了我的大部分要求,并且易于扩展。

在研究柯南之前,我将 BitBake 视为我正在寻找的模型。但是,它仅适用于 linux,并且主要面向嵌入式 linux 发行版。Conan 具有与 bb 基本相同的配方功能,并且是真正的跨平台

以下是我的要求以及我对柯南的发现:

  • 不仅仅是一个包管理器
  • 支持预构建或源依赖项

Conan 支持经典的发布或开发依赖项,还允许您打包源代码。如果注册表(或柯南所说的“存储库”)中不存在具有特定配置/设置的二进制文件,则将从源代码构建二进制文件。

  • 可以在本地下载或查找 - 没有不必要的下载
  • 与系统安装程序集成 - 可以检查是否安装了 lib

柯南维护一个本地注册表作为缓存。因此,碰巧共享依赖项的独立项目不需要重做昂贵的下载和构建。

Conan 不会阻止您查找系统包而不是声明的依赖项。如果您编写构建脚本以传递前缀路径,则可以动态更改各个依赖项的路径。

  • 使用多种方法获取(即下载或 VCS 克隆等)

实现source配方的功能可以完全控制如何获取依赖项。柯南支持下载/克隆源或可以“快照”源的配方,将其与配方本身打包。

  • 无需以任何方式调整源代码
  • 无需调整构建系统

Conan 支持各种生成器,以使您选择的构建系统可以使用依赖项。来自特定构建系统的不可知论是柯南的真正胜利,最终使 Bazel、Buckaroo 等之类的依赖管理变得繁琐。

  • 跨平台的 Python。查看。

  • 适用于第三方和/或版本化依赖项,但也能够指定非版本化和/或共同开发的依赖项(可能由 git/mercurial 哈希或标记指定)。

构建时考虑了 semver,但可以使用任何字符串标识符作为版本。此外,还具有userchannel充当包版本的命名空间。

  • 提供一种机制来覆盖指定的获取行为以使用我选择的一些替代依赖版本。

您可以通过不在install命令中包含特定依赖项来防止获取特定依赖项。或者您可以修改或覆盖生成的前缀信息以指向磁盘上的不同位置。

  • 无需手动设置依赖存储。我不反对将中央依赖位置作为避免冗余或循环依赖的一种方式。但是,我们需要简单地克隆一个 repo 并执行一些顶级构建脚本,该脚本调用依赖管理器并构建所有内容。尽管要求我不必修改我的构建系统,但显然某些顶级构建必须使用依赖管理器,然后将这些依赖提供给各个构建。该要求意味着各个构建不应该知道依赖管理器。例如,如果将 CMake 用于 C++ 包,我不需要修改它的 CMakeLists.txt 来进行特殊的函数调用来定位依赖项。相当,顶级构建管理器应该调用依赖管理器来检索依赖关系,然后提供 CMake 可以以传统方式使用的参数(即 find_package 或 add_subdirectory)。换句话说,我应该始终可以选择手动执行顶级构建和依赖管理器的工作,而单个构建不应该知道其中的区别。

Conan 将依赖项缓存在本地注册表中。这是无缝的。您将在柯南的文档中看到的规范模式是在您的构建脚本中添加一些柯南特定的调用,但这是可以避免的。再一次,如果您将构建脚本编写到消费者前缀路径和/或输入参数,您可以传递信息而根本不使用柯南。我认为柯南 CMake 生成器可以使用一些工作来使其更加优雅。作为后备方案,柯南让我编写自己的生成器。

  • 一种事后询问依赖管理器以查找依赖放置位置的方法。这将允许我创建 VCS 挂钩以自动更新共同开发的源代码库依赖项的依赖元数据中的哈希。(就像子模块或子存储库一样)。

生成器指向这些位置。借助 Python 的全部功能,您可以随心所欲地对其进行自定义。

目前共同开发依赖项目是我最大的问号。意思是,我不知道柯南是否有一些开箱即用的东西可以使跟踪提交变得容易,但我相信钩子在那里可以添加这种定制。

我在柯南中发现的其他内容:

  • Conan 提供了下载或构建我在开发过程中需要的工具链的能力。它使用 Python virtualenv 来轻松启用/禁用这些自定义环境,而不会污染我的系统安装。
于 2017-08-06T22:54:42.527 回答