RFC-0188:组件 ABI 兼容性

RFC-0188:组件 ABI 兼容性
状态已接受
领域
  • 组件框架
说明

检测组件目标 ABI 修订版本并检查其对平台的支持。

问题
  • 95188
Gerrit 更改
  • 695063
作者
审核人
提交日期(年-月-日)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 修订版本引入功能路由。

条款

该设计详细说明了打包组件的组件解析过程中的多个操作者。以下术语将用于指代具有指定角色的参与者:

执行者 角色
解决操作 组件管理器中用于执行组件解析工作流的操作。
解析器-客户端 组件管理器中的客户端实体,用于将 FIDL 请求代理到组件解析器以解析组件。
组件解析器 提供 fuchsia.component.resolution.Resolver FIDL 协议以解析组件的组件。注意:此操作符不适用于内置解析器。
软件包解析器 提供 fuchsia.pkg.PackageResolver FIDL 协议以解析软件包的组件。

注意

解析操作和解析器客户端都是组件管理器的一部分,但在此设计中起着至关重要的作用。

一个重要的区别是,解析操作无法区分打包组件与未打包组件。ABI 修订版本必须先从其数据源(因打包组件和非打包组件而异)中解码,然后才能执行解析操作。

另一方面,解析器客户端目前会针对每个组件解析器实现,并执行与其解析的组件类型相关的职责。


设计

现状

本文档围绕以下规定进行了设计:打包组件的目标 ABI 修订版本取自其软件包目标 ABI 修订版本源(如 RFC-0135 中所定义)。

这种设计提供了一种方式来满足打包组件的 ABI 修订版本的当前状态,而不是对未来和开发时间表如何表示组件的目标 ABI 修订版本做出假设。

ABI 修订版本和非打包组件部分对非打包组件支持 ABI 修订版本进行了单独介绍。

概览

此 RFC 提议了组件解析工作流程包括从其软件包读取和解码组件的目标 ABI 修订版本、通过 FIDL 通信值,以及检查以确定 ABI 修订版本是否与平台兼容。

支持 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 修订版本的单独字段,其中 AbiRevisionuint64 值的别名:

sdk/fidl/fuchsia.component.resolve/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 修订版本不同,并且平台不再支持该子打包组件的 ABI 修订版本,则子打包组件将无法解析组件。这与子软件包通常提供的可用性保证相冲突,如 RFC-0154 所述。

ABI 兼容性和内置解析器

启动组件由内置于组件管理器中的启动组件解析器解析。RFC-0167 引入了启动组件的打包:启动组件解析器从 bootfs 软件包中解析组件,其格式与非启动组件软件包类似。

检索和评估启动组件的 ABI 修订版本应遵循图 1 中所述的类似的设计工作流程,但启动组件和启动软件包解析器不会作为外部组件实现。

具体而言,启动组件解析器所需的更改包括:

  • 启动组件解析器会打开并读取在 bootfs 软件包的 meta.far 中找到的 abi-revision 文件。
  • 启动组件解析器会将 ABI 修订版本值添加到返回到解析操作处理程序的已解析组件表示法中。

实现

此设计分两个阶段实现:

  1. 组件管理器将组件目标 ABI 修订版本设为可选。
  2. 组件管理器要求对组件目标 ABI 进行修订。
    • 如果未找到 ABI 修订版本文件,则会发生打包组件解析器错误。
    • 已表示非打包组件的 ABI 修订版本。

组件管理器的配置标志可用于强制执行 ABI 要求并启用第 2 阶段。

组件的目标 ABI 修订版本可通过 ffx component 等组件发现工具进行检查。

性能

对性能没有明显影响。

工效学设计

组件管理器负责显示由于目标 ABI 修订版本缺失或不兼容而导致的组件解析警告或错误。您应记录所有组件解析警告和错误。

在某些情况下(例如使用 ffx component),最终用户可能会发起 FIDL 请求来解析组件,并在失败时返回描述性的 FIDL 错误响应。

其他场景均无法向用户提供直接反馈。例如,从目标组件到提供该功能的源组件的路由路径上,组件解析失败可能会中断功能路由。这会关闭带有 epitaph 的 fuchsia.io 功能通道,需要用户读取日志或可能需要使用诊断工具来获取通道关闭的原因。

向后兼容性

这种两阶段实现策略可确保对于尚未指定目标 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 修订版本相比,定义和引入软件包级目标 ABI 修订版本更容易,后者需要更大程度的投入和协调工作。此外,当前策略提供的 MVP 使我们能够开始使用组件目标 ABI 修订版本,而无需等待将来如何在软件包或组件元数据中定义它们。

替代选项

在软件包解析器中检查 ABI 兼容性

另一种设计可以确认 ABI 修订版本是在软件包级别定义的,并且在组件解析过程中发现 ABI 修订版本文件的首要点是软件包解析。相邻参数用于推迟引入组件级目标 ABI 修订版本,直到组件元数据中定义 ABI。

优点

  • 解决了如何定义 ABI 修订版本的直接问题。

缺点

  • 不是无软件包组件的解决方案。
  • 会影响在组件管理器中使用组件目标 ABI 修订版本的未来工作计划,例如根据 ABI 修订版本监管功能路由。
  • 将 ABI 控件移至组件管理器之外的外部组件。
  • 若要添加一种用户可控制的方式来停用 ABI 强制执行以调试或测试目的,并不像在组件管理器中添加配置标志那样简单。
  • 对于包含不兼容的 ABI 修订版本的软件包,这些软件包已解析并下载,但未使用,可能会限制过于严格,或者需要进行其他特殊处理。例如,如果更新后的软件包包含当前运行平台尚不支持的 ABI 修订版本,则新软件包会成功解析和提取。

在组件解析器中检查 ABI 兼容性

除了打开和解析 ABI 修订版本文件之外,组件解析器还可以检查与系统的 ABI 兼容性。

优点

  • 如果组件的目标 ABI 不受支持,则阻止向组件管理器返回该组件。

缺点

  • 将 ABI 控件移至组件管理器之外的外部组件。
  • 会影响在组件管理器中使用 ABI 修订版本的未来工作计划,例如根据 ABI 修订版本引入功能路由。
  • 若要添加一种用户可控制的方式来停用 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 协议以及使用该协议的组件。

早期技术和参考资料

此设计未考虑。