你正在开发一个依赖其他库的c++项目吗?你是否厌倦了用“胶水脚本”和git子模块维护定制的包管理工作流?那么,你应该考虑试用包管理器。也许你已经关注vcpkg有一段时间了,它看起来是你的团队的完美解决方案,但有一个问题:您的所有依赖项都是开源的!您的公司也有希望每个人都使用的内部库。
vcpkg 可以与非开源依赖项一起使用吗?
是的。在此之前,你的最佳选择是创建overlay ports或者fork vcpkg ports的分支。但是这还有改进的空间。现在,我们高兴地宣布一项实验性的特性来管理你期望的任何代码库。不管它们是内部使用的、开源的还是你自己fork的开源项目分支。在这篇文章中,我们将深入研究registries, 我们新的实验性功能。我们希望您尝试这个功能,给我们反馈,并帮助我们使它最好的功能,它可以!
registries入门
前面我们讨论了为什么需要registries, 现在我们来讨论怎么使用。假设我们是North Wind Traders的开发人员,我们公司订阅了Github企业版。当然,基于你公司或者你个人的实际情况,你可以继续使用你目前的工作流程。这篇文章的目标是建立一个最为常见的git registry。
1. 创建一个新的registry
公司的Github地址是https://github.com/northwindtraders,可以用例创建registry。我们将在https://github.com/northwindtraders/vcpkg-registry创建我们的registry,因为这是一个很好的名称,你可以在那里跟踪分支。
创建好registry后,我们需要做一些事来向里面添加我们需要的包,在本例中是我们内部的JSON和Unicode库。
- 首先,我们将创建一个空的基线,这是registry的最低需求。
- 然后,我们要添加库需要构建的文件,并确保他们是可工作的。
- 最后,我们通过把库添加到版本库中,并写明在git库中的位置来把库添加进registry中。
2. 创建一个空的registry基线
克隆(空的)代码仓库,在根目录下添加versions/baseline.json文件,包含下面的内容:
{
"default": {}
}
3. 创建一个vcpkg port
现在,我们开始为我们两个库中的第一个(Unicode库beicode)创建一个port条目.如果你曾经编写过port,那么你将知道如何执行此操作,但是对于那些还没有写过port的人,让我们还是进行一遍操作。
我们首先创建一个存放port的文件夹。根据vcpkg central registry的标准,我们称这个文件夹为ports。因为我们使用稳定的git标识符来指定目录,所以我们不需要将它放在特定的位置,但最好遵循习惯。在这个目录中,创建beicode的port目录,其中放入两个空文件:portfile.cmake 和 vcpkg.json。
现在,registry目录应该看起来像下面这样:
ports/
beicode/
portfile.cmake
vcpkg.json
versions/
baseline.json
现在,我们来填写port。首先,由于beicode的Github仓库已经有了vcpkg.json,将里面的manifest信息拷贝到刚刚创建的vcpkg.json文件中:
{
"name" : "beicode",
"version" : "1.0.0",
"description" : "A simple utf-8 based unicode decoding and encoding library",
"homepage" : "https://github.com/northwindtraders/beicode"
}
4. 使用overlays测试新的vcpkg port
让我们通过尝试安装来确保它工作;我们还没有使用registries,使用预先存在的overlay-ports功能来测试:
> vcpkg install beicode --overlay-ports=vcpkg-registry/ports/beicode
我们应该得到一个错误:“文件夹/include为空或者不存在”。既然我们还什么都没做,这个错误是正常的。现在,让我们来填写port!因为我们的port是一个简单的CMake库,我们可以创建一个非常简单的portifle.cmake文件:
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO northwindtraders/beicode
REF 19a1f95c2f56a27ced90227b5e2754a602a08e69
SHA512 7b2bb7acb2a8ff07bff59cfa27247a7b2cced03828919cd65cc0c8cf1f724f5f1e947ed6992dcdbc913fb470694a52613d1861eaaadbf8903e94eb9cdfe4d000
HEAD_REF main
)
vcpkg_configure_cmake(
SOURCE_PATH "${SOURCE_PATH}"
PREFER_NINJA
)
vcpkg_install_cmake()
vcpkg_fixup_cmake_targets()
file(REMOVE_RECURES "${CURRENT_PACKAGES_DIR}/debug/include")
file(
INSTALL "${SOURCE_PATH}?LICENSE"
DESTINATION "${CURENT_PACKAGES_DIR}/share/${PORT}"
RENAME copyright)
如果我们再次运行
> vcpkg install beicode --overlay-ports=vcpkg-registry/ports/beicode
我们会看到它已经成功安装了。我们已经为我们的registry写了第一个port,现在剩下要做的就是把port添加到registry的版本集中。
5. 为registry中的库指定版本
每一个port的版本信息都存放在它自己的文件中:versions/[first character]-/[portname].json。例如,fmt的版本信息存放在versions/f-/fmt.json文件中;zlib的版本信息存放在versions/z-/zlib.json文件中。所以,为beicode创建文件versions/b-/beicode.json:
{
"versions" : [
{
"versions" : "1.0.0",
"git_tree" : ""
}
]
}
在*versions/vaseline.json"文件中添加如下信息:
{
"default" : {
"deicode" : { "baseline" : "1.0.0", "port-version" : 0 }
}
}
现在,让我们来看看”git-tree"字段中应该是什么内容。进行一次beicode的git提交(但是不push):
> git add ports/beicode
> git commit -m "[beicode] new port"
然后,获取该目录的树标识:
> git rev-parse HEAD:ports/beicode
你应该得到一个类似于7fb5482270b093d40ab8ac31db89da4f880f01ba
的一串信息。把它放到beicode.json文件中“git-tree”字段处,并提交新文件:
> git add versions
> git commit --amend --no-edit
我们应该完成了!我们必须执行这个稍微复杂的步骤的原因是,我们可以准确地抓取我们想要的版本的文件;其他版本将存在于存储库的历史中,因此总是可以签出。
6. 在C++项目中使用vcpkg registry 中的库
完成此操作后,让我们尝试在示例代码库中使用新registry中的库。在registry外部创建一个目录并切换到该目录。创建一个依赖于 beicode 的 vcpkg.json:
{
"name": "test",
"version": "0",
"dependencies": [
"fmt",
"beicode"
]
}
以及将注册表设置为 git registry的 vcpkg-configuration.json:
{
"registries": [
{
"kind": "git",
"repository": "[full path to]/vcpkg-registry",
"packages": [ "beicode", "beison" ]
}
]
}
并尝试安装 vcpkg:
> vcpkg install --feature-flags=registries,manifests
如果它有效,那么您已经准备好将注册表推向上游!您可以通过将 vcpkg-configuration.json 文件中的“respository”字段替换为实际的上游存储库 URL,使用实际的远程注册表重试。
vcpkg如何从registries中获取库
您会注意到beicode和beison取自我们创建的registry;这是因为我们在vcpkg-configuration.json中明确地设置了它们的来源。因为我们没有说fmt应该来自哪里,所以它只是来自默认registry,在本例中是vcpkg本身附带的registry表。registries永远不会传递;如果在vcpkg-configuration.json中去掉beicode,这将无法工作,因为beicode不存在在默认registry中。如果希望用自己的副本覆盖fmt,可以将其添加到registry,然后将其添加到packages字段。
代码包beison将会是一样的,只是名字不同而已。您可以自己尝试一下,然后看看您的代码与上游代码是否有任何不同。
本文来自
《Registries: Bring your own libraries to vcpkg - C++ Team Blog (microsoft.com)》