RFC-0115:build 类型 | |
---|---|
状态 | 已接受 |
区域 |
|
说明 | 产品 build 类型的规范定义。 |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021-07-06 |
审核日期(年-月-日) | 2021-07-21 |
摘要
本文档介绍了 Fuchsia 的不同产品 build 类型:eng
、userdebug
和 user
。
Fuchsia 中的 build 类型是指产品配置的构建时间和运行时设置:
构建时设置包括用于定义系统行为的软件包、工具、签名配置和标志。
运行时设置包括传递给正在运行的内核或软件的标志,用于根据 build 类型调节运行时行为。
本文档旨在正式批准已在使用这些 build 类型的 Fuchsia 产品的设计决策。它还可作为 Fuchsia 平台中不同 build 类型的正式定义。
设计初衷
Fuchsia 定义了多种 build 类型,供开发者、测试人员和最终用户等多种用户使用。这三个用户群体对正在运行的 Fuchsia 系统的行为有不同的预期。
特定 build 类型会对不同的用例(例如开发或面向最终用户分发的产品)编码并保证特定的 Fuchsia 系统行为。
此外,您还可以根据产品 build 类型做出 build 时决策,例如添加特定的软件包变种。如需了解详情和示例,请参阅软件包变种部分。
因此,不同的 build 类型为 Fuchsia 平台及其用户提供了必要的灵活性,可支持 Fuchsia 产品的整个生命周期。
设计
本部分概述了 Fuchsia 上 build 类型的当前常见惯例。其中详细介绍了每种类型的不同属性以及运行时限制(如果适用)。
由于复杂性和实现成本,还应注意定义的 build 类型的数量。如需了解详情,请参阅缺点部分。
根据 Fuchsia 的当前要求,有三种 build 类型:
user
userdebug
eng
下文的定义部分对 build 类型进行了进一步说明。
如需添加其他 build 类型,则需要提交一份提案,该提案需要通过 RFC 流程并获得 Fuchsia 工程委员会 (FEC) 的批准。
目标
该设计的主要目标如下:
- 为构建类型制定正式的通用惯例,以支持开发者需求以及最终产品发布要求。
- 实现 build 类型时,应尽可能使其尽可能相似,以避免产品行为出现进一步差异。
- 构建类型的发布和资格认定采用相同的条件和节奏。
定义
user
user
build 类型用于面向最终用户出货的正式版设备。
对于 user
build,平台会在运行时强制执行最高级别的安全保证,并且仅在构建时包含产品所需的组件。
userdebug
userdebug
build 类型的行为默认与 user
相同,但允许进行额外的调试和插桩操作。
userdebug
build 主要用于开发设备,以进行最终用户产品测试和认证。
eng
eng
build 类型主要面向开发者和测试人员,会启动到产品会话定义的完整产品体验。
各种产品配置的 eng
build 可在树内获得,并且可作为预构建的系统映像与 Fuchsia SDK 一起获得。
产品配置
build 类型定义为产品专用配置。为了保持不同 build 类型之间的相似性,这些配置会从 Fuchsia 的核心产品继承和包含内容,并选择性地添加或移除软件包和配置。
构建类型关系可以总结如下:
图 1:将 build 类型用作商品配置。
注意:
eng build 类型会继承 core,并且可以包含特定于产品的其他软件包。
user build 类型会直接继承 core,但会移除所有额外的软件包、调试功能和其他插桩属性。
然后,userdebug 会继承 user,并且仅略有不同,以启用调试和插桩所需的其他功能。
userdebug 和 user 之间的反向继承可确保对 user 进行的任何更改(最终用户产品所需的更改)都会自动反映在 userdebug build 中。
该设计大致反映了产品周期,其中
eng
是基于core
Fuchsia 产品构建的第一个产品配置。然后,当产品在生命周期中进一步发展时,定义userdebug
和user
以反映这些用例和要求。
实现
以下部分按平台的主要领域记录了每种 build 类型的实现详情。
断言
Zircon 是 Fuchsia 的核心平台,由内核和一小部分用户空间服务、驱动程序和库组成。
整个代码库中使用了几种不同的类似断言的机制。内核和用户模式断言的启用或停用取决于 build 类型。例如,ZX_ASSERT
始终针对所有 build 类型处于启用状态,并且必须更便宜,以免影响性能。
再举一个示例,assert_level
在 eng
build 中为 2
,并启用所有断言,而在 userdebug
和 user
build 中为 0
,这会停用标准 C assert()
和 ZX_DEBUG_ASSERT
。
下表概述了内核中的断言:
属性 | eng | userdebug、user |
---|---|---|
ASSERT | 开启 | 开启 |
DEBUG_ASSERT | 开启 | 关闭 |
assert() | 开启 | 关闭 |
恢复分区
Fuchsia 最终用户产品使用 A/B/R 更新和恢复方案。
总而言之,系统通过无线下载 (OTA) 机制进行更新,利用 A/B 更新方案,其中包含两个系统副本(一个处于活动状态,另一个处于非活动状态)。这样可以确保在更新失败时,系统有后备方案。不过,如果回退分区无法启动,系统会使用存储在恢复分区中的恢复映像来尝试恢复系统。
每款产品都可以定义自己的恢复映像。默认情况下,eng
build 中使用 zedboot
。由于 zedboot 用于铺设 Fuchsia 系统,因此它提供了调试端口和其他用于恢复系统的设施。
在 userdebug
和 user
中,使用了不同的恢复映像,该映像最小且符合最终用户产品的安全要求。
属性 | eng | userdebug、user |
---|---|---|
恢复 (R) | zedboot | 极小恢复映像 |
软件包和更新
自动更新软件包
在 eng
build 类型中,auto_update_packages
默认处于启用状态。因此,在解析组件(即通过运行组件)时,系统会先尝试通过 fuchsia.pkg.PackageResolver
更新组件的软件包。
在日常开发中,此功能非常有用,可确保系统始终运行开发者环境中的最新组件。
对于 userdebug
和 user
build,此功能处于停用状态。对组件和软件包的任何更改都必须通过系统更新完成,系统更新会更改 base
系统中的软件包并触发重新启动。
属性 | eng | userdebug、user |
---|---|---|
auto_update_packages | true | false |
软件包变种
软件包变种用于指定软件包的 eng
变种,该变种包含组件的 eng
变种。然后,该软件包会包含在用于定义 eng
build 类型的产品配置中。
例如:
package_flavor_selections += [
{
name = "my_component_pkg"
flavor = "eng"
},
]
同样,该软件包的 user
变种包含在产品的 user
build 中。
系统更新
Fuchsia 使用无线下载 (OTA) 更新机制来运行系统更新。有两个入口点,即 omaha-client
或 system-update-checker
组件:
属性 | eng | userdebug、user |
---|---|---|
自动系统 OTA | false | true |
更新检查工具 | system-update-checker |
omaha-client |
Omaha 配置 | 不适用 | 已定义 |
Omaha 配置定义了用于执行系统更新的服务器端配置,适用于 userdebug
和 user
等最终用户 build。
Omaha 配置包含存储在 VBMeta
中的信息,以确保在执行之前验证软件的完整信任根。
软件包集、可运行组件和许可名单
Fuchsia 开发板和产品定义会扩充三个依赖项列表:Base、Cache 和 Universe。因此,这些集合中定义的软件包决定了它们在 Fuchsia 中的管理方式。
例如,只能通过系统 OTA 更新更改 base
集中的软件包。因此,需要重启系统。
由于 universe
集允许访问整个 Fuchsia 软件集,因此不允许在 user
build 中使用。
属性 | eng | userdebug | user |
---|---|---|---|
可用套装 | base、cache、universe | base、cache、universe | 基础 |
许可名单 | 允许所有软件包 | 基准 + 许可名单 | 仅限基础 |
许可名单是一种政策,用于确定哪些组件可以运行(基于组件网址),或哪些组件可以在运行时访问特定服务。例如,这对于确保 user
build 不会运行适用于 eng
build 的开发组件或服务非常有用。
在另一个示例中,userdebug
build 允许运行一组有限的工具来检查系统,例如 iquery
用于检查正在运行的组件的属性。
在 user
中,仅允许使用运行产品所需的软件。在当前设计中,此软件仅限于 base
集中包含的内容。
软件来源
Fuchsia 软件通过托管在软件代码库中的软件包提供。这些软件源必须为 Fuchsia 所知,并且通过信任链进行加密验证。
对于 eng
build,系统在运行时可添加哪些软件源没有任何限制。
对于 userdebug
build,只有在目标系统通过直接接口连接到开发者的宿主工作站时,才能添加软件源。
user
build 中的软件源是固定的,无法修改。
调试、日志和 Shell
eng
build 支持对 Fuchsia 系统的完整访问,并提供所有调试端口和日志。user
build 会限制所有访问权限和日志,而 userdebug
似乎只会出于调试目的启用有限的访问权限。
属性 | eng | userdebug | user |
---|---|---|---|
ssh | 已启用 | 已启用 | 已停用 |
serial | 已启用 | 只读引导加载程序和内核 | 引导加载程序中的 r/o |
debug_agent | 已启用 | 已停用 | 已停用 |
k 命令 | 已启用 | 已停用 | 已停用 |
ffx 运行时 | 已启用 | 已启用 | 已停用 |
崩溃报告
fuchsia.feedback
API 提供崩溃报告服务。默认情况下,系统会为 eng
build 停用崩溃数据上传功能。对于 user
和 userdebug
build,必须明确征得用户同意才能启用崩溃报告上传功能。
默认情况下,系统仍会为所有 build 捕获崩溃报告并将其存储在本地崩溃报告数据库中。
属性 | eng | userdebug、user |
---|---|---|
崩溃报告 | 已启用 | 已启用 |
崩溃问题上传 | 已停用 | 经用户同意 |
崩溃数据上传内容包括系统和内核日志文件,以及有助于问题分类的组件检查数据。这些数据文件可能包含个人身份信息 (PII),并会在上传前进行清除。
遥测
Fuchsia 平台提供了一项服务,用于记录、收集和分析指标。此服务由 fuchsia.metrics
提供。Cobalt 的两个主要支柱是保护用户隐私,以及提供高质量的汇总指标来满足系统和组件软件开发者的需求。
属性 | eng | userdebug、user |
---|---|---|
指标收集 | 已启用 | 已启用 |
指标上传 | 已启用 | 经用户同意 |
经过验证的执行
经过验证的执行是 Fuchsia 安全的核心设计,可确保所有已执行代码都是可信的。可信度是通过对哈希值的验证以及对可信实体数字签名的验证递归断言的,从不可变的信任锚点开始。
启动时验证
启动时验证是经过验证的执行阶段,在此阶段,引导加载程序会验证 Fuchsia zbi
是否可信,以便由引导加载程序执行。
本地 build(无论是 eng
、userdebug
还是 user
)使用树内开发密钥,而用于发布的 build 由从安全密钥管理服务获取的更安全的密钥签名。
预构建的系统映像
预构建的 eng
映像可在 Fuchsia SDK
中获得,而 userdebug
和 user
build 可直接从 Fuchsia Global Integration builders 下载。
构建时优化
Fuchsia 平台的常规 build 优化标志在所有 build 类型中保持不变,以便在各个 build 中保持一致。
在 eng
build 中,is_debug
设为 true
,这会将默认标志设为 debug
,而不是像 user
和 userdebug
build 中所设的 speed
。这些标志会在全局 BUILD.gn
文件中的各种配置中传递和使用。
对于组件,eng
软件包变种可以包含使用特殊标志编译的组件。例如,开发者 build 和聊天机器人配置中通常会启用 DCHECK
断言,以帮助捕获 C++ 组件中的意外问题。
性能
我们了解到,与 userdebug
build 相比,eng
build 可能会导致性能下降,但实际下降幅度因产品和开发板类型而异。主要影响来自于在平台中启用额外的断言。这使用 /zircon/system/ulib/perftest
进行测试。
在组件中,如果启用了 DCHECK
的 eng
变种在基准测试和测试期间被大量使用,也会对性能产生重大影响。
userdebug
build 和 user
build 之间的性能差异非常小。在对性能进行基准测试时,请优先使用 userdebug
build,而不是 eng
build。此方法存在缺点,详见下文的缺点部分。
安全注意事项
在设计 Fuchsia build 类型时,我们非常注重安全影响。我们在整个过程中都采用以下方法,为所有用户强制执行最高级别的安全保障:
利用经过验证的执行,从启动开始建立完整的经过验证的信任链,并使用单独的签名密钥进行加密签名。
利用组件框架中的许可名单安全政策,确保仅解析和执行允许的组件。
仅包含最终用户 build 所需的软件包和组件。
在最终用户 build 中停用所有访问端口和设施。
隐私注意事项
在设计 Fuchsia build 类型时,我们也非常重视隐私保护注意事项。最终用户 build 中的所有日志都会经过清理以去除个人身份信息,并且必须征得用户同意才能上传崩溃、日志和指标。
文档
我们将在 Fuchsia > 概念 > 构建系统中进一步记录 build 类型,以便为 Fuchsia 中产品适用的不同属性和行为提供规范参考。
测试
模拟器
若要测试不同 build 类型的行为,最简单直接的方法是利用 Fuchsia 模拟器。
通过模拟器模拟 build 类型,开发者可以比较和测试平台和应用的不同行为。缺点是,目前无法在模拟器环境中测试系统的某些方面,例如系统更新或经过验证的启动属性。
发布流程
Fuchsia 利用 CI(持续集成) 和 CQ(提交队列)流水线,确保在 CL(更改列表)提交之前以及 CL 合并后的最终集成期间构建和测试代码更改。
CQ 流水线会在 CL 提交之前,针对不同的产品配置和环境构建和测试 CL。
CI 流水线会在不同的产品配置中构建和测试在同一集成提交中已签入的代码。
由于 build 类型也作为产品配置实现,因此所有 build 类型配置都会通过同一 CI/CQ 流水线同时构建、测试和发布。
请注意,只有 eng
build 类型的产品配置会在 CI/CQ 中进行测试。不过,user
和 userdebug
仍是持续构建流程的一部分。
设施
测试框架和设施在 eng
和 userdebug
build 中设置的宇宙中提供。这些服务默认处于停用状态,但在运行时会列入许可名单以供解析和执行。
对于 user
build,安全政策不允许启用测试设施,也不允许使用测试设施。
例如,Fuchsia 具有用于端到端测试的 SL4F
框架,以及用于组件框架测试的 test_runner
。
对于自动化测试用例,可以使用上述框架。不过,如果需要额外的软件包或额外的工具,建议使用 eng
build。
缺点、替代方案和未知情况
此 RFC 中记录的设计已实现,并反映了 Fuchsia 产品 build 类型的当前状态。
通过利用产品配置来实现 build 类型,您可以利用和重复使用现有实现。主要缺点是这种方法缺乏可伸缩性和灵活性。例如,对于每款新商品,至少需要有三个与三种 build 类型匹配的商品配置。这种方法的成本在于实现冗余性,以及 Fuchsia 基础架构中为这些新配置启动构建器所需的额外资源。
另一个缺点是测试 userdebug
build。由于 userdebug
build 包含特定变种的软件包、不同的系统更新配置,并且未启用调试标志,因此非常适合运行端到端测试。但由于安全限制,无法在官方 userdebug
build 中运行 SL4F。
作为替代方案,独立系统汇编提供了修改已组装映像的功能,并且可用于组装允许访问测试框架且限制较少的本地 userdebug
build。
未来,我们应采用更可扩缩的方法,以便在不同的产品配置中应用 eng
、userdebug
和 user
build 类型配置文件。这样可以避免出现线性扩缩问题,即新产品需要多个产品配置来适应 build 类型。
另请注意,当前的实现会混合产品和平台,这并不是 Fuchsia 平台的长期目标。如前所述,建议您日后考虑采用更灵活的设计。
在先技术和参考文档
Android 操作系统: