版本控制入门

将版本与清单配合使用

让我们首先创建一个简单的 CMake 项目,该项目依赖于 fmtzlib

使用以下文件创建文件夹:

vcpkg.json

{
    "name": "versions-test",
    "version": "1.0.0",
    "dependencies": [
        {
            "name": "fmt",
            "version>=": "7.1.3#1"
        }, 
        "zlib"
    ],
    "builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc"
}

main.cpp

#include <fmt/core.h>
#include <zlib.h>

int main()
{
    fmt::print("fmt version is {}\n"
               "zlib version is {}\n", 
               FMT_VERSION, ZLIB_VERSION);
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.18)

project(versionstest CXX)

add_executable(main main.cpp)

find_package(ZLIB REQUIRED)
find_package(fmt CONFIG REQUIRED)
target_link_libraries(main PRIVATE ZLIB::ZLIB fmt::fmt)

现在,我们使用 CMake 生成并运行项目:

  1. 为项目创建生成目录。

    PS D:\versions-test> mkdir build
    PS D:\versions-test> cd build
    
  2. 配置 CMake。

    PS D:\versions-test\build> cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake ..
    -- Running vcpkg install
    Detecting compiler hash for triplet x86-windows...
    The following packages will be built and installed:
        fmt[core]:x64-windows -> 7.1.3#1 -- D:\Work\viromer\vcpkg\buildtrees\versioning\versions\fmt\4f8427eb0bd40da1856d4e67bde39a4fda689d72
        vcpkg-cmake[core]:x64-windows -> 2021-02-26 -- D:\Work\viromer\vcpkg\buildtrees\versioning\versions\vcpkg-cmake\51896aa8073adb5c8450daa423d03eedf0dfc61f
        vcpkg-cmake-config[core]:x64-windows -> 2021-02-26 -- D:\Work\viromer\vcpkg\buildtrees\versioning\versions\vcpkg-cmake-config\d255b3d566a8861dcc99a958240463e678528066
        zlib[core]:x64-windows -> 1.2.11#9 -- D:\Work\viromer\vcpkg\buildtrees\versioning\versions\zlib\827111046e37c98153d9d82bb6fa4183b6d728e4
    ...
    
  3. 生成项目。

    PS D:\versions-test\build> cmake --build .
    [2/2] Linking CXX executable main.exe
    
  4. 运行它!

    PS D:\versions-test\build> ./main.exe
    fmt version is 70103
    zlib version is 1.2.11
    

查看输出:

fmt[core]:x86-windows -> 7.1.3#1 -- D:\vcpkg\buildtrees\versioning\versions\fmt\4f8427eb0bd40da1856d4e67bde39a4fda689d72
...
zlib[core]:x86-windows -> 1.2.11#9 -- D:\vcpkg\buildtrees\versioning\versions\zlib\827111046e37c98153d9d82bb6fa4183b6d728e4

vcpkg 在 ports/中不使用端口文件,而是签出 buildtrees/versioning/versions/中每个版本的文件。 在经典模式下运行 vcpkg 时,仍使用 ports/ 中的文件。

注意

配置 CMake 时,vcpkg 的输出仅在使用 CMake 版本 3.18 或更高版本时才可用。 如果使用较旧的 CMake,可以改为检查生成目录中的 vcpkg-manifest-install.log 文件。

阅读我们的 清单公告博客文章,了解如何将清单与 MSBuild 配合使用。

清单更改

如果在注意到有一些新的 JSON 属性之前使用了清单。 让我们回顾一下这些更改:

version

{
    "name": "versions-test",
    "version": "1.0.0"
}

这是项目的版本声明。 以前,只能使用 version-string 属性声明项目的版本。 现在版本控制已经出现,vcpkg 已了解一些新的版本控制方案。

版本方案 描述
version 点分隔的数值:1.0.0.5
version-semver 符合 语义版本1.2.01.2.0-rc
version-date YYYY-MM-DD 格式的日期:2021-01-01
version-string 任意字符串:vistacandy

version>=

{
    "dependencies": [
        { "name": "fmt", "version>=": "7.1.3" },
        "zlib"
    ]
}

此属性用于表示最低版本约束,仅允许作为 "dependencies" 声明的一部分。 在我们的示例中,我们对 fmt的版本 7.1.3#1 设置显式约束。

如果传递依赖项需要较新版本,则允许 vcpkg 升级此约束。 例如,如果 zlib 声明对 fmt 版本 7.1.4 的依赖项,则 vcpkg 将改为安装 7.1.4

