构建系统

Fuchsia build 使用 Generate Ninja (GN),这是一个元构建系统,用于生成 Ninja 使用的 build 文件,后者会执行实际 build。构建系统提供了用于为特定产品配置 build 的工具,以及用于为 Fuchsia 目标构建代码的模板。

编译目标

您可以使用位于项目源代码中的 BUILD.gn 文件为 GN 定义各个构建目标。Fuchsia 构建系统会将模板作为 GN 导入项 (.gni) 提供给您,以便您声明 Fuchsia 工件,例如:

  • fuchsia_component():定义一个包含清单、程序二进制文件和资源的可执行组件
  • fuchsia_package():定义一个包含一个或多个组件以在软件包仓库中分发的软件包
  • fuchsia_test_package():定义包含测试组件的软件包。

以下是包含测试的简单组件软件包的 BUILD.gn 文件示例:

import("//build/components.gni")

executable("bin") {
  sources = [ "main.cc" ]
}

fuchsia_component("hello-world-component") {
  deps = [ ":bin" ]
  manifest = "meta/hello-world.cml"
}

fuchsia_package("hello-world") {
  deps = [
    ":hello-world-component",
  ]
}

fuchsia_component("hello-world-test-component") {
  testonly = true
  deps = [ ":bin_test" ]
  manifest = "meta/hello-world-bin-test.cml"
}

fuchsia_test_package("hello-world-tests") {
  test_components = [ ":hello-world-test-component" ]
}

由目标的名称和其 BUILD.gn 文件的路径组成的唯一标签用于标识可以参与 build 的所有内容。在上面的示例中,hello-world 目标的标签可能如下所示://src/examples/basic:hello-world

build 配置

GN 前端会根据所选的 Fuchsia 产品配置配置 build,收集 build 所需的所有必要软件包和组件。这些目标在源代码树中的各种 BUILD.gn 文件中定义。GN 步骤的输出是 build 目录中针对 Ninja 的一组经过优化的指令。

当您运行 fx set 命令来配置 build 时,构建系统会调用 GN。

fx set minimal.x64

每当您想要调整产品配置或 build 可用的软件包时,都应运行 GN 配置步骤。此外,每当当前配置中的某个 BUILD.gn 文件发生更改时,系统都会在构建期间自动调用 GN。

面板和产品

Fuchsia 构建系统将 Fuchsia 构建的基准配置定义为产品开发板的组合。这些元素共同构成了您提供给 fx set 的 build 配置。

开发板定义了 build 目标的架构,这可能会影响包含的驱动程序以及设备专用内核参数。

此 Codelab 以 x64 开发板为目标平台,该开发板支持在 x64 架构上运行的 Fuchsia 模拟器 (FEMU)。

产品定义了 build 生成的软件配置。此配置可能包括可用服务和面向用户的体验。

此 Codelab 以 minimal_eng 产品为目标平台。

构建

GN 构建配置完成后,Ninja 会使用生成的构建文件,并运行适当的编译、链接和打包命令来生成 Fuchsia 映像。

当您运行 fx build 命令以执行当前构建配置时,构建系统会调用 Ninja。

fx build

练习:构建 Minimal

在本练习中,您将从源代码构建 minimal_eng 产品配置,以便在 x64 模拟器开发板上运行。

配置 build

minimal 产品和 x64 开发板设置构建环境:

fx set minimal.x64

此命令会对产品 build 配置中定义的一组目标运行 GN,以生成 build 说明。它实际上不会执行构建操作,而是定义了可构建内容的参数。

检查 build 配置

配置 build 后,使用 fx list-packages 输出 build 知晓的一组软件包:

fx list-packages

这是一个实用工具,可用于确定您需要的软件包是否已正确包含在 build 配置中。

构建 Fuchsia Minimal

使用 fx build 构建最小目标:

fx build

重启模拟器

  1. 运行以下命令可关闭您当前打开的所有模拟器实例:

    ffx emu stop --all
  2. 启动新的模拟器实例:

    ffx emu start --headless

    启动完成后,模拟器会输出以下消息并返回:

    Logging to "$HOME/.local/share/Fuchsia/ffx/emu/instances/fuchsia-emulator/emulator.log"
    Waiting for Fuchsia to start (up to 60 seconds)........
    Emulator is ready.
    

检查设备

打开另一个终端窗口,然后运行以下命令以输出设备目标的详细信息:

ffx target show

查找目标输出的 build 配置:

Version: "2000-01-01T12:00:00+00:00"
Product: "minimal_eng"
Board: "x64"
Commit: "2000-01-01T12:00:00+00:00"

请注意,该配置指向您刚刚在机器上完成的 build。

现在,您正在运行自己的 Fuchsia build!

练习:运行代码库服务器并分发软件包

在本练习中,您将运行代码库服务器,以将 universe 中提供的软件包分发到模拟器上运行的 Fuchsia 目标。

如需详细了解代码库和不同的软件包集,请参阅 RFC-0212 软件包集

例如,运行 ffx debug connect 将会失败,因为目标需要公开 fuchsia.debugger.Launcher capability 的组件。此方法可在 minimal.x64universe 集中的 debug_agent 软件包中使用。

列出“universe”集中的软件包

运行 fx list-packages 以列出 universe 集中的软件包。对于 minimal.x64,只有一个软件包:

fx list-packages --universe

输出仅显示 debug_agent 软件包。debug_agent 包含一个提供 fuchsia.debugger.Launcher 功能的组件。在后续步骤中,我们将通过启动调试程序来演示此功能。

启动代码库服务器并将其注册到 Fuchsia 目标

fx serve 命令会启动代码库服务器并将其注册到目标。

$ fx serve

如果命令成功运行,您将看到以下输出:

2024-05-20 12:51:03 [serve] Discovery...
2024-05-20 12:51:07 [serve] Device up
2024-05-20 12:51:07 [serve] Registering devhost as update source
Serving repository '/usr/local/google/home/amituttam/fuchsia/out/minimal.x64/amber-files' to target 'fuchsia-emulator' over address '[::]:8083'.

让此命令在前台运行。如需在详细模式下运行,请将 --verbose-v 标志传递给 fx serve

练习:运行调试程序并列出正在运行的进程

代码库服务器运行后,并将 Fuchsia 目标配置为从该代码库解析软件包,我们就可以运行一个命令来解析软件包并运行其中的组件。

首先,我们运行日志,以便了解发生了什么:

ffx log --filter debug_agent

在单独的终端中运行上述命令,输出将为空。让该命令保持运行状态。在这里,我们过滤 debug_agent,因为系统需要解析该软件包才能运行调试程序。

在另一个终端中,将调试程序连接到正在运行的系统:

ffx debug connect

该命令应启动 zxdb 并将您置于交互式 shell 中。如果您切换回运行 ffx log 的另一个终端,则会看到类似以下内容的输出:

[01949.544917][pkg-resolver] INFO: attempting to resolve fuchsia-pkg://fuchsia.com/debug_agent as fuchsia-pkg://devhost/debug_agent with TUF
[01949.624075][pkg-resolver] INFO: updated local TUF metadata for "fuchsia-pkg://devhost" to version RepoVersions { root: 9, timestamp: Some(1715399460), snapshot: Some(1715399460), targets: Some(1715399460) } while getting merkle for TargetPath("debug_agent/0")
[01949.835760][pkg-resolver] INFO: resolved fuchsia-pkg://fuchsia.com/debug_agent as fuchsia-pkg://devhost/debug_agent to 3f9783abed30d70b72d5f0730bd6e6033481073126aac0b74cbbf2d14909497e with TUF
[01949.882891][debugger] INFO: [main_launcher.cc(182)] Start listening on FIDL fuchsia::debugger::Launcher.

在这里,系统会尝试解析 debug_agent 软件包,并且能够从配置的 devhost 代码库中执行此操作。解析软件包后,系统会启动监听调试程序启动器协议的组件。

返回 zxdb,您现在可以运行 ps 来查看系统上正在运行的进程列表。

[zxdb] ps
 j: 1033 root
   p: 1102 bin/component_manager
   j: 1649
     j: 1780 bootstrap/console fuchsia-boot:///console#meta/console.cm
       p: 1822 console.cm
     j: 1989 bootstrap/archivist fuchsia-boot:///archivist#meta/archivist.cm
       p: 2051 archivist.cm
     j: 2064 bootstrap/console-launcher fuchsia-boot:///console-launcher#meta/console-launcher.cm
...