最低版本要求
vcpkg 使用最少的选择方法进行版本控制,灵感来自 Go 使用的版本控制,但在某些方面进行了修改:
- 总是从全新安装开始,以避免需要进行升级或降级操作。
- 通过引入基线来允许不受约束的依赖项。
但是,最小选择原则保持不变。 给定一组约束后,vcpkg 将使用可以满足所有约束的包的“最早”可能版本。
使用最低版本方法具有以下优点:
- 这是可预测的和易于理解的。
- 用户控制何时进行升级,就像在新版本发布时一样,不会自动执行升级。
- 避免使用 SAT 求解器。
若要提供示例,请考虑以下包图:
(A 1.0) -> (B 1.0)
(A 1.1) -> (B 1.0)
-> (C 3.0)
(A 1.2) -> (B 2.0)
-> (C 3.0)
(C 2.0)
以及以下清单:
{
"name": "example",
"version": "1.0.0",
"dependencies": [
{ "name": "A", "version>=": "1.1" },
{ "name": "C", "version>=": "2.0" }
],
"builtin-baseline": "<some git commit with A's baseline at 1.0>"
}
在考虑可传递依赖项后,我们具有以下一组约束:
- A >= 1.1
- B >= 1.0
- C >= 3.0
- C >= 2.0
由于 vcpkg 必须满足所有约束,安装包集将变为:
-
A 1.1,即使A 1.2存在,也没有比1.1更高的约束,因此 vcpkg 选择了可能的最低版本。 -
B 1.0,由A 1.1传递依赖。 -
C 3.0被A 1.1添加的传递约束升级,以满足版本约束。
约束解析
给定具有一组版本控制依赖项的清单,vcpkg 将尝试计算满足所有约束的包安装计划。
版本约束具有以下风格:
- 声明的约束:在顶级清单中使用
version>=显式声明的约束。 -
基线约束:由
builtin-baseline..隐式添加的约束。 - 传递约束:由您的依赖项的依赖项间接添加的约束。
-
重写约束:使用
overrides声明在顶级清单中重写的约束。
若要计算安装计划,vcpkg 大致遵循以下步骤:
- 将所有顶级约束添加到计划。
- 以递归方式向计划添加可传递约束。
- 每次向计划添加新包时,也将新包的基线约束添加到计划中。
- 每次添加约束时:
- 如果存在针对该软件包的重写选项
- 选择替代中的版本。
- 否则:
- 如果没有选择先前的版本。
- 选择满足约束的最低版本。
- 如果选择了以前的版本:
- 如果新约束的版本控制方案与以前选择的版本不匹配:
- 添加版本冲突。
- 如果约束的版本与以前选择的版本不相上下。 例如,将“version-string: apple”与“version-string: orange”进行比较:
- 添加版本冲突。
- 如果约束版本高于以前选择的版本:
- 选择最高版本。
- 否则:
- 保留上一个选择。
- 如果新约束的版本控制方案与以前选择的版本不匹配:
- 如果没有选择先前的版本。
- 查看计划:
- 如果没有冲突
- 安装所选包
- 否则:
- 向用户报告冲突
- 如果没有冲突
获取端口版本
虽然包版本的概念一直存在于 vcpkg 中,但版本约束的概念尚未出现。
随着版本控制约束的引入,包现在可能依赖于与本地可用的端口版本不匹配的端口版本。 这引发了问题,因为 vcpkg 需要知道如何获取所请求版本的端口文件。
为了解决此问题,引入了一组新的元数据文件。 这些文件位于 versions/ vcpkg 存储库根级别的目录中。
该 versions/ 目录将包含注册表中可用的每个端口的 JSON 文件。 每个文件将列出可用于包的所有版本,并包含一个 Git 树式对象,以便 vcpkg 可以通过签出该对象来获取相应版本的 portfiles。
示例: zlib.json
{
"versions": [
{
"git-tree": "2dfc991c739ab9f2605c2ad91a58a7982eb15687",
"version-string": "1.2.11",
"port-version": 9
},
...
{
"git-tree": "a516e5ee220c8250f21821077d0e3dd517f02631",
"version-string": "1.2.10",
"port-version": 0
},
{
"git-tree": "3309ec82cd96d752ff890c441cb20ef49b52bf94",
"version-string": "1.2.8",
"port-version": 0
}
]
}
对于每个端口,其相应的版本文件应位于 versions/{first letter of port name}-/{port name}.json。 例如,zlib 的版本文件将位于 versions/z-/zlib.json. 除了端口版本文件外,当前基线文件位于 versions/baseline.json。