vcpkg 使用最低版本方法,在我们的示例中,即使发布 fmt 版本 8.0.0,vcpkg 仍会安装版本 7.1.3#1,因为这是满足约束的最低版本。 此方法的优点是,在更新 vcpkg 时,你不会获得意外的依赖项升级,并且只要使用同一清单,就可以获得可重现的生成(在版本方面)。

如果要升级依赖项,可以提升最低版本约束或使用较新的基线。

builtin-baseline

{ "builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc" }

此字段声明所有端口的版本控制基线。 设置基线是启用版本控制所必需的,否则你将在 ports/ 目录中获取当前版本。 可以运行“git rev-parse HEAD”来获取 vcpkg 的当前提交,并将其设置为内置基线。 有关详细信息,请参阅 "builtin-baseline" 文档

在我们的示例中,我们不声明 zlib的版本约束;而是从基线获取版本。 在内部,vcpkg 将在提交 3426db05b996481ca31e95fff3734cf23e0f51bc 中查找了解 zlib 版本是当时的最新版本(在本例中为 1.2.11#9)。

在版本解析期间,基线版本被视为最低版本约束。 如果声明低于基线版本的显式约束,则显式约束将升级到基线版本。

例如,如果我们修改了如下所示的依赖项:

{ "dependencies": [
    {
        "name": "fmt",
        "version>=": "7.1.3#1"
    },
    {
        "name": "zlib",
        "version>=": "1.2.11#7"
    }
] }

注意

1.2.11#7 表示版本 1.2.11,端口版本 7

由于基线为 1.2.11#9zlib 引入了最低版本约束,并且更高版本确实满足 1.2.11#7的最低版本约束,因此允许 vcpkg 对其进行升级。

基线也是一次升级多个版本的便捷机制,例如,如果希望依赖于多个 boost 库,则设置 baseline 比在每个包上声明版本约束更方便。

但是,如果要固定早于基线的版本,该怎么办?

overrides

由于基线为所有包建立版本基础,并且显式约束在低于基线时升级,因此我们需要另一种机制来降级基线版本。

vcpkg 为该方案提供的机制 overrides。 在包上声明替代时,vcpkg 将忽略在清单中直接声明或从可传递依赖项声明的所有其他版本约束。 简言之,overrides 将强制 vcpkg 使用声明的确切版本句点。

让我们再次修改示例,这次强制 vcpkg 使用 fmt的版本 6.0.0

{
    "name": "versions-test",
    "version": "1.0.0",
    "dependencies": [
        {
            "name": "fmt",
            "version>=": "7.1.3#1"
        },
        {
            "name": "zlib",
            "version>=": "1.2.11#7"
        }
    ],
    "builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc",
    "overrides": [
        {
            "name": "fmt",
            "version": "6.0.0"
        }
    ]
}

重新生成项目:

PS D:\versions-test\build> rm ./CMakeCache.txt
PS D:\versions-test\build> rm -r ./vcpkg_installed
PS D:\versions-test\build> cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake ..
-- Running vcpkg install
Detecting compiler hash for triplet x86-windows...
The following packages will be built and installed:
    fmt[core]:x86-windows -> 6.0.0 -- D:\vcpkg\buildtrees\versioning\versions\fmt\d99b6a35e1406ba6b6e09d719bebd086f83ed5f3
    zlib[core]:x86-windows -> 1.2.11#9 -- D:\vcpkg\buildtrees\versioning\versions\zlib\827111046e37c98153d9d82bb6fa4183b6d728e4
...
PS D:\versions-test\build> cmake --build .
[2/2] Linking CXX executable main.exe

然后运行它!

PS D:\versions-test\build> .\main.exe
fmt version is 60000
zlib version is 1.2.11

请注意 fmt 现在在版本 6.0.0 就像我们想要的一样。

版本和自定义端口

最后讨论的是覆盖端口如何与版本控制解析交互。 答案是:他们不是。

更详细地介绍一下,当你为端口提供覆盖时,vcpkg 将始终使用覆盖端口,而无需考虑包含的版本。 原因有两倍:(1)它与完全屏蔽现有端口的现有覆盖端口行为一致,并且(2)覆盖端口不提供足够的信息来为 vcpkg 的版本控制功能提供支持。

如果想要具有灵活的端口自定义以及版本控制,应考虑 创建自己的自定义注册表

进一步阅读

如果你有兴趣深入了解版本控制的工作原理的详细信息,建议阅读我们的 版本控制参考版本控制概念