RFC-0188:组件 ABI 兼容性 | |
---|---|
状态 | 已接受 |
区域 |
|
说明 | 检测组件目标 ABI 修订版,并检查其是否受平台支持。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2022-06-27 |
审核日期(年-月-日) | 2022-09-31 |
摘要
本文档介绍了组件框架如何在与组件交互之前检测组件的目标 ABI 修订版并检查其是否与 Fuchsia 平台兼容。
设计初衷
随着应用和 Fuchsia 系统接口的不断演变,对组件与平台的 ABI 兼容性进行监管的需求也越来越大。
组件是根据平台 ABI 的一组行为预期构建的,如果不强制执行具有 ABI 修订版本的显式 ABI 协定,此预期就会成为平台开发的限制。有时候,组件会以平台不再支持的 ABI 修订版本为目标进行构建。
组件框架可以防止执行以不受支持的 ABI 修订版为目标的组件,同样也能保证在组件运行时平台支持组件的目标 ABI。此 RFC 概述了组件框架如何在组件与 Fuchsia 平台之间强制执行此 ABI 协定。
利益相关方
教员:
- leannogasawara@google.com
审核者:
- abarth@google.com
- etryzelaar@google.com
- geb@google.com
- jsankey@google.com
咨询了:
- adamperry@google.com
- jmatt@google.com
- lukenicholson@google.com
- richkadel@google.com
- wittrock@google.com
- yeg@google.com
社交:
此 RFC 的设计文档已通过组件框架团队的设计审核。
什么是组件 ABI 兼容性?
ABI 兼容性是指 Fuchsia 系统接口向组件提供的行为预期一致性。RFC-0002 详细介绍了 ABI 修订的影响以及平台如何支持这些修订。
RFC-0002 详细介绍了 Fuchsia 平台如何支持不断演变的 ABI 修订版本集:添加的每个 ABI 修订版本都会对 Fuchsia 系统接口进行向后不兼容的更改,当平台不再支持旧版 ABI 修订版本的行为保证时,这些修订版本会从该集合中移除。如果组件的目标 ABI 修订版本包含在此不断演变的集合中,则该组件被视为与平台兼容。
此 RFC 介绍了组件与平台之间的 ABI 兼容性。关于组件之间行为兼容性的一般保证(尤其是如果它们是使用不同的但受支持的 ABI 修订版构建的)超出了本 RFC 的范围,可能会成为 RFC-0002 中建议的未来工作中的一部分,例如根据 ABI 修订版引入 capability 路线。
条款
该设计在打包组件的组件解析过程中区分了多个参与者。以下术语将用于指代具有指定角色的参与者:
执行者 | 角色 |
---|---|
解决操作 | 组件管理器中用于执行组件解析工作流的操作。 |
Resolver-Client | 组件管理器中的客户端实体,用于将 FIDL 请求代理到组件解析器以解析组件。 |
组件解析器 | 用于提供 fuchsia.component.resolution.Resolver FIDL 协议以解析组件的组件。注意:此 actor 不适用于内置解析器。 |
软件包解析器 | 用于提供 fuchsia.pkg.PackageResolver FIDL 协议以解析软件包的组件。 |
注意
resolve 操作和 resolver-client 均属于 Component Manager,但在本设计中发挥着不同的作用。
一个重要的区别是,解析操作无法区分打包组件与未打包组件。必须先从其数据源(打包的组件和未打包的组件之间会有所不同)解码 ABI 修订版,然后才能执行解析操作。
另一方面,目前为每个组件解析器实现了解析器客户端,并执行与其解析的组件类型相关的任务。
设计
当前状态
本文档的设计基于以下规定:打包的组件的目标 ABI 修订版本取自其软件包目标 ABI 修订版本源代码(定义在 RFC-0135 中)。
此设计提供了一种方法,可根据打包组件的 ABI 修订版本的当前状态来满足要求,而无需对未来如何表示组件的目标 ABI 修订版本以及开发时间范围做出假设。
ABI 修订版和非封装组件部分中将单独介绍如何为非封装组件支持 ABI 修订版。
概览
此 RFC 提出了组件解析工作流,其中包括从软件包中读取和解码组件的目标 ABI 修订版本、通过 FIDL 通信该值,以及检查 ABI 修订版本是否与平台兼容。
图 1:具有 ABI 支持的 ABI 组件解析工作流程
1. 组件解析器打开并读取软件包 ABI 修订版文件
打包组件的目标 ABI 修订版本目前与其软件包目标 ABI 修订版本相同。ABI 修订版本值存储在软件包的 meta.far
中找到的文件中。
虽然组件的目标 ABI 以这种方式定义,但组件解析器可以使用软件包解析器返回的目录代理来读取文件。组件解析器直接读取文件的原因是,最大限度地减少从软件包目标 ABI 设置组件的目标 ABI 的影响;缺点部分介绍了此行为的具体缺点。
如果存在该文件,组件解析器必须读取并解码 ABI 修订版,并将该值包含在返回给解析器客户端的 FIDL 组件表示法中。如果该文件不存在,则不包含该值。因此,组件解析器会将强制执行 ABI 存在性延迟到组件管理器。
2. 向 fuchsia.component.resolution.Component
引入了 ABI 修订版本字段
在组件 FIDL 表示法中引入了用于组件的目标 ABI 修订版本的单独字段,其中 AbiRevision
是 uint64
值的别名:
sdk/fidl/fuchsia.component.resolution/component.fidl:
type Component = resource table {
...
abi_revision AbiRevision;
}
...
“技术债务”部分将讨论,如果组件的目标 ABI 修订版本包含在 FIDL 中已表示的数据源(例如组件清单)中,此字段将如何变得多余。
3. 在组件管理器中检查 ABI 修订版是否存在以及兼容性
解析器客户端会将包含可选 ABI 修订字段的 FIDL fuchsia.component.resolution.Component
类型转换为组件管理器表示法,以便交接给解析操作。
在验证已解析组件的元信息时,应检查 ABI 修订版是否存在以及它是否与 Fuchsia 平台兼容。
解析操作必须使用公开 API 的库来检查给定 ABI 值是否属于平台支持的一组 ABI 值。这将确定解析的组件的目标 ABI 修订版是否与平台兼容。
组件管理器的配置标志可以指示解析操作针对缺失的目标 ABI 修订版生成警告,而不是错误,这将用于在实现策略中启用向后兼容性。同样,引入单独的配置标志以允许不兼容的组件 ABI 修订版,对于在没有 ABI 兼容性监管的情况下针对不同的 build 测试组件可能很有用。
为什么要在组件解析中执行 ABI 兼容性检查?
组件管理器中的调用方会解析组件网址,以便与构建的组件或其功能进行交互。将 ABI 兼容性集成到组件解析流程中可确保组件会以预期方式与平台进行交互。
重新解析组件时,ABI 修订版应包含在更新的组件数据中。与其他组件元数据类似,在明确更新组件之前,ABI 修订版不应发生变化。
其他设计注意事项
处理打包组件中缺失或不兼容的目标 ABI 修订版
预计提供目标 ABI 修订版本的打包组件可能会在以下任一时间点出错并中断组件解析:
- 如果存在 ABI 修订版文件,组件解析器将无法解码 ABI 修订版值。
- 解析操作无法将 FIDL 值解码为 ABI 修订数据类型。
- 解析操作会发现 ABI 修订版不存在或与平台不兼容,并且组件管理器配置标志会将其标记为错误。
具体取决于上下文,是最终用户还是组件管理器触发了组件解析,以及错误是可以直接返回给用户,还是只能记录以便发现。人体工学部分详细介绍了如何向用户显示警告和错误。
ABI 修订版和非封装组件
此 RFC 未定义非封装组件(例如 Web 组件)如何表示 ABI 修订版。我们将单独考虑此类组件的 ABI 兼容性,这不会影响此设计的初始发布,因为该设计允许 ABI 修订为可选项。
与子软件包的 ABI 兼容性
如 RFC-0154 中所述,顶级软件包和子软件包应包含 ABI 修订版。对于本 RFC 中涉及的问题,子软件包组件无需特殊处理:在解析每个子软件包组件时,都将遵循图 1 中所述的相同组件解析工作流。但是,如果子软件包组件与顶级打包组件的目标 ABI 修订版不同,并且平台不再支持该子软件包组件的 ABI 修订版,则该子软件包组件将无法解析组件。这与 RFC-0154 中所述的子软件包通常提供的可用性保证相冲突。
ABI 兼容性和内置解析器
引导组件由内置于组件管理器中的引导组件解析器解析。RFC-0167 引入了启动组件的封装:启动组件解析器会从 bootfs 软件包解析组件,其格式与非启动组件软件包类似。
检索和评估启动组件的 ABI 修订版遵循图 1 中所述的类似设计工作流程,但启动组件和启动软件包解析器并非作为外部组件实现。
具体而言,启动组件解析器需要进行以下更改:
- 启动组件解析器会打开并读取 bootfs 软件包的
meta.far
中找到的 abi-revision 文件。 - 引导组件解析器会将 ABI 修订版本值包含在返回给解析操作处理程序的已解析组件表示法中。
实现
此设计分两个阶段实现:
- 组件管理器使组件目标 ABI 修订版成为可选项。
- 组件管理器会要求组件目标 ABI 修订版。
- 如果找不到 ABI 修订版文件,打包的组件解析器会出错。
- 表示非封装组件的 ABI 修订版本。
组件管理器的配置标志可用于强制执行 ABI 要求并启用第 2 阶段。
您可以通过 ffx component
等组件发现工具检查组件的目标 ABI 修订版。
性能
对性能没有明显影响。
工效学设计
组件管理器负责显示因目标 ABI 修订版本缺失或不兼容而导致的组件解析警告或错误。应记录所有组件解析警告和错误。
在某些情况下(例如使用 ffx component
时),最终用户可能会发起 FIDL 请求,该请求将解析组件,并在失败时返回描述性 FIDL 错误响应。
在其他情况下,无法向用户提供直接反馈。例如,从提供相应功能的目标组件到提供相应源组件的路由路径上发生组件解析失败,可能会中断功能路由。这会关闭带有墓志铭的 fuchsia.io
capability 信道,要求用户读取日志或可能使用诊断工具来获取关闭信道的原因。
向后兼容性
两阶段实现策略可确保组件解析功能继续适用于尚未指定目标 ABI 修订版的组件软件包。
为 FIDL ABI 修订版字段生成的绑定会使该字段成员成为可选项,这让我们能够在不破坏尚未指定 ABI 修订版的组件的情况下发布实现。
向后兼容性行为取决于配置标志,如果组件的目标 ABI 修订版不存在或与平台不兼容,该标志会指示组件管理器返回错误。
安全注意事项
没有已知的安全问题。
隐私注意事项
没有已知的隐私问题。
测试
现有测试框架将用于测试以下场景:
- 用于在组件解析器中读取和解码 abi-revision 文件的单元测试。
- 用于根据配置设置检查 ABI 修订版的存在性/值的单元测试。
- 组件解析器和解析器-客户端接口之间的集成测试。
文档
我们将推出 https://fuchsia.dev 上的文档,介绍以下内容:
- 组件目标 ABI 修订版本的概念。
- 如何定义组件目标 ABI 修订版。
- 如果发现组件的目标 ABI 修订版与平台不兼容,会发生什么情况。
此外,还会根据需要编写源代码文档。
缺点
组件解析器读取软件包元数据以检索组件的目标 ABI 修订版
组件的目标 ABI 修订版派生自其软件包目标 ABI 修订版,该修订版存储在存储软件包元数据的 meta.far
中。或者,您也可以在组件元数据中定义组件目标 ABI 修订版,而组件解析器不会与软件包元数据交互。
此外,由于软件包中的所有组件都从同一单个值派生其目标 ABI 修订版,这限制了软件包中的组件可以彼此独立演变的方式。对于具有不同更新节奏的软件包中组件的单独维护者,这可能会出现问题。另一方面,子软件包提供了一种在依赖项中对组件目标 ABI 修订进行分组和区分的方法。
这时,我们需要决定为何将组件的目标 ABI 修订版本设置为其软件包目标 ABI 修订版本。本 RFC 的未知部分是:未来是否、如何或何时会更改组件目标 ABI 修订版本的定义方式。不过,我们可以承认,定义和引入软件包级目标 ABI 修订版比引入特定于组件的目标 ABI 修订版更容易,后者需要更高水平的承诺和协调工作。此外,当前策略提供了一个 MVP,使我们能够开始使用组件目标 ABI 修订版,而无需等待未来在软件包或组件元数据中定义它们的方式。
替代方案
在软件包解析器中检查 ABI 兼容性
另一种设计方案可以承认 ABI 修订版是在软件包级别定义的,并且在组件解析过程中,ABI 修订版文件的首次发现点是在软件包解析时。相邻参数用于推迟引入组件级目标 ABI 修订,直到在组件元数据中定义 ABI。
优点:
- 介绍了如何定义 ABI 修订版。
缺点:
- 不适用于无软件包组件。
- 会影响在组件管理器中使用组件目标 ABI 修订版本的未来工作计划,例如根据 ABI 修订版本来规范 capability 路由。
- 将 ABI 控制权移至组件管理器之外的外部组件。
- 添加一种用户可控的方式以便出于调试或测试目的停用 ABI 强制执行,并不像向组件管理器添加配置标志那样简单。
- 对于已解析和下载但未使用的不兼容 ABI 修订版本的软件包,此规则可能过于严格,或者需要进行特殊处理。例如,解析和提取包含当前运行平台尚不支持的 ABI 修订版的更新软件包应该仍然会成功。
在组件解析器中检查 ABI 兼容性
除了打开和解析 ABI 修订版文件之外,组件解析器还可以检查 ABI 与系统的兼容性。
优点:
- 防止在组件的目标 ABI 不受支持时将组件返回给组件管理器。
缺点:
- 将 ABI 控制权移至组件管理器之外的外部组件。
- 会影响在组件管理器中使用 ABI 修订版本的未来工作计划,例如根据 ABI 修订版本引入 capability 路由。
- 添加一种供用户控制的方法来出于调试或测试目的停用 ABI 强制执行,并不像向组件管理器添加配置标志那样简单。
组件管理器会在特定组件互动之前检查目标 ABI 兼容性
在对组件执行特定操作(例如启动或访问其某项功能)之前,组件管理器可以检查是否支持(已解析)组件的目标 ABI 修订版。
优点:
- 更具体地说明了何时应检查 ABI 修订版本。
- 可能更好地控制错误处理。
缺点:
- 忽略组件的目标 ABI 是如何作为形成其接口的声明的一部分,该接口会在组件解析期间进行验证。
- 维护成本高,需要人工了解应在哪些上下文中执行 ABI 检查。
- 由于缺少 ABI 兼容性检查,因此容易引入组件中的破坏性、意外或难以调试的行为。
打开并从 Resolver-Client 读取软件包 ABI 修订版文件
我们可能希望尽量减少此临时设计对组件目标 ABI 的影响,并通过避免向组件解析器和 FIDL 引入新行为,实现最易于撤消的解决方案。
优点:
- 避免向
fuchsia.component.resolution.Component
引入新的 FIDL 字段,如果组件目标 ABI 修订版本包含在也表示在 FIDL 中的数据源(例如组件清单)中,则该字段可能会成为技术债务。技术债务部分详细介绍了这种情况。
缺点:
- 直接从软件包中读取文件会违反解析器客户端的抽象边界。这必须在解析器客户端中执行,而不是在解析操作中执行,因为解析操作无法区分打包的组件和未打包的组件。
- 此临时修复程序的有效期尚不明确。
未知
未来是否/如何/何时定义特定于组件的目标 ABI 修订版
我们尚不清楚何时会为每个组件定义 ABI 修订版本,以允许同一软件包中的组件具有不同的目标 ABI 修订版本。我们也未承诺未来将使用哪种数据源来存储组件目标 ABI 修订版;ABI 是否会包含在组件清单中仍是一个悬而未决的问题。
技术债
此设计不会假定未来将如何定义组件目标 ABI 修订版,并且可能会引入技术债务。
如果组件目标 ABI 修订版本包含在同时具有 FIDL 表示形式的来源(例如组件清单)中,则 fuchsia.component.resolution.Component
的 ABI 修订版本字段成员将变得多余,应予以移除。这种技术债务仅限于 fuchsia.component.resolution.Resolver
协议及其使用该协议的组件。
在先技术和参考文档
此设计中未考虑任何此类情况。