如何处理依赖源版本问题
How to handle dependency source version issues
如果一个项目依赖于一些库,基本上有两种选择:
- 在众所周知的全局路径中找到库(如
/usr/src/linux-headers-4.13.0-1-amd64/
- 将源代码复制到项目文件夹中。
使用全球定位方法需要最少的 space 和时间(下载时间)。如果依赖项的版本控制良好(标记为 v3.1
、v3.1.1
等),则此选项效果很好。
如果我们的项目需要使用库的最新提交,版本控制不是一个选项。如果我们只是将最新的提交拉到众所周知的位置并让我们的项目使用该库,我们很可能在 6 个月后无法编译我们的项目,这是不可接受的。
如果我们将依赖项作为子项目添加到我们的项目中,我们将始终能够编译我们的项目。这是最安全的方法。问题是如果库是 100MB 左右,将源复制到项目文件夹只是浪费磁盘使用、下载时间等...
人们如何处理这个问题?
你不能吃蛋糕就吃:
要么你要依赖一个稳定的、版本化的库,然后引用它(无论它位于何处)
或者您将始终依赖 "latest and the greatest" - 然后引用该
的副本
磁盘 space 并不是真正的问题 - 显然你需要至少有一个你正在开发的机器上使用过的库的本地副本,如果它是 "proper versioned" 代码或 "head of trunk"。当它总是 "head of trunk" 时,您可能会使用一些版本控制系统,如 git 或 svn 来获取库,因此每当您更新本地副本时,您将只从 repo 中提取更改,不是 "full 100 MB".
但是,为了使您的构建可重现,对于源代码的每个版本,您应该对所有依赖项以及源代码进行版本控制。如果您使用的是第三方库,您可以
依靠供应商为您提供您在项目期间使用的版本,并期望他们在未来 10 年左右为您提供这些版本
或者,保留您自己使用的每个第三方库版本的副本(也可能将它们放在您自己的源代码存储库中)。这是我一直喜欢的专业发展方法,谁知道图书馆供应商下周、下个月、明年是否还在维护他的东西?
以下是您可以同时吃蛋糕的方法(参见量子物理学):
- 使用自己的分布式版本控制系统(git、hg、bazaar 等)在全球范围内维护您的依赖项(库)。 (见注释 1)
- 在项目文件夹中维护一个依赖版本数据库(一个文本文件),并在每次构建时更新它。 (格式:
MyLibrary commit-hash-or-version
)
项目将始终使用最新版本的依赖项。如果编译在某个时候失败(例如,当您在 3 年后尝试编译项目时),
- 去获取在上次成功构建点使用的依赖项的版本
- 在临时位置使用该散列创建依赖项的签出。
- 将临时位置指向构建过程中的依赖路径。
显然,这个 "return-to-successful-point" 过程可以轻松实现自动化。
Note 1: Dependencies are not meant to be only source codes, they might be simply some tools in binary format. In this case the dependency manager hook should invoke the tool with --version
parameter (or what is appropriate for that tool), get the version, append to the dependencies.txt
file. Obviously you should be prepared to be able to get the older version of the tool in case you'll need it at some point in the future.
如果一个项目依赖于一些库,基本上有两种选择:
- 在众所周知的全局路径中找到库(如
/usr/src/linux-headers-4.13.0-1-amd64/
- 将源代码复制到项目文件夹中。
使用全球定位方法需要最少的 space 和时间(下载时间)。如果依赖项的版本控制良好(标记为 v3.1
、v3.1.1
等),则此选项效果很好。
如果我们的项目需要使用库的最新提交,版本控制不是一个选项。如果我们只是将最新的提交拉到众所周知的位置并让我们的项目使用该库,我们很可能在 6 个月后无法编译我们的项目,这是不可接受的。
如果我们将依赖项作为子项目添加到我们的项目中,我们将始终能够编译我们的项目。这是最安全的方法。问题是如果库是 100MB 左右,将源复制到项目文件夹只是浪费磁盘使用、下载时间等...
人们如何处理这个问题?
你不能吃蛋糕就吃:
要么你要依赖一个稳定的、版本化的库,然后引用它(无论它位于何处)
或者您将始终依赖 "latest and the greatest" - 然后引用该
的副本
磁盘 space 并不是真正的问题 - 显然你需要至少有一个你正在开发的机器上使用过的库的本地副本,如果它是 "proper versioned" 代码或 "head of trunk"。当它总是 "head of trunk" 时,您可能会使用一些版本控制系统,如 git 或 svn 来获取库,因此每当您更新本地副本时,您将只从 repo 中提取更改,不是 "full 100 MB".
但是,为了使您的构建可重现,对于源代码的每个版本,您应该对所有依赖项以及源代码进行版本控制。如果您使用的是第三方库,您可以
依靠供应商为您提供您在项目期间使用的版本,并期望他们在未来 10 年左右为您提供这些版本
或者,保留您自己使用的每个第三方库版本的副本(也可能将它们放在您自己的源代码存储库中)。这是我一直喜欢的专业发展方法,谁知道图书馆供应商下周、下个月、明年是否还在维护他的东西?
以下是您可以同时吃蛋糕的方法(参见量子物理学):
- 使用自己的分布式版本控制系统(git、hg、bazaar 等)在全球范围内维护您的依赖项(库)。 (见注释 1)
- 在项目文件夹中维护一个依赖版本数据库(一个文本文件),并在每次构建时更新它。 (格式:
MyLibrary commit-hash-or-version
)
项目将始终使用最新版本的依赖项。如果编译在某个时候失败(例如,当您在 3 年后尝试编译项目时),
- 去获取在上次成功构建点使用的依赖项的版本
- 在临时位置使用该散列创建依赖项的签出。
- 将临时位置指向构建过程中的依赖路径。
显然,这个 "return-to-successful-point" 过程可以轻松实现自动化。
Note 1: Dependencies are not meant to be only source codes, they might be simply some tools in binary format. In this case the dependency manager hook should invoke the tool with
--version
parameter (or what is appropriate for that tool), get the version, append to thedependencies.txt
file. Obviously you should be prepared to be able to get the older version of the tool in case you'll need it at some point in the future.