概念:功能

功能

功能表示可在安装时选择性地添加到包或项目的功能、行为和依赖项集。

根据设计,功能应遵循以下原则:

  • 累加:启用功能时,应提供包中缺少的新功能,而无需禁用任何其他功能。
  • 非独占:启用功能不应阻止安装其他功能。

不应将功能用于定义替代功能集。 例如,图形库不应使用功能在独占图形后端之间进行选择,因为无法同时安装所有这些后端。

功能可能会对包依赖项产生以下影响:

  • 添加新的依赖项,包括同一包中其他功能的依赖项。
  • 对现有依赖项启用新功能。

可用的功能集由 "features" 字段进行定义。

示例 1:多种文件格式

例如,图像操作库可能通过依赖于不同的其他库集来支持几种不同的图像类型。

{
  "name": "my-image-lib",
  "version": "0.1",
  "features": {
    "png": { "description": "Support PNG files", "dependencies": ["libpng"]},
    "jpeg": { "description": "Support JPEG files", "dependencies": ["libjpeg-turbo"]},
    "tiff": { "description": "Support TIFF files", "dependencies": ["libtiff"]},
  }
}

默认功能

如果顶级项目没有明确请求版本,则默认功能是一组自动激活的功能。 默认功能旨在确保实现最低程度的功能,不管某个项目的依赖项关系图变得多么复杂,自定义程度多高。

注意

默认功能不用于对“策展”或“建议”进行建模。

例如,考虑支持 10 多种不同存档格式的库,包括一些相当模糊的库 "extract-any"。 由于它们都是可选的,如果未选择任何库,则库不起作用:则无法提取任何文件。

默认功能可确保仅将 "extract-any" 添加到其 vcpkg.json 中的依赖项列表的用户将获得基线级别的功能;例如,自动选择 .zip.tar.gz 解压缩器。

示例 2:默认功能实际运用

当用户在不指定功能的情况下将 "extract-any" 添加到其 vcpkg.json 时,会自动包括默认功能(例如支持 .zip.tar.gz 格式),从而确保基本功能。

{
  "name": "my-application",
  "version": "0.15.2",
  "dependencies": [
    "extract-any"
  ]
}

如果用户明确想要禁用默认功能,可通过将 "default-features": false 添加到依赖项来实现:

{
  "name": "my-application",
  "version": "0.15.2",
  "dependencies": [
    {
      "name": "extract-any",
      "default-features": false
    }
  ]
}

或者,如果在经典模式下使用 vcpkg,可以通过 core 功能禁用默认功能。 例如,vcpkg install extract-any[core] 会在不带任何默认功能的情况下安装 extract-any,因为 [core] 会显式将其排除。

有关详细信息,请查阅默认功能文章

依赖项解析

使用 vcpkg 时,依赖项解析起着重要作用,尤其是在处理具有相互依赖项的功能时。 为了说明,请考虑以下涉及图像操作库的方案:

{
  "name": "my-image-lib",
  "version": "0.1",
  "features": {
    "png": { "description": "Support PNG files", "dependencies": ["libpng"]},
    "jpeg": { "description": "Support JPEG files", "dependencies": ["libjpeg-turbo"]},
    "tiff": { "description": "Support TIFF files", "dependencies": ["libtiff"]},
  }
}

在不同的库依赖于通用库的各种功能的方案中,vcpkg 可确保考虑所有必需的功能和依赖项。 例如,如果 library-a 需要 png 功能,并且 library-b 需要 my-image-lib 中的 jpeg 功能,则依赖项关系图如下所示:

{
  "name": "library-a",
  "version": "1",
  "dependencies": [{"name": "my-image-lib", "features": ["png"]}]
}
{
  "name": "library-b",
  "version": "1",
  "dependencies": [{"name": "my-image-lib", "features": ["jpeg"]}]
}
{
  "name": "project-using-a-and-b",
  "version": "1",
  "dependencies": [
    "library-a",
    "library-b"
  ]
}

解析这些依赖项后,vcpkg 会将所有必要的功能和依赖项组合在一起,形成全面的安装计划。 在此示例中,一个同时取决于 library-alibrary-b 的项目将产生同时包含 my-image-lib 中的 PNGJPEG 但不包括 TIFF 的安装计划:

libjpeg-turbo[core]
libpng[core]
library-a[core]
library-b[core]
my-image-lib[core,png,jpeg]

此机制可确保 my-image-lib 生成针对所需功能进行了优化,同时提供 PNGJPEG 支持,同时排除不必要的 TIFF 支持。

高级用法

当单个存储库包含多个单独的可生成组件(例如具有一些共享代码的客户端和服务器应用程序)时,每个部分的开发人员可能希望避免安装其他部分所需的昂贵依赖项。

{
  "name": "my-game",
  "dependencies": ["grpc"],
  "features": {
    "client": { "description": "Client Game Executable", "dependencies": ["sdl2", "bullet3"]},
    "server": { "description": "Multiplayer Server Executable", "dependencies": ["proxygen"]},
    "tests": { "description": "Build tests", "dependencies": ["gtest"] }
  }
}

然后,各个开发人员可以选择要安装的功能:

有关详细信息,请参阅以下部分: