Codelab:定义和构建产品软件包

此 Codelab 介绍了如何使用 Bazel 构建系统在 Fuchsia 中定义和构建新的产品软件包。产品软件包是一种可分发的制品,其中包含刷写、更新或模拟 Fuchsia 产品所需的所有映像和元数据。

在此过程中,您还将定义产品配置,以指定构成产品的软件功能、设置和软件包。

前提条件

什么是产品配置?

Fuchsia 中的产品配置定义了特定产品的用户体验。它与指定硬件特定详细信息的板级配置不同。产品配置通常包括:

  • 平台设置:底层 Fuchsia 操作系统的设置(例如, build 类型、已启用的系统功能)。
  • 产品设置:特定于产品体验的设置(例如会话 shell、特定软件包)。

产品配置使用 BUILD.bazel 文件中的 fuchsia_product_configuration 规则进行定义。

编写产品配置

我们来了解如何定义产品配置并使用它来构建系统映像。

基本设置

商品配置主要是一个 JSON 对象(在 Starlark 中表示为字典),传递给 fuchsia_product_configuration 规则。

# //products/my_product/BUILD.bazel
load(
    "@rules_fuchsia//fuchsia:assembly.bzl",
    "fuchsia_product_configuration",
)

fuchsia_product_configuration(
    name = "product_config",
    product_config_json = {
        "platform": {
            "build_type": "eng",
            "feature_set_level": "standard",
        },
        "product": {},
    },
)

平台设置

配置字典中的 platform 键用于控制 Fuchsia 系统的各个方面。常见字段包括:

  • build_type:控制安全和优化级别。
    • eng:工程 build。此 build 最适合用于调试,因为它启用了断言并停用了优化。
    • userdebug:此 build 经过优化,与 user build 类似,但启用了一些调试功能和工具。
    • user:正式版 build。此 build 已完全优化,并且安全可靠。
  • feature_set_level:定义系统中包含的基本功能集。
    • embeddable:引导加载程序的最小子集。此版本针对内存受限的环境进行了优化,不会自行更新。
    • bootstrap:可启动,仅限串行。仅限 /bootstrap 领域。没有 netstack 或存储驱动程序。主要用于板级启动。
    • utility:具有 /core realm 的最小配置。最适合实用程序类型的系统,例如恢复。
    • standard:一种“完整 Fuchsia”配置。包括网络堆栈和自更新功能。这是默认值。
  • storage:配置文件系统(例如,Fxfs)和存储布局。

如需查看完整的平台设置列表,请参阅 PlatformSettings 文档

例如,包含平台设置的 Fuchsia 产品配置可能如下所示:

fuchsia_product_configuration(
    name = "product_config",
    product_config_json = {

        "platform": {
            "build_type": "eng",
            "feature_set_level": "standard",
            "storage": {
                "filesystems": {
                    "volume": "fxfs",
                },
            },
        },
        "product": {},

    },
)

产品设置

product 键用于更高级别的产品设置。

最重要的设置之一是会话。会话是定义产品用户体验(例如,图形界面外壳或主应用)的顶级组件。

如需使用会话,您必须指定其网址,并确保包含相应组件的软件包包含在基本软件包中。

基础软件包是指系统映像中包含的一组软件包。它们在启动时立即可用,不可变(只读),并作为系统 OTA 的一部分进行更新。

例如,包含产品设置的 Fuchsia 产品配置可能如下所示:

示例:

fuchsia_product_configuration(
    name = "product_config",
    product_config_json = {
        "platform": {
            "build_type": "eng",
            "feature_set_level": "standard",
        },

        "product": {
            "session": {
                "url": "fuchsia-pkg://fuchsia.com/my_session#meta/my_session.cm",
            },
        },
    },
    base_packages = [
        "//src/my_session:my_session_package",
    ],

)

如需查看完整的产品设置列表,请参阅 ProductSettings 文档

组装商品图片

获得 fuchsia_product_configuration 后,您可以使用 fuchsia_product 规则来组装最终的系统映像。此规则将产品配置与特定主板配置相结合。

load(
    "@rules_fuchsia//fuchsia:assembly.bzl",
    "fuchsia_product",
)

fuchsia_product(
    name = "image.x64",
    board_config = "//boards:x64",
    platform_artifacts = "//build/bazel/assembly/assembly_input_bundles:platform_eng",

    product_config = ":product_config",

)
  • board_config:指向主板配置目标。
  • platform_artifacts:指向要使用的平台工件 (AIB) 的软件包。

创建商品套装

如需在设备或模拟器上运行产品,您需要使用 fuchsia_product_bundle 规则将其打包到产品软件包中。

load(
    "@rules_fuchsia//fuchsia:assembly.bzl",
    "fuchsia_product_bundle",
)

fuchsia_product_bundle(
    name = "my_product.x64",
    product_bundle_name = "my_product.x64",

    main = ":image.x64",

)

此目标会生成 ffx product-bundle 命令所需的制品。

例如:

  • 在模拟器中运行

    ffx emu start my_product.x64
  • 刷入设备

    ffx target flash -b my_product.x64

向 build 系统注册

如需构建产品软件包,必须先向 GN 构建系统注册该软件包。这涉及到下列步骤:

桥接到 GN

Fuchsia 的 build 系统使用 GN,但您的产品软件包是在 Bazel 中定义的。您需要使用 bazel_product_bundle GN 模板来创建网桥。

在产品目录(例如BUILD.gn//products/my_product/BUILD.gn):

# //products/my_product/BUILD.gn
import("//build/bazel/assembly/bazel_product_bundle.gni")

bazel_product_bundle("my_product.x64") {
  testonly = true
  product_bundle_name = "my_product.x64"
  bazel_product_bundle_target = ":my_product.x64"
  bazel_product_image_target = ":image.x64"
  bazel_inputs_from_gn = [
    "//boards/x64:x64.bazel_input",
    "//build/images/flash:esp.bazel_input",
  ]
  allow_eng_platform_bundle_use = true
}

添加到许可名单

您可能需要将新商品添加到 //build/bazel/BUILD.gn 中的 bazel_action_allowlist,以免出现展示错误:

# //build/bazel/BUILD.gn
group("bazel_action_allowlist") {
  visibility = [
    # ...
    "//products/my_product:*",
  ]
  # ...
}

您可能还需要将其添加到 //build/BUILD.gn 中的 non_hermetic_deps 可见性列表中:

# //build/BUILD.gn
group("non_hermetic_deps") {
  visibility = [
    # ...
    "//products/my_product:*",
  ]
  # ...
}

此 GN 目标 (:my_product.x64) 现在表示 GN 构建图中的 Bazel 产品软件包。

添加到可供购买的商品

最后,将此新的 GN 目标添加到 //products/BUILD.gn 中的产品包全局列表中,以便 fx 可以发现它:

# //products/BUILD.gn
group("product_bundles") {
  testonly = true
  deps = [
    # ... other products
    "//products/my_product:my_product.x64",
  ]
}

构建产品

Fuchsia 支持多产品 build,这意味着您可以在同一 build 目录中提供多个产品。

配置 build

使用 fx set 配置构建环境。您应使用启用 Bazel 构建系统的产品配置,例如 fuchsia.x64

fx set fuchsia.x64

设置主要商品

如需处理特定商品,请将其设置为“主要”商品套装。此命令可将 fx 工具配置为默认以您的产品为目标:

fx set-main-pb my_product.x64

构建产品

如需构建当前所选的主要产品(及其依赖项),请执行以下操作:

fx build

如果您想明确构建特定产品套装,无论主要设置如何,都可以执行以下操作:

fx build my_product.x64

切换产品

您可以随时切换有效的“主要”商品套装,而无需再次运行 fx set,只需再次运行 fx set-main-pb 即可:

fx set-main-pb minimal.x64

GN 实参与汇编

在多产品 build 环境中,所有产品共享相同的 GN 实参(由 fx set 定义)。因此,您无法使用 fx set ... --args 来配置特定于产品的功能。相反,所有产品配置都必须通过 fuchsia_product_configuration Bazel 规则完成,如本 Codelab 中所示。

后续步骤

此 Codelab 介绍了定义和构建新产品包的基础知识。

如需继续学习,您可以: