RFC-0100:商品元数据 | |
---|---|
状态 | 已接受 |
区域 |
|
说明 | 产品元数据的规范化表示 |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021-04-30 |
审核日期(年-月-日) | 2021-06-02 |
摘要
Fuchsia 软件开发套件 (SDK) 目前提供所谓的设备配置元数据(本文档中简称“元数据”),其架构在 //build/sdk/meta/device_profile.json
中定义。元数据用于描述可安装在设备上的系统映像和软件包。我们发现该架构不完整,需要进行现代化改造。此外,SDK 之外的工具现在也需要元数据,这使得元数据变得更加重要。
此 RFC 为此类信息引入了一种新架构,作为平台和工具之间的协定,并介绍了日后更新该架构的过程。
设计初衷
目前,元数据随 SDK 一起提供。它目前包含设备名称、该设备的文本说明以及用户可以从中下载图片和软件包信息的 URI。我们发现,这些元数据难以保持最新状态且不完整,因此无法使用。
工具最终依赖于关于映像和软件包的非官方惯例,或可能会更改的硬编码假设(例如用于下载的 URI 结构)。因此,当这些惯例发生变化时,这些工具很容易被破坏。
我们希望解决这些问题。我们将为元数据指定一个正式的架构,以便工具可以使用它。
我们分发既完整又易于使用的元数据时,SDK 用户能够选择要将哪个映像刷写到设备或使用模拟器启动,而无需 Fuchsia 的基础架构或 SDK 团队的大力协助。对于如何向用户显示商品相关信息,SDK 开发者将获得单一可信来源。工具开发者将针对如何使用这些信息制定明确合同。
易于更新
目前,元数据在 SDK 生成过程中经过硬编码,每当我们发布新图片时,都需要手动更新。这使得添加、重命名或移除元数据非常繁琐且容易出错。这些信息经常过时,或者更糟糕的是,根本没有添加这些信息。
在实践中,由于 SDK 使用者无法依赖 SDK 附带的元数据的准确性,因此他们会将软件包和映像的位置以及其他脆弱的实现相关信息硬编码到工具中。例如,除了对网址进行硬编码之外,外部模拟器启动还依赖于系统映像中存在未记录的 images.json
文件。
此提案为我们的元数据提供了一个新架构,我们希望外部用户依赖于此架构。这将激励我们及时更新该页面。
完整性
现有设备元数据缺少关键详细信息。例如,用于刷写设备的工具需要一系列分区名称,以及写入这些分区的文件名。目前,我们尚未正式规定这一点,因此我们分发的内容与执行刷写的工具之间没有任何合同。因此,很难提供稳定性/兼容性保证。
架构不完整与更新元数据的难度相结合,问题就会更加复杂。例如,假设某个模拟器工具想要确保启动的模拟器与用户想要运行的映像具有相同的架构。在不尝试启动映像的情况下,该工具如何知道特定位置的任何映像是否与特定架构兼容?使用更新后的架构后,我们可以使用一组元数据来描述图片的架构及其位置。然后,该工具就可以为给定图片选择正确的架构。
此提案将概述元数据的初始架构,并提供更新的后续路径,以确保元数据保持相关性。
设计
元数据,我们将采取以下措施:
- 为元数据定义新的架构。
- 定义更新该架构的过程。
- 在构建过程中生成符合该架构的元数据,并在树中使用该元数据。
- 在 SDK 版本中分发符合该架构的元数据,并在树外使用该元数据。
- 提供用于使用元数据进行刷写和模拟工作流的标准工具和库。
请注意,虽然我们在此处定义了初始架构,但我们将允许通过 API 委员会审核进行演变,而无需额外的 RFC。
定义
在本文档中,我们使用以下定义:
- 架构是对元数据组织方式的正式说明。
- 元数据是给定架构的具体实例化。
- 工件是指任何具体的文件或数据,通常在元数据中通过 URI 引用。
- 清单是包含工件列表的元数据。
- 映像是刷写实体设备或启动模拟器所需的工件集合。
- 软件包是 Fuchsia 中软件分发的单元,通常打包为 Fuchsia 归档 (FAR) 文件。
- 产品是用于创建映像和软件包的 build 配置。
- 产品软件包是一系列映像和软件包,它们是产品 build 的输出。
- 目标(设备)是用于运行产品的实体或虚拟 Fuchsia 设备。
我们将使用 JSON 来表示元数据。架构采用 json-schema.org 上定义的草稿 7 格式表示。
Schemata
本部分详细介绍了我们将对架构做出的初始要求和初始更改。
对初始架构的要求
- 元数据必须具有唯一名称或 ID。
- 元数据必须包含直观易懂的说明。
- 元数据架构必须受版本控制。
- 元数据必须指定目标设备的硬件特性。其中必须至少包含:
- 目标 CPU 架构,目前为 arm64 或 x64。
- 元数据必须指定一个或多个商品套装,每个商品套装都必须包含:
- 一个具有唯一性的名称。
- 直观易懂的说明。
- 映像包。
- 软件包套装。
- 元数据可以包含其他商品元数据(以键值对的形式),旨在协助用户选择所需商品。此类元数据的示例包括 build 类型(用户 build 与 eng build)、启动类型(正常启动与被终止启动)。
- 映像或软件包软件包必须:
架构演变
架构的未来发展方向可能有很多。例如:
- 实体硬件元数据可能包括设备硬件功能,例如是否存在屏幕、键盘或指控设备。
- 虚拟硬件元数据可以指定足以预配模拟器的虚拟设备特性。
为此,架构采用了版本控制机制。版本是一个字符串,每当添加或移除架构的元素时都会更新。工具可能会定位到多个不同版本的架构,或者用户可能需要使用旧版工具来使用旧版架构。
为了简化版本之间的转换,我们提出了一种灵活的解析和版本控制方案。我们引入了一个带版本号的信封,以简化 JSON 的解析。解析工具可以读取版本字段,同时忽略 JSON 文档的其余部分。这样,该工具就可以为每个受支持的架构版本选择正确的解析器。
我们建议使用随机生成的 8 位十六进制数字为每个架构文件单独设置版本。此编号在所有现有架构文件中都必须是唯一的。为防止发生冲突,建议实现构建时冲突检测,以防止意外提交重复资源。
由于架构可以通过 $ref
工具包含其他架构,因此我们提议将架构版本附加到架构文件名中。这不仅会消除 //build/sdk/meta/common.json
等常见文件的多个版本之间的歧义,还会触发引荐来源架构的版本重新计算。
每项不兼容的架构更改(例如添加或移除必填字段)都会触发版本重新计算。
我们允许通过 API 审核流程更改架构。对架构进行的更改属于开发者功能领域。
实现
架构本身的实现主要涉及将架构添加到 fuchsia.git 并确保其通过 API 审核。除此之外,还有两个问题:在哪里生成元数据?在哪里使用元数据?
设备元数据最初将按以下方式生成:
- 作为
fuchsia.git
中 Fuchsia build 的一部分; - 作为发布映像的一部分,供树外使用;以及
- 作为 SDK 发布的一部分。
它也可能会在其他位置生成,尤其是对于在 SDK 版本之外发布的映像和软件包。
设备元数据主要将由 ffx
工具使用,该工具将用其刷写设备和启动模拟器。由于我们将随 SDK 一起发布此架构,因此 Fuchsia 树之外的工具也可能会使用遵循此架构的元数据。
采用这种方法后,所有刷写和模拟工作流(无论是树内还是树外使用)都将使用设备元数据进行规范。
这两项工作都需要超出本 RFC 范围的设计。
通用架构
我们将按如下方式扩展 common.json 架构定义。无需考虑向后不兼容性,因为这不是一个不兼容的更改。为了简洁起见,下面省略了 common.json 中的现有定义。
为简洁起见,我们省略了文件的原始内容,并使用 ...
表示省略的内容。
/** build/sdk/meta/common.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "http://fuchsia.com/schemas/sdk/common.json",
"definitions": {
...,
"envelope": {
"description": "A versioned envelope.",
"type": "object",
"properties": {
"version": {"$ref": "#/definitions/version"},
"data": {
"description": "The payload."
}
},
"required": [
"version",
"data"
],
"additionalProperties": false
},
"versioned_sdk_element": {
"type": "object",
"allOf": [
{"$ref": "#/definitions/envelope"},
{
"type": "object",
"properties": {
"data": {
"oneOf": [
{"$ref": "#/definitions/sdk_element"}
]
}
}
}
]
},
"version": {
"description": "An opaque version string. The string may include any characters. Tools must not attempt to draw any conclusions about inter version compatibility other than the version 'X' manifest complies with the version 'X' of the schema and is therefore parsable by the version 'X' parser. There are no guarantees, for example, a parser for version 'B' may be able to parse a JSON document versioned 'A'.",
"type": "string",
"minLength": 1
},
}
}
请注意,由于此架构定义了我们使用的架构的版本,因此无法轻松更改。工具必须读取符合此架构的文件,才能理解封装的 JSON。
设备
由于设备上可能会安装多个映像,因此我们将设备硬件规范提取到自己的定义中。设备硬件规范有以下两种用途:
- 它介绍了运行映像所需的最低硬件要求。
- 指定为了运行映像而创建的虚拟(模拟)设备。
我们为实体设备和虚拟设备引入了两个新的版本化 SDK 元素。
体质
目前,我们只关心实体设备的 CPU 架构。我们会在未来的架构版本中添加其他硬件属性。为了提供完整示例,下面的架构定义将信封架构与 sdk_element
架构相结合1。
/** build/sdk/meta/physical_device-c906d79c.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "http://fuchsia.com/schemas/sdk/physical_device-c906d79c.json",
"description": "A physical device specification.",
"type": "object",
"allOf": [
{"$ref": "common.json#/definitions/envelope"},
{
"type": "object",
"properties": {
"data": {
"allOf": [
{"$ref": "common.json#/definitions/sdk_element"},
{
"properties": {
"type": {
"allOf": [
{"$ref": "common.json#/definitions/type"},
{"enum": ["physical_device"]}
]
}
}
},
{"$ref": "hardware-f9928aa4391e2ae3644ce712074a1ef7.json#/definitions/requirements"}
]
}
}
}
]
}
物理设备要求架构
借助此架构,我们可以表示设备硬件要求。这样,工具就可以确保设备硬件与我们将用于预配的工件相匹配。目前仅介绍 CPU 架构。
/** build/sdk/meta/hardware-c0a116ca.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"requirements": {
"properties": {
"hardware": {
"additionalProperties": false,
"properties": {
"cpu": {
"additionalProperties": false,
"properties": {
"arch": {
"oneOf": [
{"$ref": "common.json#/definitions/target_arch"}
]
}
},
"required": ["arch"],
"type": "object"
}
},
"required": ["cpu"],
"type": "object"
}
},
"required": ["hardware"],
"type": "object"
},
},
"description": "Hardware requirements for running a product image.",
"id": "http://fuchsia.com/schemas/sdk/hardware-c0a116ca.json"
}
虚拟
根据虚拟设备规范,我们可以选择适当的产品软件包来启动模拟器。在未来的修订版中,我们将进一步开发该架构,以便配置模拟器。例如,以下架构定义使用了新定义的 versioned_sdk_element
架构。
/** build/sdk/meta/virtual_device-8a8e2ba9.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "http://fuchsia.com/schemas/sdk/virtual_device-8a8e2ba9.json",
"description": "A virtual device specification for launching emulators.",
"type": "object",
"allOf": [
{"$ref": "common.json#/definitions/versioned_sdk_element"},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"type": {
"allOf": [
{"$ref": "common.json#/definitions/type"},
{"enum": ["virtual_device"]}
]
},
"description": {"type": "string"},
"virtual": {"$ref": "virtual_hardware-4c5d1a5d.json#/definitions/spec"}
},
"required": ["virtual"]
}
}
}
]
}
虚拟设备要求架构
虚拟硬件规范用于在启动模拟器时选择适当的产品软件包。
/** build/sdk/meta/virtual_hardware-4c5d1a5d.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "http://fuchsia.com/schemas/sdk/virtual_hardware-4c5d1a5d.json",
"description": "A virtual device specification for launching emulators.",
"definitions": {
"spec": {
"emu": {
"type": "object",
"properties": {
"cpu": {
"type": "object",
"properties": {
"arch": {
"oneOf": [
{"$ref": "common.json#/definitions/target_arch"}
]
}
},
"required": ["arch"],
"additionalProperties": false
}
},
"required": ["cpu"],
"additionalProperties": false
}
},
"required": ["emu"]
}
}
}
产品套装
映像和软件包软件包提供对设备上安装的软件工件的访问权限。
/** build/sdk/meta/product_bundle-514c2856.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "http://fuchsia.com/schemas/sdk/product_bundle-514c2856.json",
"description": "Artifacts required to boot and run software on a device.",
"type": "object",
"allOf": [
{"$ref": "common.json#/definitions/versioned_sdk_element"},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"type": {
"allOf": [
{"$ref": "common.json#/definitions/type"},
{"enum": ["product_bundle"]}
]
},
"description": {
"description": "A human readable description of the product bundle.",
"type": "string"
},
"device_refs": {
"description": "A list of physical or virtual device names this product can run on.",
"type": "array",
"minItems": 1,
"items": {
"type": "string",
"minLength": 1
}
},
"metadata": {
"description": "A list of key-value pairs describing product dimensions. Tools must not rely on the presence or absence of certain keys. Tools may display them to the human user in order to assist them in selecting a desired image or log them for the sake of analytics. Typical metadata keys are: build_info_board, build_info_product, is_debug.",
"$ref": "common.json#/definitions/key_value_list"
},
"manifests": {
"description": "Manifests describing how to boot the product on a device.",
"flash": {"$ref": "flash_manifest-c85dbd8e.json#/definitions/manifest"},
"emu": {"$ref": "emu_manifest-b0708439.json#/definitions/manifest"}
},
"images": {
"description": "A list of system image bundles. Each image bundle must be equivalent to all others. I.e., all image bundle URIs are effectively mirrors of each other. Their formats may vary. Pick an entry that best suits your needs.",
"type": "array",
"minItems": 1,
"items": {"$ref": "#/definitions/image_bundle"}
},
"packages": {
"description": "A list of package bundles. Each package bundle must be equivalent to all otherwise. I.e., all package bundle URIs are effectively mirrors of each other. Their formats may vary. Pick an entry that best suits your needs.",
"type": "array",
"minItems": 1,
"items": {"$ref": "#/definitions/package_bundle"}
}
},
"required": ["device_refs", "manifests", "images", "packages"]
}
}
}
],
"definitions": {
"image_bundle": {
"description": "A set of artifacts necessary to provision a physical or virtual device",
"type": "object",
"properties": {
"base_uri": {
"description": "A base URI for accessing artifacts in the bundle.",
"$ref": "#/definitions/bundle_uri"
},
"format": {
"description": "Bundle format: files - a directory layout; tgz - a gzipped tarball. In case of the 'files' format, the base base path points to a directory. The manifest paths is relative to the directory. To get a full path append a path inside the manifest to base_uri. In case of the 'tgz' format, the base path points to the archive. The manifest path is relative within the archive."
"enum": [
"files",
"tgz"
]
}
},
"required": [
"base_uri",
"format"
],
"additionalProperties": false
},
"package_bundle": {
"description": "A set of artifacts necessary to run a physical or virtual device",
"type": "object",
"properties": {
"repo_uri": {
"description": "A package repository URI. This may be an archive or a directory.",
"$ref": "#/definitions/bundle_uri"
},
"format": {
"description": "Repository format: files - a directory layout; tgz - a gzipped tarball.",
"enum" : [
"files",
"tgz"
]
},
"blob_uri": {
"description": "An optional blob repository URI. If omitted, it is assumed to be <repo_uri>/blobs. If repo_uri refers to a gzipped tarball, ./blobs directory is expected to be found inside the tarball.",
"$ref": "#/definitions/bundle_uri"
}
},
"required": [
"repo_uri",
"format"
],
"additionalProperties": false
},
"bundle_uri": {
"description": "Allowed system image and package bundle URIs.",
"type": "string",
"format": "uri",
"pattern": "^(?:http|https|gs|file):\/\/"
}
}
}
Flash 架构
基于闪存架构的清单描述了刷写设备所需的映像工件。清单与 build 生成的现有 flash.json 匹配。Flash 元数据将嵌入到商品包 SDK 元素中。
/** build/sdk/meta/flash_manifest-c85dbd8e.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "http://fuchsia.com/schemas/sdk/flash_manifest-c85dbd8e.json",
"description": "A manifest that describes how to flash a device.",
"type": "object",
"properties": {
"manifest": {"$ref": "#/definitions/manifest"}
},
"required": ["manifest"],
"additionalProperties": false,
"definitions": {
"manifest": {
"description": "A named list of partitions and OEM files necessary to flash a device.",
"type": "object",
"properties": {
"hw_revision" : {
"description": "A board name used to verify whether the device can be flashed using this manifest.",
"type": "string"
},
"products": {
"description": "A list of product specifications that can be flashed onto the device.",
"type": "array",
"items": {"$ref": "#/definitions/product"},
"minItems": 1
}
},
"required": ["hw_revision", "products"],
"additionalProperties": false
},
"product": {
"description": "A named product specification.",
"type": "object",
"properties": {
"name": {
"description": "A unique name of this manifest.",
"type": "string"
},
"partitions": {
"description": "A list of partition names and file names corresponding to the partitions.",
"$ref": "common.json#/definitions/key_value_list"
},
"bootloader_partitions": {
"description": "A list of partition names and file names corresponding to the partitions.",
"$ref": "common.json#/definitions/key_value_list"
},
"oem_files": {
"description": "A list of OEM command and file names corresponding to the command.",
"$ref": "common.json#/definitions/key_value_list"
}
},
"required": ["name", "partitions"],
"additionalProperties": false
}
}
}
模拟器架构
模拟器架构指定了在模拟器上启动产品所需的映像工件。
/** build/sdk/meta/emu_manifest-b0708439.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "http://fuchsia.com/schemas/sdk/emu_manifest-b0708439.json",
"definitions": {
"manifest": {
"description": "A manifest that describes how to boot an emulator.",
"type": "object",
"properties": {
"kernel": {
"description": "A path to the kernel image file. The path is relative to the image bundle base.",
"type": "string",
"minLength": 1
},
"initial_ramdisk": {
"description": "A path to the initial ramdisk, the kernel ZBI. The path is relative to the image bundle base.",
"type": "string",
"minLength": 1
},
"disk_images": {
"description": "A list of one or more disk image paths to FVM images. Each path is relative to the image bundle base.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
},
"minItems": 1
}
},
"required": ["kernel", "initial_ramdisk", "disk_images"],
"additionalProperties": false
}
}
}
其他常见定义
以下是常见定义的额外补充。如需了解与版本相关的新增内容,请参阅“common.json”部分。为了简洁起见,下面省略了 common.json 中的现有定义。
/** build/sdk/meta/common.json */
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "http://fuchsia.com/schemas/sdk/common.json",
"definitions": {
...,
"key_value": {
"description": "A key-value pair.",
"type": "array",
"items": [
{"type": "string"},
{"type": ["number", "string"]}
],
"minItems": 2,
"additionalItems": false
},
"key_value_list": {
"description": "A list of key-value pairs.",
"type": "array",
"items": {"$ref": "#/definitions/key_value"}
}
示例
设备
物理设备
设备硬件规格示例如下。
{
"version": "c906d79c",
"data": {
"type": "physical_device",
"name": "generic-x64",
"description": "A generic x64 device.",
"hardware": {
"cpu": {
"arch": "x64"
}
}
}
}
产品套装
实体设备上的终端
这是可在通用 x64 设备上启动的通用终端产品示例,其中包含两个归档镜像,分别对应于可通过基于 gs
和 https
的 URI 访问的映像和软件包。
{
"version": "514c2856",
"data": {
"type": "product_bundle",
"name": "generic-x64",
"description": "A terminal x64 product.",
"device_refs": ["generic-x64"],
"metadata": [
["build-type", "release"],
["product", "terminal"]
],
"manifests": {
"flash": {
"hw_revision": "x64",
"products" : [
{
"bootloader_partitions": [],
"name": "fuchsia",
"oem_files": [],
"partitions": [
["", "fuchsia.zbi"],
["", "zedboot.zbi"],
["", "fuchsia.vbmeta"],
["", "zedboot.vbmeta"]
]
}
]
}
},
"images": [
{
"base_uri": "gs://fuchsia/development/0.20201216.2.1/images/generic-x64.tgz",
"format": "tgz"
},
{
"base_uri": "https://storage.googleapis.com/fuchsia/development/0.20201216.2.1/images/generic-x64.tgz",
"format": "tgz"
}
],
"packages": [
{
"repo_uri": "gs://fuchsia/development/0.20201216.2.1/packages/generic-x64.tar.gz",
"format": "tgz"
},
{
"repo_uri": "https://storage.googleapis.com/fuchsia/development/0.20201216.2.1/packages/generic-x64.tar.gz",
"format": "tgz"
}
]
}
}
模拟器上的终端
这是可以在 x64 模拟器上启动的通用终端产品示例。您可以直接从 GCS 访问映像和软件包。
{
"version": "514c2856",
"data": {
"type": "product_bundle",
"name": "generic-x64",
"description": "A terminal x64 product.",
"device_refs": ["qemu-x64"],
"metadata": [
["build-type" , "debug"],
["product", "terminal"]
],
"manifests": {
"emu": {
"kernel": "qemu-kernel.kernel",
"initial_ramdisk": "zircon-a.zbi",
"disk_images": ["storage-sparse.blk"]
}
},
"images": [
{
"base_uri": "https://storage.googleapis.com/fuchsia-artifacts/builds/8852232026486839104/images/",
"format": "files"
}
],
"packages": [
{
"repo_uri": "https://storage.googleapis.com/fuchsia-artifacts/builds/8852232026486839104/packages/",
"blob_repo_uri": "https://storage.googleapis.com/fuchsia-artifacts/blobs/",
"format": "files"
}
]
}
}
性能
这不太可能对性能产生影响,因为元数据生成和解析不会占用大量资源。
工效学设计
发布标准化元数据时,便不再需要脆弱的硬编码配置,从而简化集成工作。
我们选择 JSON,因为它是一种成熟的格式,并且是 Fuchsia 配置文件的实际上标准。JSON 架构格式经过了形式化处理和同行评审。
向后兼容性
由于现有元数据没有当前用户,因此引入元数据不会影响向后兼容性。
这些架构的未来修订版本将接受 API 审核,并通过标准 LSC 流程(涉及与高优先级客户进行测试和直接互动)管理变更。此过程将通过对架构定义进行版本控制来帮助完成。
安全注意事项
基于这些架构的元数据的安全性不低于现有解决方案(即对类似信息进行临时硬编码)。
我们将在这些架构的生命周期早期加强工件提交的安全性。这可能在部署之前,具体取决于安全团队正在提供的反馈。重要的是,工具必须验证下载工件内容的完整性:工件必须与发布元数据时预期的内容一致。这可以通过将哈希函数的输出添加到架构中来实现,也可以通过使用支持完整性检查的协议(例如 TUF)来实现。
作为 Fuchsia SDK 的一部分提供的工具会使用此架构并提取工件,因此必须实施额外的安全措施来确保传输安全,以防止中间人攻击等攻击。为此,他们可能会拒绝从不安全 / 不可信的位置提取或使用工件。
隐私注意事项
此提案没有已知的隐私权注意事项。发布元数据的用户或团队可能需要注意一些隐私权注意事项;我们希望他们自行进行隐私权审核。例如,发布元数据的团队可能需要仔细考虑如何跟踪下载情况。
测试
虽然架构的存在不需要测试,但我们会确保 build 生成的元数据符合架构。我们还将进行兼容性测试,以确保工具在必要时继续使用旧版架构。
文档
目前,除了架构本身之外,我们没有计划提供其他文档,但这可能会因需求而变化。创建或更新架构的开发者可能需要提供术语表,说明每个架构的使用方式以及它们之间的相互作用。
缺点、替代方案和未知问题
我们将致力于使用特定 API 来指定设备映像。这样做的好处是可以提高不同版本之间的兼容性,利用现有的更改管理流程,并让我们能够分发始终如一的工具;但缺点是灵活性较低(由于官僚主义障碍,更改架构需要更长时间)。
在先技术和参考文档
本文档将收集并系统化整个树中的常用配置,如上所述。您可以在 //build/images/BUILD.gn
中找到大部分现有元数据;例如,您可以在其中找到当前版本的刷写架构。
-
所有元数据均以 SDK 元素的形式分发。 ↩