RFC-0076:FIDL API 摘要

RFC-0076:FIDL API 摘要
状态已接受
领域
  • FIDL
说明

提供人类可读的 FIDL API Surface 的格式。

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2021-03-16
审核日期(年-月-日)2021-03-16

摘要

提供了描述 FIDL API Surface 的总结方法,其 第一个输出是人类可读的格式, 总结了 Fuchsia 源代码中 FIDL 库的 API 变更 树。

修正条款(2022 年 8 月)。此 RFC 描述了一种人类可读的文本格式, 每行一个 API 元素。在实现过程中,JSON 格式 (https://fxrev.dev/480357)。取消点赞 JSON 格式可以解析回 Go 数据结构, 这对 fidl_api_diff 特别有用。由于只有 JSON 格式 我们已移除文本格式,以简化维护工作。

设计初衷

在撰写本文时,已针对紫红色 有一个共同目标,即跟踪平台 API Surface 的变化。 完成后,获得汇总结果后,我们就可以使用版本控制功能 将平台开发与 SDK 使用的库版本分离开来 。

具体而言,在 FIDL 的领域,需要采用人类可读懂的格式, FIDL 库的 API Surface 的表示形式。这种表示形式 从现在起称为“摘要”有多种用途:

  • 由 FIDL 库提供的 API 目录,提供人性化的参考信息。

    其他生成 API Surface 的软件也在保留类似的库存, 例如 go。这允许将版本归因于特定 API 。

  • 作为检测 FIDL API 中向后不兼容性更改的基础。

    API 摘要可用于计算两个 API 之间的差异 surface 中,因此可以自动检查一个 API Surface 能否 可能就会演变成另一个星球与当前 使用的方法,其中以稳定(称为“标准化”)的形式调用库 它通过以可预测的方式串联所有来源的 并移除评论和不相关的空格。

  • 作为其他开发工作(例如兼容性测试套件)的基础组件 (CTS,请参阅 RFC-0015)用于检测需要在更改之后运行的 API 更改。

    特别是,CTS 需要减少在 平台变更了解 API Surface 中发生的变化可能有助于 仅运行受更改影响的测试,从而保存 执行时间和计算资源。

入门示例

请参考以下 FIDL 库定义(取自 fuchsia.accessibility.gesture。评论已被删减 但库就是完整的

library fuchsia.accessibility.gesture;

/// Maximum size of a returned utterance.
const uint64 MAX_UTTERANCE_SIZE = 16384;

/// Gesture types that accessibility offers to a UI component for listening.
enum Type {
    THREE_FINGER_SWIPE_UP = 1;
    THREE_FINGER_SWIPE_DOWN = 2;
    THREE_FINGER_SWIPE_RIGHT = 3;
    THREE_FINGER_SWIPE_LEFT = 4;
};

/// An interface to listen for accessibility gestures.
protocol Listener {
    /// When accessibility services detect a gesture, the listener is informed
    /// of which gesture was performed.
    OnGesture(Type gesture_type) -> (bool handled, string:MAX_UTTERANCE_SIZE? utterance);
};

/// An interface for registering a listener of accessibility gestures.
[Discoverable]
protocol ListenerRegistry {
    /// A UI registers itself to start listening for accessibility gestures
    /// through `listener`.
    Register(Listener listener) -> ();
};

上述库的 API 摘要如下所示:

protocol/member fuchsia.accessibility.gesture/Listener.OnGesture(fuchsia.accessibility.gesture/Type gesture_type) -> (bool handled,string:16384? utterance)
protocol fuchsia.accessibility.gesture/Listener
protocol/member fuchsia.accessibility.gesture/ListenerRegistry.Register(fuchsia.accessibility.gesture/Listener listener) -> ()
protocol fuchsia.accessibility.gesture/ListenerRegistry
const fuchsia.accessibility.gesture/MAX_UTTERANCE_SIZE uint64 16384
enum/member fuchsia.accessibility.gesture/Type.THREE_FINGER_SWIPE_DOWN 2
enum/member fuchsia.accessibility.gesture/Type.THREE_FINGER_SWIPE_LEFT 4
enum/member fuchsia.accessibility.gesture/Type.THREE_FINGER_SWIPE_RIGHT 3
enum/member fuchsia.accessibility.gesture/Type.THREE_FINGER_SWIPE_UP 1
strict enum fuchsia.accessibility.gesture/Type uint32
library fuchsia.accessibility.gesture

需要注意以下几点:

  • 每个 API 元素都是一行文本。
  • 每个 API 元素都通过其完全限定名称进行引用。
  • API 元素在摘要中的显示顺序是固定的。如果 更改 FIDL 文件中声明的顺序,则应该有 对 API 摘要的形状没有影响。
  • 您可轻松使用 grep 等文本工具提取摘要的各个部分。对于 例如,假设 API 摘要位于名为 fidl.api_summary 的文件中。 以下命令行仅提取该协议的 API Surface:

    cat fidl.api_summary | grep "fuchsia.accessibility.gesture/ListenerRegistry"
    

    同样,仅提取方法也很简单:

    cat fidl.api_summary \
      | grep "fuchsia.accessibility.gesture/ListenerRegistry" \
      | grep "protocol/member"
    
  • 可以通过以下方式生成基本的 API Surface 差异:

    diff -u fidl.old.api_summary fidl.new.api_summary
    

    (假设 fidl.{old,new}.api_summary 包含原始版本和修改后的版本) API surface)

要求

  • API 摘要应人类可读,并可通过 简单的工具,例如 grepdiff

  • 生成的 API 摘要必须列出且仅列出 FIDL 的元素 会造成 API Surface 影响。

设计

API 摘要格式包含具有 API 的库的相关信息, 影响。在定义:来源 RFC-0024 的兼容性和可转换性,并在 FIDL 绑定规范。实际上只是其中的一部分信息 已包含在 FIDL IR 中,但以 便于用户阅读和处理文本实用程序。请参阅概述 规则,获取完整列表。

摘要规则涵盖了每种 FIDL 语言结构。

每个 FIDL 声明都使用完全限定名称命名。对于 在上述示例的缩短代码段中:

library fuchsia.accessibility.gesture;
enum Type { THREE_FINGER_SWIPE_UP = 1; };
protocol Listener {
  OnGesture(Type gesture_type);
};

标识符 OnGesture 始终称为 fuchsia.accessibility.gesture/Listener.OnGesture

为了便于读取和处理,我们特意调整了文件格式。 这意味着,FIDL 成员(出现在 structprotocol)列于单独的文本行中。这为我们提供了一些 如果需要的话,将来可以扩展该格式。例如,它会变为 包含未来版本编号属性。

单个 API 摘要文件会列出整个 FIDL 中的所有声明。 无论在多少个文件中指定了声明。

声明在 API 摘要中的显示顺序为 不依赖于声明顺序,并且保持稳定。相关声明包括 以便于后期处理,但这并不是 正确性要求:任何与声明顺序无关的且稳定的排序 就足够了

API 摘要排序

声明的顺序派生自 FIDL AST:声明 与 AST 的后订单遍历一致, 包含字母数字较小、完全限定名称的标识符, 同级之间选择。

我们将此排序称为 API 摘要排序。

此方法建议按照以下顺序对 API 中的声明进行排序。 摘要文件:

fuchsia.accessibility.gesture/Listener.OnGesture
fuchsia.accessibility.gesture/Listener
fuchsia.accessibility.gesture/ListenerRegistry.Register
fuchsia.accessibility.gesture/ListenerRegistry
fuchsia.accessibility.gesture/MAX_UTTERANCE_SIZE
fuchsia.accessibility.gesture/Type.THREE_FINGER_SWIPE_DOWN
fuchsia.accessibility.gesture/Type.THREE_FINGER_SWIPE_LEFT
fuchsia.accessibility.gesture/Type.THREE_FINGER_SWIPE_RIGHT
fuchsia.accessibility.gesture/Type.THREE_FINGER_SWIPE_UP
fuchsia.accessibility.gesture/Type
fuchsia.accessibility.gesture

获取上述示例 FIDL 库。

API 摘要中声明的顺序是相同的 无论 .fidl 文件中声明的实际顺序如何, 包括是否将其拆分到多个文件中。

API 摘要声明架构

下面指定了用于实现以下目的的 API 摘要文件的简化 BNF: 参考。

summary          ::= declaration_list

declaration_list ::= declaration
                   | declaration "\n" declaration_list
declaration      ::= library
                   | const
                   | bits
                   | bits_member
                   | enum
                   | enum_member
                   | struct
                   | struct_member
                   | union
                   | union_member
                   | protocol
                   | protocol_member
                   | alias

alias           ::= "alias" fqn
bits            ::= strictness "bits" fqn fp
bits_member     ::= "bits/member" fqn
const           ::= "const" fqn d fv
enum            ::= strictness "enum" ft
enum_member     ::= "enum/member" fqn fv
library         ::= "library" fqn
protocol        ::= "protocol" fqn
protocol_member ::= "protocol/member" fqn d
struct          ::= resourceness "struct" fqn
struct_member   ::= "struct/member" fqn ft [ fv ]
union           ::= strictness "union" fqn
union_member    ::= "union/member" fqn

resourceness    ::= "" | "resource"
strictness      ::= "flexible" | "strict"

d   ::= <FIDL protocol member type signature>
fp  ::= <FIDL primitive type>
fqn ::= <FIDL identifier>
ft  ::= <FIDL type>
fv  ::= <FIDL value>

实现

API 摘要由程序实现 fidl_api_summarize。程序将 FIDL IR 作为输入, 输出 FIDL API 摘要,并将两个文件名指定为标志。 调用者应使用扩展 .api_summary 作为此程序的输出 但这绝不是硬性要求。

性能

fidl_api_summarize 是 FIDL IR 文件的简单转换。 抽查结果显示,当在 相当大的库因此,该计划很可能可以接受 作为常规构建流程的一部分,在每个 FIDL 库上运行。

安全注意事项

fidl_api_summarize 的当前实现不会尝试验证 FIDL IR,并假设其输入始终作为有效输出生成 共 fidlc 个。这可能会使程序容易因格式不正确 但很难判断能否将其用作攻击途径 介绍 Fuchsia 构建流程。

隐私注意事项

到目前为止,fidl_api_summarize 处理的信息已成为 供大家查看我们有理由假设 任何适用于其输入的隐私权规则也将应用于其输出。

这意味着,如果将其用于汇总非公开 FIDL 库代码, 其输出应遵循与库代码相同的隐私权标准 上次使用日期。

测试

该程序使用大型示例输入库进行测试, 并与本地输出进行比较。这样可以确保 Fuchsia 代码库的生命周期。

文档

应使用 FIDL 帮助页面来记录 fidl_api_summarize 的使用方法, https://fuchsia.dev.

先验技术和参考资料

Go 语言 API 会定期生成 API Surface 摘要