RFC-0106:Fuchsia SDK 中包含的组件清单

RFC-0106:组件清单包含在 Fuchsia SDK 中
状态已接受
领域
  • 组件框架
说明

创建一个组件清单,在 SDK 中包含分片 sysroot,并将其分发给树外集成商。

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2021-05-12
审核日期(年-月-日)2021-06-23

摘要

本文档建议将组件清单分片添加到 集成商开发套件 (IDK)。这样就能创建一个标准选项 用于将组件清单分片发布给树外 (OOT) 开发者,以及 建立一种通用模式,使清单分片可在不同平台之间移植 开发者环境

读者应熟悉以下内容:

设计初衷

跨环境协调工作流

自推出以来,组件清单分片和 include 语法 cmlcmx获得了广泛采用。它们用于 减少样板文件封装实现详情 简化开发者工作流程 核心领域变体

目前,处理清单包含的机制依赖于来源 Fuchsia 树的布局。这适用于位于 Fuchsia 树,但无法很好地移植到 OOT 开发。以示例为例 C/C++ 组件日志记录指南。该指南的打开者 指示开发者将以下内容添加到其组件清单中:

{
  include: [ "sdk/lib/diagnostics/syslog/client.shard.cml" ],
}

不过,本指南指出,上述内容仅适用于树内 (IT) 资源。自开支以来 开发者也是本指南的目标受众群体,本指南会指导 将这些开发者改为将以下内容添加到其组件清单中, 来有效地内联分片的内容:

{
  use: [
    { protocol: "fuchsia.logger.LogSink" },
  ],
}

其他地方也存在同样的问题。例如,测试运行程序 框架测试运行程序目录(用于支持各种 在 Fuchsia 上运行的测试类型,例如 C/C++ GoogleTest、Rust libtest、gotest 等)提供的说明仅适用于 IT 人员。这阻碍了 面向 OOT 开发者的良好测试做法。

这种折衷不符合将清单分片包含在第一个 因为客户会看到 Fuchsia 日志记录的实现细节。 此外,它还增加了在组织内编排大规模更改的难度, 如计划未来软过渡到其他协议, 从组件发布日志。最后,这增加了 IT 部门和 OOT 之间的阻力 开发者工作流程

掩盖实现细节

如果我们回顾 LogSink 分片示例,建议使用 Syslog 的客户端 库添加此碎片,因为它会将 确保该客户端库正常运行所需的功能

目前,这组功能非常简单,只包含单个协议, 预计将来会发生变化例如,不使用当前的 该协议中,客户端将套接字连接到 Syslog,然后缓冲字符 写入该套接字,以记录这些消息,我们可能会引入一个系统, 转换为 VMO,并在客户端和服务器之间 这与目前的跟踪功能没有区别。

遮盖分片后面的这些细节可以减少 而只想写入 syslog(由其开发的 而并不关心这些细节。但这也让 Syslog 维护人员无需 需要组件所有者注意

这同样适用于相反的方向(从 组件(而非使用它们)以及不同类型的功能 (例如目录功能,而非 协议功能)。例如 检查发现和托管指南。指南 解释了开发者必须将以下内容添加到其组件中: 清单:

{
    capabilities: [
        {
            directory: "diagnostics",
            rights: [ "connect" ],
            path: "/diagnostics",
        },
    ],
    expose: [
        {
            directory: "diagnostics",
            from: "self",
            to: "framework",
        },
    ],
}

或者,开发者也可以直接添加一个分片。这样,开发者就能 从 14 行样板代码开始,无需处理模糊的概念 例如,向框架公开目录功能(大部分功能 而无需开发者熟悉的组件) 以便日后根据需要更改此机制。最后,如果分片可以 可在 IT 和 OOT 组件清单之间进行移植,那么检查指南就是 明显要短得多,因为这样就不需要指定单独的 面向 IT 和 OOT 开发者的说明。

简化系统功能的使用

另一个更复杂的示例是 使用 Web 引擎时需要,直接作为 FIDL 客户端使用 而不是像上个示例那样通过客户端库使用Web 运行时 功能强大且稳健,现在的 Web 应用能够执行许多 特权设备操作。 fuchsia.web 定义了 Web 提供的 引擎实现需要能够托管某些 Web 应用。

为了简化环境中的相同功能使用,并 再将它们提供给 Web 引擎,我们就会将这些文件分成多个碎片, 功能。例如,此分片定义了一个基准, 一组“基本要求”功能:

{
    "sandbox": {
        "services": [
            "fuchsia.device.NameProvider",
            "fuchsia.fonts.Provider",
            "fuchsia.intl.PropertyProvider",
            "fuchsia.logger.LogSink",
            "fuchsia.memorypressure.Provider",
            "fuchsia.process.Launcher",
            "fuchsia.sysmem.Allocator",
        ]
    }
}

此分片定义了 Web 应用需要的其他功能, 不是本地且/或需要网络:

{
    "sandbox": {
        "services": [
            "fuchsia.net.name.Lookup",
            "fuchsia.net.interfaces.State",
            "fuchsia.posix.socket.Provider"
        ]
    }
}

然而,若要在风景视图中渲染此 Web 应用,必须使用此分片:

{
    "sandbox": {
        "services": [
            "fuchsia.accessibility.semantics.SemanticsManager",
            "fuchsia.ui.input.ImeService",
            "fuchsia.ui.input.ImeVisibilityService",
            "fuchsia.ui.scenic.Scenic"
        ]
    }
}

还存在其他分片,例如,用于解锁硬件加速 或用于硬件媒体编解码器

其中包含的信息量非常重要。将它存储在自己的分片中是 这比将其添加到组件 沙盒此外,这也让进化变得更加简单。

请注意,这只是一个假设示例。这些碎片现存在于 IT 环境中。这是 探索如何将这些碎片移到 IDK 中 提供开箱即用,不保证一定能做到。此外,上述碎片的内容 仍处在变化之中,此处仅作说明之用,并非作为参考 文档。

实现

将清单分片打包到 IDK 发行版中

通过设置 include 指令,可实现以 Fuchsia 为目标的 C/C++ 开发 路径(通过 --include-directory 向编译器指定)-I 标志)添加到一个或多个包含特别嵌套的 以及子目录和头文件的层次结构这会使得代码包含 可在 IT 和 OOT build 之间移植的 Fuchsia 专用头文件。

例如,下面这行 C 代码在 IT 和 OOT 中都有效:

#include <lib/zx/process.h>

这是因为针对 Fuchsia 的 IT 版本和 OOT 版本都增加了 在目录下包含文件 lib/zx/process.h 的路径。在 Fuchsia 结账时对应的包含目录为 //zircon/system/ulib/zx/include/,而在 OOT build 中,此路径需要 设为 $FUCHSIA_SDK/pkg/zx/include/。另请参阅:IDK 布局

在 include 路径中设置目录以使 include 指令可移植是 也称为设置“sysroot”。

我们将以类似方式部署组件清单分片,在 $FUCHSIA_SDK/pkg/ 以下 与分片用途在概念上相关的子路径,以及 在 IT 和 OOT 中相应地在 cmc 中设置 --includepath 标志 build。

例如,上面用作示例的 Syslog 碎片可能是:

  • 其中包括:include: [ "syslog/client.shard.cml" ]
  • 发现 IT 位于 //sdk/lib/syslog/client.shard.cml 下,因此我们对其进行配置 通过--includepath $FUCHSIA_CHECKOUT/sdk/lib/支付 cmc IT 费用。
  • $FUCHSIA_SDK/pkg/syslog/client.shard.cml 下发现 OOT,因此 使用 --includepath $FUCHSIA_SDK_ROOT/pkg/ 配置 cmc 开箱即用。

可移植分片与本地分片

预计部分分片会提供给 OOT 开发者,而 而另一些则只能供 IT 人员使用。在上文中,我们查看了一些 开箱即可使用。一个只对 IT 有帮助的分片示例是 此分片用于共享大部分数据 两个组件定义之间的复杂功能路由,其中一个是 一个系统组件,另一个是该组件的测试替身。还有 此特定分片开箱没有用处。

因此,一些分片应变为可移植并在 IDK 中发布, 其他代码库应仅对特定代码库保持私有状态

我们提议使用相对和 绝对路径。清单 include 指令中应解析的路径 至可移植分片时,不应没有前导 //,例如 syslog/client.shard.cml。这些将针对分片的 sysroot 进行解析。 另一方面,指向特定代码库的纯本地分片路径 应以 // 开头,并针对以下项的源根目录(或结账根目录)进行解析: 自己的代码库 例如,此分片应通过 路径 //src/sys/test_manager/meta/common.shard.cml

构建系统与 cmc 集成

构建系统,如树内 GN &Ninja build 和 所有以 Fuchsia 为目标的树外 build,均已与 cmc 集成。此类 集成需要进行修改,以承受新的 include 行为。 特别是以下 cmc 子命令

  • compile
  • include
  • check-includes

cmc 的调用需要指定以下标志:

  • --includeroot:用于解析带有 // 前缀的 include 路径的路径。
  • --includepath:在 指定顺序(第一个匹配)。

分片为 SDK Atom

与其他 IDK 类似,分片将由构建系统包含在 IDK 中。 元素。我们将重复使用现有的 sdk_atom() 模板, 指定 id 参数。 IDK 布局

将分片添加到 IDK 的流程

分片可以指定可能与平台重叠的合同预期 。例如,syslog 分片引用了 Fuchsia 中的协议 命名空间 - fuchsia.logger.LogSink - Fuchsia 系统组件。因此,在 IDK 中发布分片将 被视为 API 和 SDK Atom,并且会通过 目前用于添加或修改 FIDL 文件的 以 IDK 的形式发布。您还可以使用 sdk_atom() 概念的 例如,首先将分片引入为“内部”(不是 分发 OOT),然后通过 现有流程

未来工作

端口:expect_includes()

Fuchsia 的 GN build 提供了一个模板,用于预测依赖组件 在其清单中加入某个分片(请参阅 本指南)。它的其中一项优势是 它会指示添加依赖项(例如客户端 以及将清单分片添加到其应用的 组件,确保其库能够访问 才能正常运行

IT 开发者对此给出了非常积极的反馈, 一些开发者表现出了兴趣。此模板或其概念 上传到使用 GN 元数据的 GN SDK,以及使用 Bazel 的 Bazel/Blaze SDK 切面或 Bazel 提供程序。

另请参阅:https://fxbug.dev/42156975

性能

此方案对运行时性能没有影响,因为所有工作都在 构建时间。

处理包括在构建时执行,这会增加一些额外的工作。不过,这属于正常现象 不影响干净 build 实际用时。根据以往的研究, 如果构建工作不在关键路径上,则通常不会 会导致构建延迟时间, 来源(例如 cmc 调用、fidlc 调用等) 关键路径上没有出现,因为这项工作可以很好地并行运行, 可以非常灵活地安排时间

例如,请考虑此项更改,其中 虽然有数千次调用,但 cmc 的速度加快了大约 300 毫秒 的 cmc 对构建实际用时没有影响。

工效学设计

已给予注意,确保清单包含机制简单易用 透明例如,可以生成 清单,其中 include 指令替换为所含文件的内容 (必要时传递)。

fx cmc include manifest --includepath $(fx get-src-dir)

这类似于在 C/C++ 源代码上运行 C 预处理器。 (请参阅:man cpp)。

此外,cmc 会生成易于排查的简单错误, 包括不常见的错误情况,如 include 循环。所有支持的错误 都经过了单元测试

cmc 工具本身已在 Fuchsia IDK 中捆绑为预构建版本。时间是 完全封闭,在没有任何外部依赖项的情况下运行。可以调用 而无需集成构建系统。

向后兼容性

选择新构建的 OOT 组件后,在 IDK 中更改分片会对它们产生影响 但不会影响旧版预构建。请务必注意 避免破坏性更改,并采用标准做法进行平台更改:软 多个版本的过渡、支持时段,以及 相关方。

与平台发展的所有问题一样,应对变更进行全面测试, 应对破坏性更改采取适当的管理方式 例如使用某种版本控制机制请注意,平台方面的问题 版本控制和此问题的子集,例如 FIDL 版本,此时保持打开状态,并且不在 此 RFC。

安全注意事项

组件清单定义功能路由和沙盒 对安全性的影响。但是,清单包含的目的不是 最终会生成一个不同的清单, 更符合人体工程学的要求。只要在 include 会得到处理,对安全性没有任何影响。

帮助开发者了解其清单会是什么样子 会对其进行处理,它们可以使用上面演示的 cmc include

测试

单元和集成已涵盖 cmc 中的现有功能 测试。cmc的测试覆盖率超过 90%,尤其是 include 子命令完成。需要对 Fuchsia 进行的任何未完成更改 系统将按照 SDK 的指示和预期对 IDK 集成或到 OOT 集成进行测试 团队。

IDK 中的组件清单应被视为任何其他 IDK 软件工件或工件

文档

include 语法已记录。

cmc include 命令通过 cmc help include 自行记录。

目前指导 OOT 开发者使用 对清单包含的替换项将会更新,不再使它 IT 开发与 OOT 开发之间的区别。

缺点、替代方案和未知问题

不进行任何操作

我们可以保持现状,代价是不解决所述的问题 。

将 IDK 中的分片整理为顶级工件

作为以各种可能情况发布组件清单分片的替代方法 IDK 中的位置,例如 $FUCHSIA_SDK_ROOT/pkg 下或 $FUCHSIA_SDK_ROOT/fidl(基于分片的逻辑关联), 还探索了为 组件清单分片。例如: $FUCHSIA_SDK_ROOT/component_manifests/。这与 .fidl 文件会整理到 $FUCHSIA_SDK_ROOT/fidl/ 下,也就是说, 按类型(即 FIDL 文件)汇总,而不是按其他逻辑关联汇总 (例如 pkg/async/pkg/memfs/pkg/zx/)。

根据 SDK 客户的反馈,此替代方案被拒绝,指出: 他们更喜欢 SDK 内容的逻辑关联,而不是 不同类型的文件分布在不同的基本目录中。可接受的设计 例如,将组件清单分片用于使用 Syslog 用于从使用 C++ 编写的组件向 syslog 写入内容的 C++ 头文件。

先验技术和参考资料

组件清单包含的灵感来自 C/C++ include。

cmc include 命令的灵感来源于 cpp 命令,该命令运行 C 预处理器,并输出后处理结果。请参阅: man cpp