包名称解析

vcpkg 先确定每个包的负责注册表(或覆盖),然后再联系网络。 这样做可以防止包依赖项混淆攻击,因为名称解析不依赖于任何外部状态。

名称解析算法步骤如下:

  • 如果在覆盖中找到名称,则使用该覆盖;否则
  • 如果存在与端口名称匹配的 "packages" 模式,则使用此注册表;否则
  • 如果默认注册表不是 null,则使用此注册表;否则
  • 无法将端口解析为注册表。

如果有多个 "packages" 模式与名称匹配,vcpkg 将如下所示优先设置:

  1. 通过 boost* 选择完全匹配 -- boost
  2. 通过 b* 选择最长的模式 -- boost*
  3. 第一个匹配 -- 声明最佳模式的第一个注册表已选择

示例 #1:包名称解析

vcpkg-configuration.json

{
  "registries": [
    {
      "kind": "git",
      "repository": "https://github.com/microsoft/vcpkg-docs",
      "reference": "vcpkg-registry",
      "baseline": "768f6a3ad9f9b6c4c2ff390137690cf26e3c3453",
      "packages": ["bei*"]
    },
    {
      "kind": "git",
      "repository": "https://github.com/vicroms/vcpkg-registry",
      "baseline": "dacf4de488094a384ca2c202b923ccc097956e0c",
      "packages": ["beicode", "bei*"]
    }
  ]
}

vcpkg.json

{
  "dependencies": [ 
    "beicode", 
    "beison",
    "fmt"
  ],
  "builtin-baseline": "7e7c62d863b1bf599c1d104b76cd8b74475844d4"
}

鉴于此配置,每个包名称解析为:

  • beicode:来自注册表https://github.com/vicroms/vcpkg-registry(在 beicode 上完全匹配)
  • beison:来自注册表 https://github.com/Microsoft/vcpkg-docsbeison 上的模式匹配,并在 "registries" 数组中首先声明)
  • fmt:来自默认注册表(无匹配项)

由于多个注册表声明 bei*,vcpkg 也会发出警告:

Found the following problems in configuration (path/to/vcpkg-configuration.json):
$ (a configuration object): warning: Package "bei*" is duplicated.
    First declared in:
        location: $.registries[0].packages[0]
        registry: https://github.com/microsoft/vcpkg-docs
    The following redeclarations will be ignored:
        location: $.registries[1].packages[1]
        registry: https://github.com/vicroms/vcpkg-registry

示例 #2:将多个模式分配给默认注册表

可以通过两种方式更改默认注册表。 第一种,通过定义 "default-registry"

{
  "default-registry": {
    "kind": "git",
    "repository": "https://github.com/Microsoft/vcpkg",
    "baseline": "e79c0d2b5d72eb3063cf32a1f7de1a9cf19930f3"
  }
}

第二种,通过将 "default-registry" 设置为 null,并在 "registries" 数组中使用 "*" 模式。

{
  "default-registry": null,
  "registries": [
    {
      "kind": "git",
      "repository": "https://github.com/Microsoft/vcpkg",
      "baseline": "e79c0d2b5d72eb3063cf32a1f7de1a9cf19930f3",
      "packages": ["*"]
    }
  ]
}

第二种形式的优势在于可以向包数组添加更多条目,而 "default-registry" 对象则完全不允许你定义包数组。 当需要确保包来自默认注册表,这种差异变得很重要。

假设有一个注册表可以提供 Qt 架构库。

vcpkg-configuration.json

{
  "default-registry": {
    "kind": "git",
    "repository": "https://github.com/Microsoft/vcpkg",
    "baseline": "7e7c62d863b1bf599c1d104b76cd8b74475844d4"
  },
  "registries": [
    {
      "kind": "git",
      "repository": "https://github.com/custom-qt/custom-qt-registry",
      "baseline": "adfc4de488094a384ca2c202b923ccc097956e0c",
      "packages": ["qt*"]
    }
  ]
}

以及以下项目依赖项:

vcpkg.json

{
  "dependencies": [ 
    "qt5", 
    "qt-advanced-docking-system", 
    "qtkeychain" 
  ]
}

"qt*" 模式匹配 vcpkg.json 中的所有端口名称。 但是有一个问题! 端口 qt-advanced-docking-systemqtkeychain 不是官方 Qt Framework 库的一部分,因为 vcpkg 将无法在自定义注册表中找到端口,安装将失败。

可以通过将这些包分配给默认注册表来修复此问题。 我们通过更改声明默认注册表的方式,并将 qt-advanced-docking-systemqtkeychain 添加到其 "packages" 数组来实现。

vcpkg-configuration.json

{
  "default-registry": null,
  "registries": [
    {
      "kind": "git",
      "repository": "https://github.com/Microsoft/vcpkg",
      "baseline": "e79c0d2b5d72eb3063cf32a1f7de1a9cf19930f3",
      "packages": ["*", "qt-advanced-docking-system", "qtkeychain"]
    },
    {
      "kind": "git",
      "repository": "https://github.com/custom-qt/custom-qt-registry",
      "baseline": "adfc4de488094a384ca2c202b923ccc097956e0c",
      "packages": ["qt*"]
    }
  ]
}

因为完全匹配项优先于模式匹配项,qt-advanced-docking-systemqtkeychain 会解析为默认注册表。

覆盖

覆盖是为 vcpkg 扩展更多端口和三联密码的一种方法,无需创建完整的注册表。 在执行任何注册表查找或版本控制之前,会考虑覆盖层,并替换任何内置的三联密码或端口。 有关详细信息,请参阅覆盖端口

按以下顺序评估覆盖设置:

  1. 按传递顺序从命令行 覆盖;然后
  2. 按顺序从vcpkg-configuration.json 覆盖;然后
  3. 按顺序从 VCPKG_OVERLAY_[PORTS|TRIPLETS] 环境变量覆盖。