本文档介绍了在 Fuchsia 开发环境中使用 fx 工具的基本工作流程。
设置 fx
fx 是一组子命令的入口点,可简化许多与 Fuchsia 开发相关的任务。(运行 fx help 可查看所有可用的子命令。)
如果您使用 bash 或 zsh 作为 shell,强烈建议您运行 source scripts/fx-env.sh 以在 shell 中启用自动补全功能。此设置已通过测试,并经常与 bash 和 zsh 搭配使用,可能也适用于其他兼容的 shell。
前往您的 Fuchsia 代码库,例如:
cd ~/Fuchsia向 shell 添加配置以包含
fx-env.sh:echo "source \"$PWD/scripts/fx-env.sh\"" >> "$HOME/.$(basename "$SHELL")rc"(可选)如果您想要使用 Fuchsia 脚本中的其他便利工具,请运行:
echo "fx-update-path" >> "$HOME/.$(basename "$SHELL")rc"重启 shell:
exec "$SHELL"
这些步骤提供了最明确的功能集,并且通常不会造成侵入性影响。如果它导致 shell 环境中出现 bug,请提交项目 bug。
如果出于某种原因,您需要使用多个 Fuchsia 代码库(下面的推荐工作流程应该可以避免这种需求),那么您可能需要执行上述操作以外的其他操作。在这种情况下,有几种受支持的方法:
- 始终明确执行
$FUCHSIA_DIR/scripts/fx - 在特定 Fuchsia 目录下工作时,使用 direnv 或 dotenv 等工具将
$FUCHSIA_DIR/.jiri_root/bin添加到$PATH。
常用日常工具
在检出 Fuchsia 树后,您首先需要做的是构建 Fuchsia,然后将其安装到设备上。fx 提供了一些命令来帮助您完成此操作:
fx set配置 buildfx build执行 buildfx mkzedboot准备 Zedboot USB 驱动器fx serve提供 buildfx publish cache迭代缓存软件包fx ota更新目标fx test执行测试fx shell连接到目标 shell- 以及许多其他小任务
配置 build
首先,我们来配置 build。为此,您需要做出以下选择:
- 您需要哪种产品配置?
(不确定:尝试
workbench_eng) - 您要构建哪个开发板?(不确定:尝试
x64) - 您需要哪些额外的测试目标?(不确定:尝试
//bundles/tools,如果您正在开发功能,则可能需要//bundles/tests)
如果您已了解上述选择(如果您尚未阅读上述内容,请立即阅读),那么您就可以开始配置 build 了:
fx set workbench_eng.x64 --with //bundles/tests在结账流程中运行 fx set 后,除非需要修改后续的实参,否则无需再次运行。
fx set 将其配置存储在输出目录中的 args.gn 文件中。直接输出为 out/default。您可以使用 fx --dir <out_dir> set <set_args> 指定其他目录。
您可以使用 fx args 命令修改生成的 args.gn 文件,以创建更精细的配置。fx args 将在编辑器中打开 args.gn,让您进行更改并重新生成 build 图。
刚刚发生了什么?
- 您选择了产品
workbench_eng(运行fx list-products可查看其他产品配置的列表)。 - 您选择了
x64板,该板支持许多基于x64架构的典型板。(请注意,arm64板的互换性较差,在构建到arm64架构时,您很可能需要为fx set提供特定的板。运行fx list-boards可查看已知主板配置的列表。) - 您正在临时构建
tests作为universe软件包集的一部分。
软件包部署选项
--with 选项有三种变体,分别与软件包部署到 Fuchsia 设备的方式有关:--with-base、--with-cache 和 --with(表示 universe)。(请注意,fx set 还有一个 --with-host 选项,用于构建仅限主机的目标,例如基于主机的工具和库。)
那么,base、cache 和 universe 是什么?
配置最终会指定有助于构建输出制品(主要是映像和软件包存储库)的依赖项(主要是软件包)。相应 build 已参数化,可确定哪些依赖项(主要是软件包)会添加到哪些输出工件(映像或软件包存储库)中。这三个轴分别称为“基础”“缓存”和“宇宙”:
- 基础:添加到基础中的软件包会包含在 build 生成的系统映像中。它们包含在无线下载更新中,并且始终作为单个单元进行更新。基本软件包在运行时无法从设备中逐出 - 它们编码了配置的最小可能大小。
- 缓存:缓存中的软件包包含在系统映像中,但不包含在无线下载系统更新中,并且允许根据资源需求(例如磁盘空间压力)从系统中逐出。缓存中的软件包可以在有可用更新时随时更新,并且每个软件包都可以单独更新。这是“可选”软件,但最好能“开箱即用”。
- Universe:Universe 中的软件包是额外的可选软件包,可以按需获取和运行,但不会预先打包到任何系统映像中。
“board”和“product”配置会为每个软件包集选择一组预定义的成员。最常见的情况是,板配置指定了一组要添加到基本依赖项集中的启动关键驱动程序,例如,可以在缓存集中包含一些可选但常见的外围设备驱动程序。板配置还可以包括一些板特定的开发工具(更常见的是主机工具,而不是目标软件包),用于在“宇宙”中与板进行交互。产品配置会根据其所代表产品的定义和特征集,选择在基础、缓存或全集软件包集中添加更多或更少的软件。例如,音箱产品会向基础模块添加许多与音频媒体相关的软件包。工作台产品在基础产品中添加了各种 GUI、媒体和许多其他软件包。
主要产品配置
配置远不止以下这些,但以下三种配置尤为重要,您应熟练掌握:
bringup是一款特征集极简的产品,专注于实现非常简单且精简的体验。它的存在是为了提供快速构建和小型映像(主要用于网络启动),非常适合处理 Zircon 内核或特定于板的驱动程序和配置等非常底层的设施。它缺少大多数网络功能,因此无法在运行时添加新软件或自行升级。这也意味着,某些fx命令(例如fx serve和fx shell)无法与bringup产品搭配使用。core是一组最小的特征集,可安装其他软件(例如添加到“universe”依赖项集中的项)。它是所有更高级别产品配置的起点。它具有常见的网络功能,并且可以通过无线下载方式更新系统。workbench_eng是通用开发环境的基础,非常适合处理界面、媒体和许多其他高级功能。对于发烧友来说,这也是一个非常好的环境,可供他们尽情探索。
关键的其他 build 目标
fx set 的 --with 标志接受任意build 目标。为了方便起见,我们定义了许多软件包,其中包括各种常用的 build 目标。请务必熟悉以下软件包:
//bundles/tools包含各种最常用的开发者工具。这包括用于从命令行 shell 派生组件的工具、用于重新配置和测试网络的工具、用于发出 HTTP 请求的工具、用于调试程序的工具、用于更改音量的工具等。核心产品默认在 Universe 软件包集中包含//bundles/tools。//bundles/tests会导致构建所有测试程序。大多数测试程序都可以在设备上使用run-test-suite调用,也可以通过fx test调用。//bundles/kitchen_sink是一种会导致包含所有其他 build 目标的 build 目标。在测试核心变更的影响或对代码库进行大规模变更时,此功能非常有用。对于发烧友来说,这也是一种有趣的配置,因为它包含源树中的所有可用软件。请注意,kitchen sink 将生成超过 20GB 的 build 制品,并且需要在目标设备上至少有 2GB 的存储空间(大小估计值来自 2019 年第 1 季度)。
执行 build
如上所示,使用 fx set 配置 build 后,您可以使用 fx build 运行 build。此命令会构建所有必需的目标及其输出。
清理 build
您可以继续更改结账中的文件,然后运行 fx build 进行重建。如果存在之前构建的结果,构建系统会尝试减少工作量。使用之前构建结果的构建称为增量构建,通常比全新重建快得多。
更改配置不应导致增量 build 损坏,但由于构建系统的限制,这种情况在极少数情况下仍可能会发生。如果发生这种情况,请提交详细的 bug 报告,其中包含重现问题的任何步骤以及任何诊断信息(例如 build 日志)。然后使用以下命令进行恢复:
fx clean将清除所有 build 制品。fx clean-build等效于fx clean,然后等效于fx build。fx cleandead-build等效于fx cleandead,然后fx build
启用增量软件包重新构建
默认情况下,fx build 会为指定的产品配置构建所有软件包。
对于某些开发者工作流程,这是必需的,但对于许多其他工作流程,这过于繁琐。
如果您只是在迭代测试,则无需重新构建和重新发布所有临时(宇宙)软件包。
您可以通过向 ~/.bashrc 或等效项添加 export FUCHSIA_DISABLED_incremental=0 来启用增量重建。此变更会导致以下结果:
(
fx serve) fx-serve-ref 会监控 Fuchsia build 中创建或修改的软件包,并自动发布这些软件包。这样一来,您就可以从空树开始运行fx serve,并在工作时逐步发布更改。fx test仅构建运行所需的最低限度的目标。对于组件测试,这是软件包、其 GN 依赖项和//zircon。
请注意,fx build 的行为保持不变。
迭代缓存软件包
运行 fx build 除了编译和发布缓存软件包之外,还会触发完整的系统组装。如果您的工作流只需要迭代重建缓存软件包,运行 fx build 可能会过度消耗资源并导致速度变慢。
对于重建缓存软件包,您可以通过将 fx build 替换为 fx publish cache 来提高构建速度。在典型的开发工作流程中,它可能如下所示:
# Set up your workspace here.
$ fx serve
# Make changes to cache packages here.
# Rebuild and publish cache packages:
$ fx publish cache
# Restart your component, for example:
$ ffx component stop /core/your_component
$ ffx session restart
已知问题:重新启动 Fuchsia 模拟器不会导致组件从更新后的软件包运行。需要手动重启组件。
如需查看所有缓存软件包的列表,您可以运行 fx list-packages --cache。
构建特定目标
fx build 可以指定要构建的特定目标或文件的名称。
如果启用了实验性 build-with-labels 功能,则可以直接将 GN 标签传递给 fx build。例如,fx build //examples/hello_world 将为 Fuchsia 构建 //examples/hello_world:hello_world GN 目标,而 fx build --host //examples/hello_world 将为宿主机构建该目标。
如果未启用该功能,您还可以传递 GN 目标输出的 Ninja 目标路径。对于在默认工具链中定义的 GN 目标,GN 定义的 Ninja 别名看起来像没有 // 前缀的 GN 标签,因此 fx build examples/hello_world:hello_world 将在默认工具链中构建 GN 目标 //examples/hello_world 的输出。
不过,如果目标是在非默认工具链中声明的,您就必须猜测 Ninja 输出路径,这通常非常棘手。不过,对于主机二进制文件,它通常位于 host_x64 子目录下。因此,如果目标仅定义为 executable(),则可以使用 fx build host_x64/blah 构建 //foo/bar:blah(//build/toolchain:host_x64)。
如需详细了解 build 目标,请参阅构建系统概览。
创建商品套装 ZIP 文件
如果您已构建 Fuchsia 产品(通过运行 fx build),则可以运行以下命令来创建包含产品软件包的 ZIP 文件:
fx create-pb-zip -o <path-to-pb-zip>此命令会在您指定的路径中创建一个包含产品包的 ZIP 文件。
构建并上传商品套装 ZIP 文件
fx build-and-upload 命令提供了一种便捷的方式,只需一步即可构建 Fuchsia、创建产品软件包 ZIP 文件并将其上传到 Google Cloud Storage (GCS) 存储分区。
fx build-and-upload默认情况下,此命令会将商品软件包上传到 gs://fuchsia-build-stage 存储分区。不过,您可以使用 --bucket(或 -b)标志指定其他 GCS 存储分区:
fx build-and-upload --bucket gs://<bucket-name>上传完成后,打印的 GS 网址可直接与 ffx 命令搭配使用,以刷写目标设备或启动模拟器,例如:
# Flash a target device
$ ffx target flash -b gs://fuchsia-build-stage/pb.zip
# Start the emulator
$ ffx emu start gs://fuchsia-build-stage/pb.zip -H
准备 Zedboot USB 驱动器
将 Fuchsia 刷写到目标设备上所需的具体准备工作因设备而异,但您可以使用 fx mkzedboot 为启动到 Zedboot 的 x64 设备准备可启动的 USB 驱动器。
什么是 Zedboot?
Zedboot 是 Zircon 的一种特殊配置,包含简单的网络栈、简单的设备广告和探查式协议,以及一套用于将 Fuchsia 写入目标磁盘和/或通过网络启动目标系统的协议。Zedboot 是一个术语,既指整个流程,也指一种特殊的 build 配置。许多人将其称为“带有 ASCII 图案的蓝屏”。
若要在 arm64 目标平台上进入 Zedboot,请在触发启动进入 fastboot 刷写模式时开启设备电源(通常这涉及在重新启动或开启电源时按住某个特定按钮,具体取决于特定硬件目标平台)。进入刷写模式后,在主机系统上执行 fx flash。
若要在 x64 目标平台上进入 Zedboot,请先使用 fx mkzedboot <path-to-usb-device> 生成 Zedboot USB 密钥(如需列出系统上合适的 USB 设备,请执行 fx list-usb-disks)。完成后,移除 USB 密钥,将其插入目标设备,然后重新启动目标设备,从启动选项或设备 BIOS 中选择“从 USB 启动”。
什么是网络启动?
在 Fuchsia 中,“netboot”是指将一组制品发送到 Zedboot 实例,该实例不会对磁盘进行更改,而只会从 RAM 启动。用户可以先使用 fx flash (arm64) 或 fx mkzedboot (x64) 将设备启动到 Zedboot,然后在主机系统上执行 fx netboot,从而执行“网络启动”。
提供 build
许多 Fuchsia build 配置都包含未立即包含在 build 生成的基础映像中的软件,这些软件在刷写期间写入设备。此类软件会按需提供给目标设备,通常俗称为“临时软件”。
命令 fx serve 在内部执行两项功能:
- 启动软件包资源库服务器,用于在运行时动态安装软件,以及进行全系统更新。
在内部,fx serve 命令还会搜索要配置的设备,并在发现设备后(可能会受到 fx set-device 或 fx -t 的限制/调制),将目标设备配置为使用代码库服务器作为动态软件包和系统更新的来源。
更新目标设备
如前几部分所述,Fuchsia 设备上有不同的软件组:
- 属于核心系统“基础”的一部分,通过单次交易进行更新的软件。
- 属于 Zedboot 映像(而非基础 [缓存])的一部分,可以临时更新的软件。
- 始终为临时性(universe)的软件。
对于新用户开发工作流程,用于协助更新目标设备的最通用命令是 fx ota。fx ota 命令首先会更新“基本”和“缓存”软件,然后在完成后重新启动目标设备。此流程的最终结果在软件版本方面应与全新刷写设备无异。
由于 fx ota 进程会导致设备重启,因此有时对于诊断、调试或其他非基于测试的工作流程或需求而言,它并不是最有效的流程。在这种情况下,用户可以通过多种方式确保设备上的软件定期更新。
fx serve 进程配置具有自动更新功能的 Fuchsia 软件代码库。每次更新底层代码库(在每次成功完成 fx build 时发生)时,代码库都会通知目标设备有新更新的软件。对于许多软件组件,在开发期间更新这些组件的最简单方法是确保它们不包含在基本集中,而是包含在“缓存”或“universe”中。在这种情况下,只需在目标上重启软件(例如,完全关闭软件或调用 killall),即可在软件再次启动时立即更新。
执行测试
Fuchsia 代码库包含许多测试。这些测试本身大多是组件,可以像其他组件一样在目标设备上启动。在目标设备上,某些程序还可以帮助解决组件启动方面的特定测试问题,例如 run-test-suite。还可以通过 fx test 从开发主机方便地控制该进程。如需了解详情,请参阅运行 Fuchsia 测试。
有些用户发现,高效的高专注度工作流程是让系统在每次保存源代码时都进行构建、推送和执行测试。使用 fx 可以非常轻松地实现这一点,例如:
fx -i test hello-world-rust-tests上述命令会在每次对树中的源代码进行更改时执行测试。fx 的 -i 标志会导致 fx 在每次更改树中的源代码时重复执行其命令的其余部分。由于 fx test 命令会先执行 build,然后在目标上执行测试,因此这种组合提供了一个便捷的自动测试循环,非常适合测试驱动开发等高度专注的工作流程。
连接到目标 shell
大多数产品配置都包含一个具有 Fuchsia 特定配置的 SSH 服务器。命令 fx shell 是一个便捷的封装容器,用于通过 SSH 连接到目标设备,并提供对非常简单的 POSIX 样式 shell 的访问权限。用户应注意,虽然 shell 是 POSIX shell 的分支,但它并不提供常见 Unix shell 的所有功能。特别是用户会发现 CTRL+C 有一些奇怪的特性,并且经常会发现子 shell 表达式和某些更高级的 IO 重定向或环境变量传播存在一些奇怪的特性。这些错误功能是 Fuchsia 不是 POSIX 系统的副作用。
不过,通过 fx shell 提供的 shell 对于在 Fuchsia 目标平台上强制执行程序以及探索文件系统树中提供的一些诊断 / 调试接口(例如 /hub 和 /dev)非常有用。它还可用于调用 /bin/run 等程序,这些程序可提供启动 Fuchsia 组件的功能。如果 tools 软件包在 build 配置中可用,则许多常见的 Unix shell 环境工具已移植并可供使用,例如 ps、ls、cat、curl、vim、fortune 等。
执行其他常见任务
获取日志
fx log 可捕获低级和高级程序(包括内核、驱动程序和其他用户空间程序)的所有日志。fx log 依赖于正常运行的高级网络堆栈和 SSH。因此,fx log 不适用于 Zedboot 或“启动”产品配置。如果设备处于 fx log 停止运行的状态,切换到 fx klog 通常有助于捕获有关可能原因的更多信息。
fx klog 仅捕获名为“klog”的低级别日志流。klog 流包含来自 Zircon 内核本身的日志,以及一部分用户空间软件(最值得注意的是驱动程序和低级核心软件)。fx klog 依赖于名为 netsvc 的轻量级网络堆栈,即使在更高级别的软件出现问题后,该堆栈也往往会保持可用状态。netsvc 套件也始终在“启动”产品配置中可用,因此在处理 Zircon 内核或驱动程序等低级软件时,fx klog 最有用。
如需了解详情,请参阅查看日志。
复制文件
fx cp 提供了一个围绕 scp 的基本封装容器,类似于 fx shell 围绕 ssh 的封装容器。
# copy ./book.txt from the host, to /tmp/book.txt on the target
$ fx cp book.txt /tmp/book.txt
# copy /tmp/poem.txt on the target to poem.txt on the host
$ fx cp --to-host /tmp/poem.txt poem.txt
使用多台 Fuchsia 设备
有些用户会在网络上拥有多个 Fuchsia 设备,并希望将各种命令的效果限制在这些设备中的特定设备上。fx set-device 命令可帮助您实现此用例。
fx set-device 命令会将特定设备节点名称绑定到特定 build 目录。当用户希望在多个 build 配置中保留多个不同的设备时,此功能特别有用,并且可以按如下方式进行设置:
$ fx --dir out/workbench set workbench_eng.x64
$ fx build
$ fx set-device <workbench-node-name>
$ fx --dir out/core set core.arm64
$ fx build
$ fx set-device <core-node-name>
# Start a server for the workbench:
$ fx --dir=out/workbench serve
# Set the default build-dir and target device to the arm64 core, and
# connect to a shell on that device:
$ fx use out/core
$ fx shell
此外,对于希望从当前默认 build 目录针对单个 Fuchsia 设备执行命令的用户,fx 全局标志 -d 允许针对单个命令调用替换目标节点名称。
重启设备
fx reboot
在某些设备(目前是大多数 arm64 设备)上,还有一些实用标志:
fx reboot -r重新启动到“恢复”模式 (Zedboot)fx reboot -b重新启动到“引导加载程序”(刷写)
确定 CL 的状态
您可以使用 fx cl 命令在 Gerrit 中通过新的浏览器标签页打开当前 CL。
调试和开发 fx 命令
fx -x-x标志会为fx脚本启用跟踪,并输出在fx调用期间评估的所有表达式。fx exec在当前fx环境中执行任意程序。例如,fx exec env会打印相应环境中的所有环境变量(fx exec env | grep FUCHSIA可能很有用)。
获取fx方面的帮助
fx help <command> 可提供有关相应命令的最佳入门文档。某些命令还支持并提供 fx <command> -h 或 fx <command> --help,但并非所有命令都提供此帮助。
这种情况并不常见,但属于实现细节。在内部,许多 fx 命令只是运行其他程序(通常是 build 生成的程序),并且在许多情况下,标志会原封不动地传递给这些程序。在这些情况下,传递常规的 -h 或 --help 标志可能不会提供 fx <command> 的文档,而是提供 fx 下游调用的程序的文档。
用户应始终以 fx help <command> 开头。
不带其他实参的 fx help 会提供 fx 中所有可用命令的列表,以及 fx 全局标志的文档。
显示待处理的提交
fx pending-commits 显示尚未回滚到全局集成的提交。
如需查看 Fuchsia 的集成信息中心,请参阅构建器。
将 Fuchsia 检出同步到发布分支
如需将本地 Fuchsia 代码库同步到特定发布分支,请运行以下命令:
fx sync-to RELEASE_BRANCH将 RELEASE_BRANCH 替换为您要切换到的发布分支(例如 refs/heads/releases/f6)。如需查看所有可用的发布分支的列表,请参阅 Fuchsia 全局集成代码库页面上的“分支”部分。
以下示例命令会将 Fuchsia 代码库同步到 F6 发布分支:
fx sync-to refs/heads/releases/f6
如需将 Fuchsia 代码库重置为树的顶部,请运行以下命令:
fx sync-to reset如需了解更多选项,请参阅fx sync-to参考页面。
定义持久性本地 build 实参
如果您想定义在每次运行 fx set 时都会包含的 build 实参,请将其添加到 $FUCHSIA_DIR/local/args.gn。在每次重新生成 build 实参时,它们都会附加到 $FUCHSIA_BUILD_DIR/args.gn。
如需禁止包含 local/args.gn,请运行 fx set ... --skip-local-args。