我需要一个与特定语言或构建系统无关的依赖管理器.我已经研究过几种优秀的工具(Gradle,Bazel,Hunter,Biicode,柯南等),但没有一种能满足我的要求(见下文).我还使用了
Git Submodules和Mercurial Subrepos.
Daniel Pfeifer在2014年C会议上的presentation中详细描述了我的需求.总结了这种依赖工具的目标(讨论了链接视频的@ 18:55):
>不仅仅是包管理器
>支持预构建或源依赖
>可以在本地下载或查找 – 没有不必要的下载
>使用各种方法获取(即下载或VCS克隆等)
>与系统安装程序集成 – 可以检查是否安装了lib
>无需以任何方式调整源代码
>无需调整构建系统
>跨平台
我要补充的进一步要求或说明:
>适用于第三方和/或版本化依赖项,但也能够指定非版本化和/或共同开发的依赖项(可能由git / mercurial哈希或标记指定).
>提供一种机制来覆盖指定的提取行为,以使用我选择的某个备用依赖项版本.
>无需手动设置依赖项存储.我不反对中央依赖位置作为避免冗余或循环依赖的方法.但是,我们需要克隆repo并执行一些顶级构建脚本的简单性,该脚本调用依赖管理器并构建所有内容.
>尽管要求我不必修改我的构建系统,但显然一些顶级构建必须使用依赖管理器,然后将这些依赖项提供给各个构建.该要求意味着各个构建不应该知道依赖管理器.例如,如果对C包使用CMake,我不需要修改其CMakeLists.txt来进行特殊的函数调用来定位依赖项.相反,顶级构建管理器应该调用依赖项管理器来检索依赖项,然后提供CMake可以以传统方式使用的参数(即find_package或add_subdirectory).换句话说,我应该总是可以选择手动执行顶级构建和依赖管理器的工作,并且单个构建不应该知道差异.
很高兴有:
>一种在事后查询依赖关系管理器以查找依赖关系放置位置的方法.这将允许我创建VCS挂钩以自动更新共同开发的源repo依赖项的依赖关系元数据中的散列. (像子模块或subrepos那样).
最佳答案 在彻底搜索了可用的技术之后,与各种语言的包管理器(即npm)进行比较,甚至运行我自己的依赖管理器工具,我已经选择了柯南.深入柯南之后,我发现它开箱即可满足我的大多数要求并且易于扩展.
在研究柯南之前,我看到BitBake是我所寻找的模型.但是,它只是Linux,并且非常适合嵌入式Linux发行版.柯南具有与bb基本相同的配方功能,并且是真正的跨平台
以下是我的要求和我在柯南发现的内容:
- Not just a package manager
- Supports pre-built or source dependencies
柯南支持经典版本或开发依赖项,并允许您打包源代码.如果注册表中存在具有特定配置/设置的二进制文件(或者“Conan”中的“存储库”),则将从源构建二进制文件.
- Can download or find locally – no unnecessary downloads
- Integrated with the system installer – can check if lib is installed
柯南将本地注册表维护为缓存.因此,碰巧共享依赖项的独立项目不需要重做昂贵的下载和构建.
柯南不会阻止您查找系统包而不是声明的依赖项.如果编写构建脚本以传递前缀路径,则可以动态更改各个依赖项的路径.
- Fetches using a variety of methods (i.e. download, or VCS clones, etc.)
实现配方的源函数可以完全控制如何获取依赖项.柯南支持下载/克隆源的配方,或者可以“快照”源,将其与配方本身打包在一起.
- No need to adapt source code in any way
- No need to adapt the build system
柯南支持各种生成器,使您所选择的构建系统可以使用依赖项.来自特定构建系统的不可知论是柯南的真正胜利,并最终使得来自Bazel,Buckaroo等等的依赖管理变得繁琐.
Cross-platform
Python. Check.Suitable for third-party and/or versioned dependencies, but also capable of specifying non-versioned and/or co-developed dependencies (probably specified by a git/mercurial hash or tag).
在构建时考虑了semver,但可以使用任何字符串标识符作为版本.此外,还有用户和通道作为包版本的命名空间.
- Provides a mechanism to override the specified fetching behavior to use some alternate dependency version of my choosing.
您可以通过不在install命令中包含它来阻止获取特定依赖项.或者,您可以修改或覆盖生成的前缀信息以指向磁盘上的其他位置.
- No need to manually set up a dependency store. I’m not opposed to a central dependency location as a way to avoid redundant or circular dependencies. However, we need the simplicity of cloning a repo and executing some top-level build script that invokes the dependency manager and builds everything.
Despite the requirement that I should not have to modify my build system, obviously some top-level build must wield the dependency manager and then feed those dependencies to the individual builds. The requirement means that the individual builds should not be aware of the dependency manager. For example, if using CMake for a C++ package, I should not need to modify its CMakeLists.txt to make special functional calls to locate dependencies. Rather, the top-level build manager should invoke the dependency manager to retrieve the dependencies and then provide arguments CMake can consume in traditional ways (i.e find_package or add_subdirectory). In other words, I should always have the option of manually doing the work of the top-level build and dependency manager and the individual build should not know the difference.
柯南在本地注册表中缓存依赖项.这是无缝的.您将在Conan的文档中看到的规范模式是在构建脚本中添加一些Conan特定的调用,但这可以避免.再一次,如果您将构建脚本编写到使用者前缀路径和/或输入参数,您可以传入信息而不使用Conan.我认为柯南CMake发生器可以使用一些工作来使它更优雅.作为后备,柯南让我编写自己的发电机.
- A way to interrogate the dependency manager after-the-fact to find where a dependency was placed. This would allow me to create VCS hooks to automatically update the hash in dependency metadata of co-developed source repo dependencies. (Like submodules or subrepos do).
发电机指向这些位置.凭借Python的全部功能,您可以根据自己的内容自定义此功能.
目前共同开发的依赖项目对我来说是最大的问号.这意味着,我不知道柯南是否有开箱即用的东西可以让跟踪提交变得容易,但我相信钩子会在那里添加这个自定义.
我在柯南找到的其他东西:
>柯南提供了在开发过程中下载或构建我需要的工具链的功能.它使用Python virtualenv来轻松启用/禁用这些自定义环境,而不会污染我的系统安装.