| RFC-0115:build 类型 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 产品 build 类型的规范定义。 |
| Gerrit 更改 | |
| 作者 | |
| 审核人 | |
| 提交日期(年-月-日) | 2021-07-06 |
| 审核日期(年-月-日) | 2021-07-21 |
摘要
本文档介绍了 Fuchsia 的不同产品 build 类型:eng、userdebug 和 user。
Fuchsia 中的 build 类型是指产品配置的 build 时和运行时设置:
构建时设置包括软件包、工具、签名配置和定义系统行为的标志。
运行时设置包括传递给运行中内核的标志,或根据 build 类型调节运行时行为的软件。
本文档旨在正式批准已在使用这些 build 类型的 Fuchsia 产品的设计决策。它还可作为 Fuchsia 平台中不同 build 类型的正式定义。
设计初衷
Fuchsia 定义了多种 build 类型,供包括开发者、测试人员和最终用户在内的各种用户使用。每个用户群组对正在运行的 Fuchsia 系统的行为都有一定的预期。
特定 build 类型会针对不同的使用情形(例如开发或交付给最终用户的产品)对某些 Fuchsia 系统行为进行编纂并提供保证。
此外,还可以根据产品 build 类型做出 build 时决策,例如是否包含特定软件包变种。如需了解详情和示例,请参阅软件包变种部分。
因此,不同的 build 类型为 Fuchsia 平台及其用户提供了必要的灵活性,从而支持 Fuchsia 产品的整个生命周期。
设计
本部分概述了 Fuchsia 上 build 类型的当前通用惯例。其中详细介绍了每种类型的不同属性以及适用的运行时限制。
由于复杂性和实现成本,我们还会考虑对所定义的 build 类型数量施加限制。如需了解详情,请参阅缺点部分。
根据 Fuchsia 的当前要求,有三种 build 类型:
useruserdebugeng
下文的定义部分将进一步说明 build 类型。
其他 build 类型需要提交提案,该提案需经过 RFC 流程并获得 Fuchsia 工程委员会 (FEC) 的批准。
目标
设计的主要目标是:
- 正式确定一种支持开发者需求以及最终产品发布要求的通用构建类型惯例。
- build 类型的实现方式尽可能相似,以避免产品行为出现额外的差异。
- build 类型以相同的标准和节奏发布和进行资格认证。
定义
user
user build 类型用于交付给最终用户的正式版设备。
对于 user build,平台在运行时强制执行最高安全保证,并在 build 时仅包含产品所需的组件。
userdebug
userdebug build 类型的行为与 user 相同(默认情况下),但允许进行额外的调试和插桩行为。
userdebug build 主要用于开发设备,以进行最终用户产品测试和资格认证。
eng
eng build 类型主要面向开发者和测试人员,并启动到产品 session 定义的完整产品体验。
各种产品配置的 eng build 可在树内找到,也可作为预构建的系统映像与 Fuchsia SDK 一起找到。
产品配置
build 类型定义为产品特定配置。为了在 build 类型之间保持相似性,这些配置会继承并包含来自 Fuchsia 核心产品的配置,并有选择性地添加或移除软件包和配置。
构建类型关系可总结如下:

