特别感谢
感谢维克多·罗梅罗对本文的贡献。
今天,我们很高兴地宣布vcpkg的一个新特性:包版本控制。开发人员已经等待这个新功能很久了,今天它终于到来了。该功能可以实现软件包特定依赖版本的安装,同时控制已安装的现有版本。要使用这个新特性,您需要在仓库中创建一个vcpkg.json的清单文件,该文件用于声明各种包的依赖关系。请注意,以命令行模式安装的库尚不支持版本控制。版本控制功能是完全可选的,也就是说,您可以选择不指定库的版本,这样vcpkg将从基线目录中为您选择最合适的兼容版本。
目前这个功能是实验性的,大家试一试,体验一下。
关于新功能:包版本控制
在过去的一年里,我们一直在努力实现开发者想要的新特性,让vcpkg可以广泛应用于各种工作场景中。清单和二进制文件缓存是两个新特性。我们在之前的文章中已经介绍过了。从那以后,开发人员在他们的项目中使用它们。
今天,我们再一次宣布一个被大众所称的新特性:包版本控制。有了这个新特性,开发人员可以做以下事情:
对依赖项声明最小版本约束。
>冻结指定版本的依赖项。
>使用基线轻松更新所有声明的依赖关系。
>获得独立于当前vcpkg的可复制的构建版本的ports注册表状态。
我们开始吧。
首先,您需要在环境变量中打开“版本”特性标志。有以下几种方法:
>在Windows 10中,可以设置VCPKG_FEATURE_FLAGS环境变量,如下图所示:
>通过在命令行上设置VCPKG_FEATURE_FLAGS变量:
$ env:VCPKG _ FEATURE _ FLAGS = " versions " VCPKG安装
>通过在命令行向vcpkg传递新的功能标志:
vcpkg–功能标志=“版本”安装
在下面的示例中,我们将使用Visual Studio Code创建一个简单的CMake项目,该项目将自动读取vcpkg的清单文件并安装其所需的依赖包。在Visual Studio中,您也可以这样做。如果您需要了解更多关于如何在Visual Studio中使用vcpkg和清单的信息,请查看我们之前关于vcpkg的介绍性文章。
第一个例子:简单的版本控制
如下图所示,通过在vcpkg.json中编写以下语句来创建一个文件夹:
当您使用清单文件时,vcpkg有一个新的版本声明属性可用。在以前的版本中,您只能使用属性“version-string”来声明项目的版本。现在版本控制的方法变了,vcpkg可以感知到新的版本控制结构,如下图所示:
首先,选择的版本结构会影响vcpkg包搜索的顺序规则。
其次,我们使用属性“version>=”来声明最小版本约束。请注意,我们还添加了一个对zlib的依赖,声明没有特定的版本约束。
最后,我们声明了“内置基线”,它的值是vcpkg仓库中的一个代码提交的SHA哈希值。
在上例中,vcpkg会找到“b60f 003 cf5 Fe 8613d 029 f 49 f 835 c 8929 a 66 EB 61”对应的提交版本,然后找到当时最新的fmt版本和zlib版本,如下:
> fmt 7.1.3
> zlib 1.2.11#9
上面列出的包集是在项目所依赖的基线版本中定义的。当需要解决包版本冲突时,基线版本会添加最低版本约束信息。
下面是一个简单的源文件,演示了如何测试是否安装了依赖项:
要在CMake项目中使用vcpkg清单文件,需要将find_package和target_link_libraries添加到CMakeLists.txt文件中,以定位所有依赖项。无论您是否使用像vcpkg这样的包管理器,您都可以使用这两个函数,这样您就可以在项目的构建中包含所需的依赖项。
如果您使用的是Visual Studio Code,下面的配置演示了如何将CMake项目指向vcpkg CMake工具链文件。必须为任何使用vcpkg的CMake项目设置此文件。此外,其他集成开发环境或编辑器可能有不同的方式来配置CMake工具链文件。
接下来,使用Visual Studio代码中的“CMake: Configure”指令生成CMake缓存,如下图所示:
上图显示了使用CMake命令行创建CMake缓存时的信息输出。在Visual Studio代码中,如果安装了CMake Tools扩展,则可以通过执行“CMake: Configure”指令来生成缓存。
如果您注意到路径中的“/build trees/version/versions/”,您就可以理解新的版本控制功能已经在工作了。Vcpkg检查仓库中的包装版本。
最后,当我们执行测试程序时,我们将得到以下输出:
fmt版本是70103
zlib版本是1.2.11
第二个例子:修复旧版本
因为基线版本决定了所有包的基本版本信息,并且当包低于基线版本时需要进行一些显式的约束检查,所以我们需要另一种机制来降级版本以通过基线检查。
vcpkg提供的新机制是override。
当我们在包上声明重写时,vcpkg将忽略所有其他版本约束和直接在清单或依赖版本中声明的版本。简单地说,重写将迫使vcpkg使用一个精确声明的版本。
首先,请修改您的清单文件,为fmt添加一个覆盖,并强制vcpkg使用6.0.0版本,如下图所示:
接下来,请删除您的项目生成文件夹,生成CMake缓存并再次执行生成:
最后,执行我们的测试程序,我们将观察到以下输出:
fmt版本为60000
zlib版本是1.2.11
vcpkg中的版本控制是如何工作的?
下图描述了四个包的发布时间表:FMT、zlib、Boost和Azure Core C++库。
vcpkg内部的版本系统包括以下几个部分:
基线
要使用版本控制,您需要将基线设置为特定的vcpkg提交版本。通过选择基线,您可以在发布计划中选择版本快照。通过设置基线,您可以为所有依赖项设置最低版本。
在上图中,我们有7.1.0版的FMT,v9版的zlib v 1 . 2 . 11修订版,1.74.0版的Boost和2020年9月发布的Azure Core C++库。
使用基线的一个优点是,同一时期的版本很可能相互兼容。主vcpkg注册表将同时构建它包含的所有库,以确保整个库目录的整体兼容性。
约束条件
约束允许您逐个包地指定最低版本,而不是为所有包的最低版本设置基线。
约束只允许您升级版本,而不允许升级基线版本。如上所述,基线为所有包设置了最低版本限制,因此如果您试图添加一个低于基线的约束,该约束将被升级。
关于约束的一个重要注意事项是,当基线和替代不存在时,它们是可传递的。图中的依赖关系可以表达自己的约束,版本解析算法会考虑它们。
但是,如果真的需要将版本设置在基准之下呢?如何在不降低基准的情况下做到这一点?对于这些情况,可以使用替代方案。
无视
重写会强制vcpkg使用特定版本,同时忽略所有其他约束。这允许用户解决某些情况,例如:
>降级版本低于基线。
>对传递依赖项强制升级/降级版本。
>解决不同软件包之间的版本冲突。
在图中所示的场景中,我们拥有基线、约束和替换的所有知识。我们可以看到,使用所有四个包的项目的版本解析将导致:
FMT:版本7.1.2,由约束指定。
Zlib:端口修订版2的版本1.2.11。
提升:1.74版本,默认由基线设置。
azure-core-CPP:2020-09-01版本。
版本和自定义端口
最后,我们将讨论覆盖端口如何与版本控制解析交互。
答案是:他们根本不互动。更详细地说,当您为端口提供覆盖时,vcpkg将始终使用覆盖端口,而不管其中包含的版本如何。
原因有二:
与覆盖端口的现有行为一致
覆盖端口没有足够的信息来支持vcpkg的版本控制功能。
摘要
希望大哥的包经理越来越好。
最后的
微软Visual C++团队的博客是我最喜欢的博客之一,里面包含了很多关于Visual C++的知识和最新的开发进展。如果你还对Visual C++这种古老的技术感兴趣,可以经常去看看。
本文来源于:“通过版本支持控制您的VC PKG依赖关系”