跳到主要内容

理解 kmpkg 中的功能(Features)

功能(Features)的定义

功能(Features)代表一组可在安装时选择性添加到包或项目中的功能、行为及依赖项。

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

  • 累加性:启用某功能应新增包原本不具备的功能,而非禁用其他功能。
  • 非排他性:启用某功能不应阻止其他功能的安装。

功能不应用于定义互斥的功能集。例如,图形库不应通过功能选择互斥的图形后端(因无法同时安装所有后端)。

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

  • 新增依赖项(包括对同一包中其他功能的依赖)。
  • 启用现有依赖项的新功能。

可用功能集通过 "features" 字段定义。

示例1:多文件格式支持

例如,一个图像处理库可能通过依赖不同的库来支持多种图像格式:

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

默认功能(Default features)

默认功能是一组在顶层项目未显式要求禁用时,会自动激活的功能。其目的是确保无论项目的依赖关系图多么复杂和可定制,包都能提供最低水平的可用功能。

信息

默认功能并非用于表示“推荐配置”或“建议功能”。

例如,考虑一个支持10多种归档格式(包括一些非常冷门格式)的库 "extract-any"。由于所有格式都是可选的,若未选择任何格式,该库将无法使用(无法提取任何文件)。

默认功能确保用户只需在 kmpkg.json 中添加 "extract-any" 作为依赖,就能获得基线功能(例如自动包含 .zip.tar.gz 解压支持)。

示例2:默认功能的实际应用

当用户在 kmpkg.json 中添加 "extract-any" 而未指定功能时,默认功能(如 .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
}
]
}

此外,若使用 经典模式,可通过 core 功能禁用默认功能。例如,kmpkg install extract-any[core] 会安装不含任何默认功能的 extract-any[core] 会明确排除默认功能。

如需了解更多信息,请参阅 默认功能文档

依赖解析

在使用 kmpkg 时,依赖解析至关重要,尤其是处理具有相互依赖关系的功能时。以下通过图像处理库的场景说明:

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

当不同库依赖同一库的不同功能时,kmpkg 会整合所有必需的功能和依赖项,形成完整的安装计划。例如:

  • library-a 依赖 my-image-libpng 功能
  • library-b 依赖 my-image-libjpeg 功能

它们的清单文件如下:

{
"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"
]
}

当解析这些依赖时,kmpkg 会整合所有必需的功能,最终安装计划如下(包含 PNGJPEG 支持,排除 TIFF):

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

该机制确保 my-image-lib 的构建仅包含所需功能,优化构建体积和性能。

高级用法

示例3:单个仓库中的多个关联项目

当单个仓库包含多个独立可构建组件(如客户端和服务器应用,共享部分代码)时,开发者可能希望避免安装其他组件所需的庞大依赖项:

{
"name": "my-game",
"dependencies": ["grpc"],
"features": {
"client": { "description": "客户端游戏可执行文件", "dependencies": ["sdl2", "bullet3"]},
"server": { "description": "多人服务器可执行文件", "dependencies": ["proxygen"]},
"tests": { "description": "构建测试", "dependencies": ["gtest"] }
}
}

开发者可选择安装所需功能:

如需了解更多信息,请参阅: