RFC-0115:build 类型

RFC-0115:build 类型
状态已接受
区域
  • 系统
说明

产品 build 类型的规范定义。

Gerrit 更改
作者
审核人
提交日期(年-月-日)2021-07-06
审核日期(年-月-日)2021-07-21

摘要

本文档介绍了 Fuchsia 的不同产品 build 类型: enguserdebuguser

Fuchsia 中的 build 类型是指产品配置的构建时间和运行时设置

  • 构建时间设置包括软件包、工具、签名配置和定义系统行为的标志。

  • 运行时设置包括传递给正在运行的内核的标志,或根据 build 类型调整运行时行为的软件。

本文档旨在正式批准已为使用这些 build 类型的 Fuchsia 产品做出的设计决策。它还用作 Fuchsia 平台中不同 build 类型的正式定义。

设计初衷

Fuchsia 定义了多种 build 类型,供包括开发者、测试人员和最终用户在内的各类用户使用。这些用户群体中的每一个都对正在运行的 Fuchsia 系统的行为有一定的预期。

特定的 build 类型会针对不同的使用情形(例如开发或向最终用户发货的产品)对某些 Fuchsia 系统行为进行编纂和保证。

此外,还可以根据产品 build 类型做出构建时间决策,例如包含特定 软件包变种。如需了解详情 和示例,请参阅软件包变种部分。

因此,不同的 build 类型为 Fuchsia 平台及其用户提供了必要的灵活性,以支持 Fuchsia 产品的完整生命周期。

设计

本部分概述了 Fuchsia 上 build 类型的当前通用惯例。它详细介绍了每种类型的不同属性以及适用的运行时限制。

由于复杂性和实现成本,在定义 build 类型的数量时,也需要考虑限制。如需了解详情,请参阅 缺点部分。

就 Fuchsia 的当前要求而言,有三种 build 类型:

  • user
  • userdebug
  • eng

build 类型将在下方的 定义 部分中进一步说明。

其他 build 类型将需要提案,该提案需要经过 RFC 流程并获得 Fuchsia 工程 委员会 (FEC) 的批准。

目标

设计的主要目标是:

  • 正式确定 build 类型的通用惯例,以满足开发者需求以及最终产品发货要求。
  • 尽可能以相似的方式实现 build 类型,以避免产品行为出现额外的差异。
  • 以相同的标准和节奏发布和限定 build 类型。

定义

user

user build 类型用于发货给最终用户的生产设备。

对于 user 构建,平台在运行时强制执行最高安全保证,并且在构建时间期间仅包含产品所需的组件。

userdebug

默认情况下,userdebug build 类型的行为与 user 相同,但允许 额外的调试和插桩行为。

userdebug build 主要用于开发设备,以进行最终用户产品测试和限定。

eng

eng build 类型主要面向开发者和测试人员,并启动 到产品会话定义的完整产品体验。

各种产品配置的 eng build 在树内提供, 并作为预构建的系统映像与 Fuchsia SDK 一起提供。

产品配置

build 类型定义为产品专用配置。为了保持 build 类型之间的相似性,配置会继承并包含 Fuchsia 的核心产品,并有选择地添加或移除软件包和配置。

build 类型关系可以总结如下:

build 类型。请参阅下文中的注释。

图 1:build 类型作为产品配置。

注意:

  • eng build 类型继承了核心产品,并且可以包含特定于产品的其他软件包。

  • user build 类型直接继承了核心产品,但移除了所有额外的软件包、调试功能和其他插桩属性。

  • userdebug 随后继承了 user,并且仅略有不同,以 启用调试和 插桩所需的其他功能。

  • userdebuguser 之间的反向继承可确保 最终用户产品所需的 user 的任何更改都会 自动反映在 userdebug build 中。

  • 该设计大致反映了产品周期,其中 eng 是基于 core Fuchsia 产品构建的第一个产品配置。然后,当产品进一步进入其 生命周期时,会定义 userdebuguser 以反映这些 使用情形和要求。

实现

以下部分记录了每个 build 类型的实现详细信息,这些信息按平台的主要区域进行整理。

断言

Zircon 是为 Fuchsia 提供支持的核心平台,由内核和一小部分用户空间服务、驱动程序和库组成。

整个代码库中使用了几种不同的类似断言的机制。内核和 用户模式断言 会 根据 build 类型启用或停用。例如,ZX_ASSERT 始终适用于所有 build 类型,并且必须更便宜,以避免影响性能。

再举一例,assert_leveleng build 中的 22,并启用 所有断言,而 userdebuguser build 中的 20,这会停用标准 C assert()ZX_DEBUG_ASSERT

下表概述了内核中的断言:

属性 eng userdebug, user
ASSERT 开启 开启
DEBUG_ASSERT 开启 关闭
assert() 开启 关闭

恢复分区

Fuchsia 最终用户产品使用 A/B/R 更新和恢复方案。

简而言之,系统通过无线下载 (OTA) 机制进行更新,利用 A/B 更新方案(其中存在两个系统副本,一个处于活跃状态,另一个处于非活跃状态)。这可确保系统在更新失败时具有回退机制。但是,如果回退无法启动,系统会尝试使用存储在恢复分区中的恢复映像来恢复系统。

每个产品都可以定义自己的恢复映像。默认情况下,在 eng build 中,会使用 zedboot。由于 zedboot 用于 铺设 Fuchsia 系统,因此它会提供调试 端口和其他设施来恢复系统。

userdebuguser 中,会使用不同的恢复映像,该映像是 最小的,并且满足最终用户产品的安全要求。

属性 eng userdebug, user
恢复 (R) zedboot 最小恢复映像

软件包和更新

软件包自动更新

eng build 类型中,auto_update_packages 默认启用 。因此,在解析组件时(即通过运行组件),系统会先尝试通过 fuchsia.pkg.PackageResolver 更新组件的软件包。

在日常开发中,此功能有助于确保系统始终运行开发者环境中的最新组件。

对于 userdebuguser 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-clientsystem-update-checker 组件:

属性 eng userdebug, user
自动系统 OTA false true
更新检查器 system-update-checker omaha-client
Omaha 配置 不适用 已定义

Omaha 配置定义了用于执行 系统更新的服务器端配置,该配置适用于最终用户 build,例如 userdebuguser

Omaha 配置包含存储在 VBMeta中的信息,以确保在执行之前验证软件的完整信任根 。

软件包集、可运行组件和许可名单

Fuchsia 板和产品定义扩充了三个依赖项列表: Base、Cache 和 Universe。因此,在这些集中定义的 软件包 决定了它们在 Fuchsia 中的管理方式。

例如,只有通过系统 OTA 更新才能更改 base 集中的软件包。因此,需要重启系统。

由于 universe 集允许访问整个 Fuchsia 软件集,因此在 user build 中不允许使用该集。

属性 eng userdebug user
可用集 base、cache、universe base、cache、universe base
许可名单 允许所有软件包 base + 许可名单 仅 base

许可名单是一种政策,用于 确定哪些组件可以运行(基于组件网址),或者 哪些组件可以在运行时访问某些服务。这有助于确保 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 已启用 引导加载程序和内核的只读权限 引导加载程序中的只读权限
debug_agent 已启用 已停用 已停用
k 命令 已启用 已停用 已停用
ffx 运行时 已启用 已启用 已停用

崩溃报告

崩溃报告服务由 fuchsia.feedback API 提供。默认情况下,eng build 会停用崩溃上传。对于 useruserdebug build,必须明确提供用户同意才能启用崩溃报告上传。

默认情况下,所有 build 仍会在本地崩溃报告数据库中捕获和存储崩溃报告。

属性 eng userdebug, user
崩溃报告 已启用 已启用
崩溃上传 已停用 经用户同意后允许

崩溃上传包括系统和内核日志文件,以及组件检查数据,以帮助进行问题分类。这些数据文件可能包含个人身份信息 (PII),并且在上传之前会经过清理。

Telemetry

Fuchsia 平台提供了一项服务,用于记录、收集和分析指标。此服务由 fuchsia.metrics 提供。 Cobalt 的两大支柱是保护用户隐私,以及提供高质量的汇总指标,以满足系统和组件软件开发者的需求。

属性 eng userdebug, user
指标收集 已启用 已启用
指标上传 已启用 经用户同意后允许

已验证执行

已验证执行是 Fuchsia 安全性的核心设计,可确保所有执行的代码都是可信的。可信度通过验证哈希和验证可信实体的数字签名以递归方式断言,从不可变的信任锚点开始。

启动时验证

启动时验证是已验证执行的一个阶段,在此阶段,引导加载程序 会验证 Fuchsia zbi 是否受 引导加载程序信任以供执行。

本地 build(无论是 enguserdebug 还是 user)使用树内 开发密钥,而为发布而生成的 build 则由从安全密钥管理服务获取的更 安全密钥进行签名。

预构建的系统映像

预构建的 eng 映像在 Fuchsia SDK 中提供,而 userdebuguser build 可直接从 Fuchsia 全球集成构建器下载

build 时间优化

Fuchsia 平台的常规 build 优化标志在所有 build 类型中保持不变,以保持 build 之间的一致性。

eng build 中,is_debug 设置为 true,这会将默认标志设置为 debug,而不是 在 useruserdebug build 中设置的 speed。这些标志在全局 BUILD.gn 文件中的 各种配置中携带和使用。

对于组件,eng 软件包变种可以包含 使用特殊标志编译的组件。例如, DCHECK 断言通常在开发者 build 和 bot 配置中启用,以帮助捕获 C++ 组件中的意外问题。

性能

可以理解的是,与 userdebug build 相比,eng build 可能会导致性能下降,但实际下降幅度因产品和板类型而异。主要影响来自在平台中启用额外的断言。这是使用 /zircon/system/ulib/perftest 进行测试的。

在组件中,启用 DCHECKeng 变种也会在基准测试和测试期间大量使用这些组件时导致显著的性能影响。

userdebuguser build 之间的性能差异很小。在对性能进行基准测试时,最好选择 userdebug build 而不是 eng build。这种方法存在一些缺点,这些缺点将在下方的缺点部分中说明。

安全注意事项

在设计 Fuchsia build 类型时,我们充分考虑了安全影响。我们始终使用以下方法来为所有用户强制执行最高级别的安全保证:

  • 利用已验证执行从启动开始建立完整的已验证信任链,并为加密签名使用单独的签名密钥。

  • 利用组件框架中的许可名单安全政策,确保仅解析和执行允许的组件。

  • 仅包含最终用户 build 所需的软件包和组件。

  • 停用最终用户 build 中的所有访问端口和设施。

隐私注意事项

在设计 Fuchsia build 类型时,我们还充分考虑了隐私注意事项。最终用户 build 上的所有日志都会经过 PII 清理,并且必须提供用户同意才能上传崩溃、日志和指标。

文档

build 类型将在 Fuchsia > 概念 > 构建系统 中进一步记录,以便为不同的属性和 行为提供规范参考,因为它们适用于 Fuchsia 中的产品。

测试

模拟器

测试不同 build 类型行为的最简单、最直接的方法是利用 Fuchsia 模拟器

通过模拟器模拟 build 类型,开发者可以比较和测试平台和应用的不同行为。 缺点是,目前无法在模拟器环境中测试系统的某些区域,例如系统更新或启动时验证属性。

发布流程

Fuchsia 利用 CI(持续集成) 和 CQ (提交队列)流水线,确保在 CL(更改列表)着陆之前以及在 CL 合并后的最终集成期间构建和测试代码更改 。

  • CQ 流水线会在 CL 着陆之前,跨不同的产品配置和环境构建和测试 CL。

  • CI 流水线会在同一集成提交中跨不同的产品配置构建和测试已签入的代码。

由于 build 类型也作为产品配置实现,因此所有 build 类型配置都通过同一 CI/CQ 流水线同时构建、测试和发布。

请注意,只有 eng build 类型产品配置作为 CI/CQ 的一部分进行测试。但是,useruserdebug 仍然是持续构建流程的一部分。

设施

测试框架和设施在 enguserdebug build 的 universe 集中提供。这些服务默认处于停用状态,但在运行时允许解析和执行。

对于 user build,测试设施未启用,也不受安全政策允许。

例如,Fuchsia 具有用于 端到端测试的 SL4F 框架和用于组件 框架测试的 test_runner

对于自动化测试用例,可以使用上述框架。但是,如果需要其他软件包或其他工具,建议使用 eng build。

缺点、替代方案和未知事项

此 RFC 中记录的设计已实现,并反映了 Fuchsia 产品 build 类型的当前状态。

通过利用产品配置来实现 build 类型,可以利用和重复使用现有实现。主要缺点是这种方法缺乏可伸缩性和灵活性。例如,对于每个新产品,至少需要三个与三个 build 类型匹配的产品配置。这种方法存在成本,即实现的冗余以及在 Fuchsia 基础架构中启动这些新配置的构建器所需的额外资源。

另一个缺点包括测试 userdebug build。由于 userdebug build 包含特定变种的软件包、不同的系统更新配置,并且不启用调试标志,因此非常适合运行端到端测试。但是,由于安全限制, 无法在官方 userdebug build 中运行 SL4F

作为替代方案,独立系统程序集 提供了修改程序集映像的功能,并且可以利用它 来程序集本地 userdebug build,这些 build 允许访问测试 框架并且限制较少。

将来,我们应利用更具可伸缩性的方法,允许将 enguserdebuguser build 类型配置文件应用于 不同的产品配置。这避免了线性扩缩问题,即新产品需要多个产品配置来适应 build 类型。

还值得注意的是,当前实现混合了产品和平台,这并非 Fuchsia 平台的长期愿望。如上所述,建议将来考虑更灵活的设计。

在先技术和参考文档

Android 操作系统:

  • 定义 enguserdebuguser build。
  • 发布了有关修改 userdebug build 的最佳实践指南