RFC-0135:软件包 ABI 修订版本 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 将系统 ABI 修订版本编码到软件包中。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021-09-30 |
审核日期(年-月-日) | 2021-11-05 |
摘要
用于将系统 ABI 修订版本编码为软件包的设计。
设计初衷
RFC-0002 引入了 API 级别和 ABI 修订版本的概念。API 水平是一个单调递增的人类可理解数字, 与构建应用时可用的一组 API 相对应。通过 ABI 修订版本与 Fuchsia 提供的特定语义相对应 应用期望平台提供的系统接口。API 级别 对应于特定的 ABI 修订版本,但多个 API 级别可以引用 ABI 修订版本相同。此功能使 Fuchsia 平台能够改进 同时继续为旧版应用提供支持。
实现平台版本控制要求软件包对 ABI 级别进行编码 以便平台了解某个软件包是否 与正在运行的系统兼容。
利益相关方
教员:abarth@google.com
审核者:
在此 RFC 涉及 Fuchsia Tools 时,我们选择了以下利益相关方, 最终将影响组件框架的 选择要呈现给应用的组件系统界面。
- abarth@google.com(FEC 成员)
- computedruid@google.com (SWD)
- geb@google.com (CF)
- mkember@google.com (FIDL)
- raggi@google.com(工具)
- wittrock@google.com (SWD)
已咨询:
- 利家明 (PDK)
社交化:
此 RFC 通过了 Software Delivery 和 Fuchsia 的设计评审 工具团队。
术语
Fuchsia 软件包是用于分发和 组织 Fuchsia 程序、组件和服务的文件。
meta.far 是软件包元数据归档。它包含 面向用户的文件名添加到底层内容寻址 blob。这是 下载软件包内容并构造命名空间 层级结构。它还包含用户提供的自定义文件。
设计
此设计引入了软件包 ABI 修订版本的概念,
软件包使用的 Fuchsia 平台接口的目标 ABI 修订版本。这个
值将被写入一个无符号小端序 64 位整数,
文件 meta/fuchsia.abi/abi-revision
中的 meta.far
。
所有软件包生成工具都将更新,以要求使用 API 级别 或 ABI 修订版本。当 API 级别 则工具应对在文件中找到的相应 ABI 修订版本 SDK 版本历史记录,或出错。同样,该工具应 SDK 支持指定的 ABI 修订版本,否则会出现错误。这个 应避免通过旧版 SDK 创建组件的风险 只有较新版本的 SDK 中存在 ABI。最多只会生成一个组件 运行失败。最严重的是,这可能会导致组件出现奇怪或 危险的虫子
软件包 ABI 修订版本的用例
此提案仅介绍如何将 ABI 修订版本编码到软件包中。用户 软件包 ABI 修订版本将在未来的设计中定义。不过,在这里 下面列举了一些可能的用例,以帮助您说明可以如何使用这类数据:
- RFC-0002 平台描述了组件管理器可使用的机制 软件包 ABI 修订版本,用于选择何时使用哪个平台接口 运行组件的过程
- 系统组装是从 一组软件包和其他已编译的工件。随后该系统映像 用于通过不同的方式(OTA、刷写、铺砌 等)。编译器可以使用软件包 ABI 修订版本来拒绝 集成软件包。
- 同样,花瓣或应用开发者可以使用软件包 ABI 修订版本 以了解复杂树中的所有组件能否 目标 Fuchsia 版本。
- 临时软件包是按需下载的软件包,而不是 都内置在系统映像中Package Resolver 可以利用 软件包 ABI 修订版本拒绝下载它知道不是 可执行文件但请注意,这种方法可能不适用于系统更新。 如需了解详情,请参阅系统更新注意事项。 。
选择目标 API 级别或 ABI 修订版本
此方案旨在将 API 级别或 ABI 修订版本设置为必需的参数 但在初始发布期间是可选的 功能部分。考虑到这一点,最终开发者应 针对目标 API 级别或 ABI 修订版本的构建规则。这样应该可以轻松地 以定位新版本您甚至可以针对 通过设置一个测试滚轮来试验性地推进 API 级别, 目标 API 级别,看看是否有任何问题。这可以反馈给平台 bug 报告。
系统更新注意事项
为了使 Fuchsia 设备从一个版本更新到另一个版本, 系统更新程序会解析一个名为“更新软件包”的特殊软件包。这个 package 描述了进行构建时所需的全部基础软件包和其他工件, 要运行的新 Fuchsia 版本。这些新软件包不 而是在设备重新启动到 新系统。
因此,如果我们决定使用软件包 ABI 修订版本来拒绝 下载软件包时,我们需要小心,以免破坏 OTA 流程。 这可通过以下示例了解:
假设有两个 Fuchsia build A
,它们仅支持 ABI-1
和 C
,
支持 ABI-2
。如果我们根据 ABI 过滤软件包,则针对
C
的值必须为 ABI-1
,才能下载。不过,基于 C
的版本基准
软件包必须为 ABI-2
才能使用新的 ABI,但应为
被版本 A
软件包解析器拒绝。
避免这种情况的一种方法是,通过步进 英石版本。Fuchsia 旨在支持设备跳过多个版本 才能更新到最新版本。踏步石版本是一种特殊的发行 版本。它旨在实现顺畅的过渡 通过平台界面进行通信
重做前面的示例,我们改为提供 3 个连续的 Fuchsia 版本:
A
:支持ABI-1
,基础软件包为ABI-1
B
:支持ABI-1
和ABI-2
,基础软件包为ABI-1
。C
:支持ABI-2
,基础软件包为ABI-2
。
如果我们将 B
标记为跳石版本,那么运行 A
的设备会
先更新为 B
,然后再更新为 C
。
通过将软件包的定义方式与 ABI 修订版本。由于我们不打算频繁向后 对软件包布局不兼容的更改,我们可以对软件包布局进行版本控制, 然后说明给定 ABI 修订版本支持哪些软件包布局版本。 这样,我们无需 进行构建。
避免 meta.far 中的命名空间冲突
meta.far
目前包含两个软件包元数据文件:meta/package
meta/contents
和任意用户指定的文件。这意味着
用户文件可能会与任何新的元数据发生冲突
打包成一个文件包为避免这种可能性
修订版本将写入目录 meta/fuchsia.abi
。此目录名称
遵循 Fuchsia 中其他地方使用的惯例,如平台 FIDL
命名空间我们将进一步更新软件包构建工具,
在 meta/fuchsia.abi
中定义自定义文件。
由于这是一个由平台控制的目录,因此可以使用此
用于存储 ABI 相关文件的位置,而不会与用户文件发生冲突。这个
可以让我们改进软件包 ABI 修订版本的概念。例如,如果
想要支持软件包中的多个 ABI 修订版本,可以添加
meta/fuchsia.abi/abi-revision-set
以包含所有支持的修订版本。
在所有用户迁移到meta/fuchsia.abi/abi-revision
新文件。
存储开销
将软件包 ABI 修订版本添加到元数据的开销增加了 8KiB 因为第一个 4KiB 来自于 FAR 数据块,如果 DIRNAMES 部分导致第一个数据块,则创建第二个 要推送的下一个 4KiB 对齐偏移。不过, 在实践中应该不会产生重大影响,因为 blobfs 的 8KiB 块对齐。而且,使用默认值时, 压缩器 zstd。根据以下示例,这仅将 47 个字节 添加到 meta.far 中:
# Create an empty package.
% mkdir empty && cd empty
% pm init && pm build
% ls -l meta.far
-rw-r--r-- 1 etryzelaar primarygroup 12288 Oct 5 10:21 meta.far
% fx chunked-compress c meta.far meta.far.compressed
Wrote 447 bytes (97% compression)
# Then create a meta.far that contain's the abi-revision.
% cd .. && mkdir with-abi && cd with-abi
% pm init
% mkdir meta/fuchsia.abi
% python3 -c "
import struct;
abi_revision = int('0xC7003BF9', 16)
f = open('meta/fuchsia.abi/abi-revision', 'wb')
f.write(struct.pack('<Q', abi_revision))
"
% pm build
% ls -l meta.far
-rw-r--r-- 1 etryzelaar primarygroup 16384 Oct 5 10:22 meta.far
% fx chunked-compress c meta.far meta.far.compressed
Wrote 494 bytes (97% compression)
实现
所有软件包构建工具都将进行扩展,以支持指定 API 级别 或 ABI 修订版本。
pm CLI
pm
CLI 将扩展,以允许在打包软件包期间指定 ABI
初始化和软件包构建。
调用示例:
# Create a package with an API level. Under the covers this will look up the
# ABI revision from the SDK.
% pm init --api-level 5
# Create a package with an ABI revision. These commands are equivalent.
% pm init --abi-revision 0xC7003BF9
% pm init --abi-revision 3338681337
# Build a package with an ABI revision.
% pm build --abi-revision 0xC7003BF9
选项:
--api-level LEVEL
:要编码到软件包中的 API 级别。此值 必须受 SDK 支持此选项与--abi-revision
标志。--abi-revision REVISION
:将内置于 软件包。可以是十进制或十六进制整数 。此选项与--api-level
标志冲突。
最初,--api-level
和 --abi-revision
标志对于
以便花瓣和最终开发者在一段时间内实现支持。
最终,在生态系统完成过渡后,这将成为一项必不可少的论据
如何指定标志
性能
在构建软件包时,此 RFC 引入了少量额外工作, 而且存储空间开销也很小,因此性能影响应 可以忽略不计。
工效学设计
此方案本身并未显著改变紫红色的人体工程学设计。 不过,这最终会使产品开发者能够定位特定的 为其组件创建系统接口这应该会为他们提供 同时又不阻碍 Fuchsia 的进化能力。
向后兼容性
此更改向后兼容,因为此设计引入了一个新文件 没有使用方不过,此功能最终会让 弃用并最终取消对旧版 ABI 修订版本的支持。
安全注意事项
需要解析 meta/fuchsia.abi/abi-revision
文件。不过,
格式易于解析,且应易于验证解析器是否
正确。
如需了解详情,请参阅 RFC-0002 安全注意事项。
隐私注意事项
此方案对隐私保护没有任何实质性的影响。
测试
将扩展打包工具,以验证是否生成了软件包
以及要设置的预期 ABI。由于会有过渡期,
将扩展软件包解析器测试,以验证其是否与软件包一起使用
(包含或不包含 meta/fuchsia.abi/abi-revision
文件)。
文档
我们将更新打包文档,以讨论 ABI 的 以软件包的形式表示,以及用户如何选择 API 级别或 ABI 修订版本
缺点、替代方案和未知问题
备用 ABI 修订版本文件格式
我们无需将 ABI 修订版本编码为小端序整数, 请改用:
- 人类可读的整数字符串
- JSON
- 永久性 FIDL
选择了一个小端序整数,原因如下:
- 我们预计人类不会理解此值。应改为 指的是人类可理解的 API 级别。
- 该值将作为小端序整数传递,因此可以避免 额外的转换。
- 它易于解析。
包含一组 ABI 修订版本的软件包
RFC-0002 Applications 指出软件包可以包含多个组件, 每个版本都以不同的 ABI 修订版本为目标。为了支持这一点, 对软件包中的单个 ABI 修订版本进行编码,则软件包 ABI 可以是一组 所有组件 ABI 修订版本。
不过,在编写时,没有任何用例需要使用 包含以不同系统 ABI 为目标的组件。单个数字 简化了对 ABI 支持的初始实现。这并不困难 如果这种情况非常重要,您可以扩展此设计。
将 ABI 修订版本直接编码到 meta.far 中
元 [meta.far] 可以通过以下任一方式直接嵌入 ABI 修订版本:
- 将 ABI 添加到 FAR 索引块中。
- 优点:
- 只增加 8 个字节的开销。
- 缺点:
- 索引区块没有任何预留字节,因此将其添加到 索引将需要对 FAR 格式进行破坏性更改。为了使 我们必须先实现对读取新 FAR 格式,然后创建阶梯版本,以及 最后迁移到该格式
- 对于使用者而言,读取 ABI 修订版本会更加困难。通过 软件包解析器不会以文件的形式直接向用户公开 meta.far, 因此需要添加一个 API 来公开这些信息
- 创建一个新的 ABI 修订版本区块类型。
- 优点:
- 应向后兼容以添加新的分块类型。
- 以字节为单位的开销要小得多,因为我们不需要 创建一个 4096 字节对齐的内容块。数据块按 64 位对齐, 索引开销条目大小为 24 字节,所以此方法应 只会向未压缩的 FAR 格式增加 32 个字节。
- 缺点:
- 我们尚未在 FAR 格式中添加新的分块类型,因此 FAR 可能 如果库遇到新的错误, 数据块类型。
- 我们必须更新所有 FAR 库才能理解新分块 类型。过去,对 FAR 库所做的任何更改都代价很高 要执行的任务。
- 对于使用者而言,读取 ABI 修订版本会更加困难。通过 软件包解析器不会以文件的形式直接向用户公开 meta.far, 因此需要添加一个 API 来公开这些信息
由于存储开销很小,特别是在压缩时,我们不 认为节省的空间值得定义新的分块类型。
代码库元数据中的 ABI 修订版本
我们可以改为将 ABI 添加到软件包中,而不是直接将 ABI 编码到软件包中。 对软件包代码库中软件包元数据的修订版本。它包含 以下缺点:
- ABI 修订版本是软件包的固有属性。可能是 很难确保 ABI 修订版本在 TUF 中正确表示 代码库或基础软件包列表中
- 打包元数据仍将包含 ABI 修订版本,因此打包 系统仍然必须承担开销
即将发布的永久性 FIDL 软件包元数据中的 ABI 修订版本
Software Delivery 正在编写 RFC,以提议新的永久性 FIDL 打包元数据。我们可以通过以下方式将 ABI 修订版本存储在此元数据中 将建议的架构更新为以下内容:
flexible union Contents {
1: ContentsV1 v1;
};
table ContentsV1 {
1: vector<fuchsia.io.Path>:MAX paths;
2: vector<fuchsia.pkg.BlobId>:MAX hashes;
3: vector<uint64>:MAX blob_sizes;
4: uint64 abi_revision;
};
优点:
- 将所有打包元数据整合到单个 FIDL 文件中的优势 我们利用 FIDL 工具确保文档资料和验证 功能。使用多个文件有助于我们更轻松地处理 验证彼此不同步。
- 我们只需向未压缩的 meta.far 中添加少量字节 大约 4KiB。
使用 FIDL 的缺点:
- 我们无法保证接受基于永久性 FIDL 的 RFC, 以及实现所需时间
- 虽然基于永久性 FIDL 的方法带有版本编号,但内部版本 无法帮助我们将包装元数据迁移到其他文件格式。对于 例如,如果我们决定从永久性 FIDL 切换到 JSON 文件。它 更轻松地使用新的 ABI 修订版本来告知打包系统 查找与之前不同的文件格式。
先验技术和参考资料
Android
Android 应用以 SDK 版本为目标,方法是指定 uses-sdk 元素 应用清单中。
Windows
Windows 应用通过指定 SupportedOS 来定位操作系统版本, 应用清单中列出的 GUID。
macOS
macOS 应用通过指定
LSMinimumSystemVersion。Info.plist
iOS
iOS 应用通过在MinimumOSVersion
应用软件包的 Info.plist
文件。