图 1:作为产品配置的 build 类型。
注意:
eng build 类型继承自 core,并且可以包含特定于产品的其他软件包。
用户 build 类型直接继承 core,但会移除所有额外的软件包、调试功能和其他插桩属性。
userdebug 继承了 user,只是略有不同,可实现调试和插桩所需的额外功能。
userdebug 和 user 之间的反向继承可确保对 user 所做的任何最终用户产品所需的更改都会自动反映在 userdebug build 中。
该设计大致反映了产品周期,其中
eng是基于coreFuchsia 产品构建的第一个已定义产品配置。然后,当产品进入生命周期的后期阶段时,系统会定义userdebug和user,以反映这些使用情形和要求。
实现
以下部分记录了每个 build 类型的实现详细信息,这些信息按平台的主要领域进行整理。
断言
Zircon 是为 Fuchsia 提供支持的核心平台,由内核和一小部分用户空间服务、驱动程序和库组成。
整个代码库中使用了几种不同的类似断言的机制。有内核和 usermode 断言,这些断言会根据 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 配置定义了用于执行系统更新的服务器端配置,适用于最终用户 build,例如 userdebug 和 user。
Omaha 配置包含存储在 VBMeta 中的信息,以确保在执行之前验证软件的完整信任根。
软件包集、可运行组件和许可名单
Fuchsia 板和产品定义增强了三个依赖项列表:Base、Cache 和 Universe。因此,在这些集合中定义的软件包决定了它们在 Fuchsia 中的管理方式。
例如,对 base 集中的软件包所做的更改只能通过系统 OTA 更新来实现。因此,需要重新启动系统。
由于 universe 集允许访问整个 Fuchsia 软件集,因此在 user build 中不允许使用该集。
| 属性 | eng | userdebug | 用户 |
|---|---|---|---|
| 可用套装 | 基本、缓存、宇宙 | 基本、缓存、宇宙 | 基础 |
| 许可名单 | 允许所有软件包 | 基本 + 许可名单 | 仅限基础 |
许可名单是一种政策,用于确定哪些组件可以运行(基于组件网址)或哪些组件可以在运行时访问某些服务。这有助于确保 user build 不会运行专为 eng build 设计的开发组件或服务。
在另一个示例中,userdebug build 允许运行一组有限的工具来检查系统,例如 iquery,以检查正在运行的组件的属性。
在 user 中,仅允许使用运行产品所需的软件。在当前设计中,此软件仅限于 base 集中的内容。
软件来源
Fuchsia 软件通过托管在软件代码库中的软件包进行交付。这些软件来源必须是 Fuchsia 已知的,并且通过信任链以加密方式进行验证。
对于 eng build,对运行时可添加到系统的软件源没有任何限制。
对于 userdebug build,只有当目标系统通过直接接口连接到开发者的主机工作站时,才能添加软件源。
user build 中的软件来源是固定的,无法修改。
调试、日志和 Shell
eng build 可实现对 Fuchsia 系统的完全访问,并提供所有调试端口和日志。user build 会限制所有访问权限和日志,而 userdebug build 旨在仅启用有限的访问权限以用于调试。
| 属性 | eng | userdebug | 用户 |
|---|---|---|---|
| ssh | 已启用 | 已启用 | 已停用 |
| serial | 已启用 | 只读引导加载程序和内核 | 在引导加载程序中为只读 |
| debug_agent | 已启用 | 已停用 | 已停用 |
| k 命令 | 已启用 | 已停用 | 已停用 |
| ffx 运行时 | 已启用 | 已启用 | 已停用 |
崩溃报告
崩溃报告服务由 fuchsia.feedback
API 提供。默认情况下,对于 eng build,崩溃上传处于停用状态。对于 user 和 userdebug build,必须明确征得用户同意才能启用崩溃报告上传功能。
默认情况下,所有 build 仍会捕获崩溃报告并将其存储在本地崩溃报告数据库中。
| 属性 | eng | userdebug、user |
|---|---|---|
| 崩溃报告 | 已启用 | 已启用 |
| 崩溃上传 | 已停用 | allowed on user consent |
崩溃上传包括系统和内核日志文件,以及组件检查数据,有助于问题分诊。这些数据文件可能包含个人身份信息 (PII),因此在上传之前会进行清理。
Telemetry
Fuchsia 平台提供了一项用于记录、收集和分析指标的服务。此服务由 fuchsia.metrics 提供。
Cobalt 的两大支柱是保护用户隐私和提供高质量的汇总指标,以满足系统和组件软件开发者的需求。
| 属性 | eng | userdebug、user |
|---|---|---|
| 指标收集 | 已启用 | 已启用 |
| 指标上传 | 已启用 | allowed on user consent |
已验证的执行
经过验证的执行是 Fuchsia 安全性的核心设计,可确保所有执行的代码都是可信的。通过验证哈希和可信实体的数字签名(从不可变的信任锚开始),以递归方式断言可信度。
启动时验证
启动时验证是经过验证的执行阶段,在此阶段,引导加载程序会验证 Fuchsia zbi 是否受引导加载程序信任,可以由引导加载程序执行。
本地 build(无论是 eng、userdebug 还是 user)使用树内开发密钥,而为发布而生成的 build 则由从安全密钥管理服务获取的更安全的密钥签名。
预构建的系统映像
预构建的 eng 映像可在 Fuchsia SDK 中找到,而 userdebug 和 user build 可直接从 Fuchsia Global Integration 构建器下载。
构建时间优化
Fuchsia 平台的常规 build 优化标志在所有 build 类型中保持一致,以确保 build 之间的一致性。
在 eng build 中,is_debug 设置为 true,这会将默认标志设置为 debug,而不是像在 user 和 userdebug build 中那样设置为 speed。这些标志在全局 BUILD.gn 文件中的各种配置中传递和使用。
对于组件,eng 软件包变种可以包含使用特殊标志编译的组件。例如,DCHECK 断言通常在开发者 build 和 bot 配置中启用,以帮助捕获 C++ 组件中的意外问题。
性能
我们知道,与 userdebug build 相比,eng build 可能会导致性能下降,但实际降幅因产品和主板类型而异。主要影响来自在平台中启用额外的断言。此功能使用 /zircon/system/ulib/perftest 进行测试。
在组件中,启用 DCHECK 的 eng 风味也会在基准比较和测试期间大量使用这些组件时,对性能产生重大影响。
userdebug 和 user build 之间的性能差异非常小。在进行性能基准测试时,最好选择 userdebug build,而不是 eng build。此方法存在一些缺点,详见下方的缺点部分。
安全注意事项
在设计 Fuchsia build 类型时,我们充分考虑了安全隐患。我们始终采用以下方法来确保为所有用户提供最高级别的安全保障:
利用已验证的执行来建立从启动开始的完整已验证信任链,并使用单独的签名密钥进行加密签名。
利用组件框架中的许可名单安全政策,确保仅解析和执行允许的组件。
仅包含最终用户 build 所需的软件包和组件。
在最终用户 build 中停用所有访问端口和设施。
隐私注意事项
在设计 Fuchsia build 类型时,我们也充分考虑了隐私保护。最终用户 build 上的所有日志都会经过清理,以移除 PII,并且必须征得用户同意才能上传崩溃信息、日志和指标。
文档
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 中设置的 universe 中,测试框架和设施可用。这些服务默认处于未启用状态,但已列入许可名单,可在运行时进行解析和执行。
对于 user build,安全政策不允许启用测试设施。
例如,Fuchsia 具有用于端到端测试的 SL4F 框架和用于组件框架测试的 test_runner 框架。
对于自动化测试用例,可以使用上述框架。但如果需要其他软件包或其他工具,建议使用 eng build。
缺点、替代方案和未知因素
此 RFC 中记录的设计已实现,并反映了 Fuchsia 产品 build 类型的当前状态。
通过利用产品配置来实现 build 类型,可以利用并重复使用现有实现。这种方法的主要缺点是缺乏可伸缩性和灵活性。例如,对于每款新商品,至少需要三个与三种 build 类型相匹配的商品配置。这种方法会产生一些成本,包括实现中的冗余以及在 Fuchsia 基础架构中启动这些新配置的构建器所需的额外资源。
另一个缺点是需要测试 userdebug build。由于 userdebug build 包含特定风格的软件包、不同的系统更新配置,并且不启用调试标志,因此非常适合运行端到端测试。但由于安全限制,无法在正式版 userdebug 中运行 SL4F。
作为替代方案,独立系统组装功能可用于修改组装的映像,并可用于组装本地 userdebug build,以便访问测试框架并减少限制。
未来,我们应采用更具可扩缩性的方法,以便在不同的产品配置中应用 eng、userdebug 和 user build 类型配置文件。这样可以避免线性扩展问题,即新产品需要多个产品配置来适应 build 类型。
另请注意,当前实现融合了产品和平台,这并非 Fuchsia 平台的长期目标。 如上所述,建议您考虑在未来采用更灵活的设计。
在先技术和参考资料
Android 操作系统: