理解 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-lib的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"
]
}
当解析这些依赖时,kmpkg 会整合所有必需的功能,最终安装计划如下(包含 PNG 和 JPEG 支持,排除 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"] }
}
}
开发者可选择安装所需功能:
- 在 安装命令行 中传递
--x-feature=参数 - 使用 CMake 集成 时,在
project()命令前设置KMPKG_MANIFEST_FEATURES - 使用 MSBuild 集成 时,通过
KmpkgAdditionalInstallOptions传递--x-feature=
如需了解更多信息,请参阅: