为 FIDL 做贡献

概览

FIDL 工具链大致由三个部分组成:

  1. 前端,也称为 fidlc
    • 解析并验证 .fidl 文件
    • 计算各种结构的尺寸、对齐方式和偏移
    • 生成 JSON IR(中间表示法)
  2. 后端
    • 可在 IR 上运行(C 后端除外)
    • 生成目标语言特定代码,该代码会关联到该语言的库
  3. 运行时库
    • 实现消息的编码/解码/验证
    • 方法调度机制

代码位置

编译器前端

前端位于 //tools/fidl/fidlc/,测试位于 //tools/fidl/fidlc/tests

编译器后端

目标 Codegen 运行时库 测试
HLCPP(旧版) /tools/fidl/fidlgen_hlcpp /sdk/lib/fidl/cpp (位于运行时库旁边)
新 C++ /tools/fidl/fidlgen_cpp /sdk/lib/fidl/cpp /src/lib/fidl/llcpp/src/lib/fidl/cpp
Go /tools/fidl/fidlgen_go /third_party/go/src/syscall/zx/fidl (位于运行时库旁边)
Rust /tools/fidl/fidlgen_rust /src/lib/fidl/rust (位于运行时库旁边)

适用于特定目标后端的支持代码位于 /tools/fidl/lib/fidlgen 中。

测试工具

GIDL

GIDL 是一种用于创建常规“一次编写,针对每个后端生成”程序的工具。目前,GIDL 用于生成编码或解码测试(“一致性测试”)以及基准。

路径 说明
/tools/fidl/gidl GIDL 工具本身的源代码和构建模板。
/src/tests/fidl/conformance_suite 用于测试一致性测试的定义(.fidl.gidl 文件)。
/sdk/ctf/tests/pkg/fidl/cpp/test/{test,handle}_util.h 运行时支持 HLCPP 一致性测试。
/src/lib/fidl/llcpp/tests/conformance/conformance_utils.h 运行时支持 C++ 传输类型一致性测试。
/src/lib/fidl/rust/gidl_util 对 Rust 一致性测试的运行时支持。
/third_party/go/src/syscall/zx/fidl/fidl_test 对 Go 一致性测试的运行时支持。
/src/tests/benchmarks/fidl/benchmark_suite 基准定义(.fidl.gidl 文件)。
/src/tests/benchmarks/fidl 对基准测试的运行时支持。

通常,每个后端中的一致性测试的实际测试目标会与该后端的相应测试一起定义。如需了解详情,请参阅绑定测试部分。

兼容性

兼容性测试是一种集成测试,用于通过相互不同的绑定运行 FIDL 客户端和服务器,以测试它们是否兼容。您可以在以下位置找到兼容性测试:/src/tests/fidl/compatibility/

危险标识符

危险标识符测试位于 /src/tests/fidl/dangerous_identifiers

其他

其他一些与 FIDL 相关的领域包括:

路径 目录
/tools/fidl/fidlgen_* 各种其他编译器后端。
/tools/fidl/fidlc/cmd/fidl-format FIDL 格式设置工具。
/tools/fidl/fidlc/cmd/fidl-lint FIDL linter。
/tools/fidl/fidldoc 生成 FIDL 文档。
/tools/fidl/fidlmerge 用于根据 FIDL JSON 生成代码的工具。
/tools/fidl/measure-tape 用于最大限度地分页的工具。
/tools/fidl/scripts 主要是一次性脚本,例如用于执行迁移并保留以供日后参考的脚本。
/src/lib/fostr 基于 fidlmerge 的工具,用于使用 C++ 生成格式设置代码。
/src/lib/fostr/build fostr 格式库构建模板。
/src/lib/fidl_codec 用于对 FIDL 消息进行编码/解码的库(由 fidlcat 使用)。

其他 FIDL 工具

许多 FIDL 工具都位于 fidl-misc 代码库中。如需克隆此代码库,请运行以下命令:

git clone https://fuchsia.googlesource.com/fidl-misc

然后,建议将路径导出到此目录,以便更轻松地设置别名:

export FIDLMISC_DIR=...

常用开发工具

这是 FIDL 团队的众包部分,介绍了他们可用于处理 FIDL 代码库的实用工具。

IDE

FIDL 团队的大部分人使用 VS Code 进行开发。一些有用的插件和工作流:

  • 远程 SSH 功能非常适合通过笔记本电脑执行远程工作。
    • 设置 tmux 或屏幕也有助于远程工作,以保留历史记录并在 shell 中管理多个会话。
  • Fuchsia 文档提供了有关如何设置语言服务器的说明:
  • 重新换行扩展程序对于自动将代码行重排到特定长度(例如,在修改 Markdown 文件时)非常有用。
  • 如需获得绑定黄金文件的自动语法突出显示功能,请更新 file.associations 设置:

    "files.associations": {
          "*.json.golden": "json",
          "*.rs.golden": "rust",
          "*.cc.golden": "cpp",
          "*.h.golden": "cpp",
          "*.go.golden": "go",
          "*.dart.golden": "dart",
    },
    

提交消息样式指南

编写更改消息时,请遵循提交消息样式指南

C++ 样式指南

我们遵循 Fuchsia C++ 样式指南,并制定了额外的规则,以进一步消除应用相关规则或准则解释方面的歧义。

注释

与代码行大小不同,注释行的大小不得超过 80 列,代码行大小不得超过 100 行。

Lambda 捕获

  • 如果 lambda 转义当前范围,请显式捕获所有变量。
  • 如果 lambda 是局部的(未转义当前范围),请优先使用引用的默认捕获(“[&]”)。

看到 [&] 意味着 lambda 仅存在于当前作用域内,可用于区分局部 lambda 和非局部 lambda。

// Correct.
std::set<const flat::Library*, LibraryComparator> dependencies;
auto add_dependency = [&](const flat::Library* dep_library) {
  if (!dep_library->HasAttribute("Internal")) {
    dependencies.insert(dep_library);
  }
};

常规设置

Fuchsia 设置

请先阅读 Fuchsia 使用入门指南。

fx set

如果您要处理 FIDL 工具链,请使用:

fx set core.x64 --with //bundles/fidl:tests --with-base //src/dart:dart_jit_runner

运行 Dart 测试和基准测试需要使用 --with-base 标志。

如果您负责处理 LSC:

fx set terminal.x64 --with //bundles/kitchen_sink \

符号化工具

如需对回溯进行符号化处理,您需要在作用域内使用符号化程序:

export ASAN_SYMBOLIZER_PATH="$(find `pwd` -name llvm-symbolizer | grep clang | head -1)"

快速测试 build

FIDL 是系统中非常深层的一部分,因此修改 FIDL 通常会导致“重建世界”,而细微的更改可能会触发数万次编译操作和耗时数分钟的编译。当您只是尝试构建并运行一些 FIDL 测试而不是整个系统时,这种方法可能会既缓慢又麻烦。

fx 工具支持小范围按需构建和软件包发布,可帮助您应对这种情况。如需启用该工具,请在 ~/.bashrc(或等效项)中设置以下环境变量:

export FUCHSIA_DISABLED_incremental=0

编译和运行测试

我们主要提供一行代码来针对各个部分运行测试。如有疑问,请参阅 Git 提交消息中的“Test:”注释;我们会尽最大努力描述用于验证我们在那里所做的工作的命令。

测试使用 fidldev 工具运行。示例假定 fidldev 脚本位于 PATH 上的某个位置(例如通过添加别名):

alias fidldev=$FIDLMISC_DIR/fidldev/fidldev.py

fidlc

# optional; builds fidlc for the host with ASan <https://github.com/google/sanitizers/wiki/AddressSanitizer>
fx set core.x64 --variant=host_asan

fx build host_x64/fidlc

如果您要在 fidlc 上进行大量的“修改-编译-测试”周期,以更少的优化进行构建可能会对构建速度产生显著影响。为此,请将 zircon/public/gn/config/levels.gni 中的 optimization 设置从 default 更改为 debugnone

为避免意外提交此更改,请运行以下命令:

git update-index --skip-worktree zircon/public/gn/config/levels.gni

如果您希望允许重新提交更改,请运行以下命令:

git update-index --no-skip-worktree zircon/public/gn/config/levels.gni

fidlc 项测试

fidlc 测试位于:

如需构建并运行 fidlc 测试,请执行以下操作:

fx test //tools/fidl/fidlc

如果您希望直接使用 ninja

fx_build_dir=$(cat .fx-build-dir) \
    fidlc_tests_target=$(fx ninja -C $fx_build_dir -t targets all | grep -e 'unstripped.*fidlc-test:' | awk -F : '{ print $1; }') \
    fx ninja -C $fx_build_dir $fidlc_tests_target && ./$fx_build_dir/$fidlc_tests_target

如需运行一系列特定的测试,请以适当的模式使用 --gtest_filter。例如:

fx_build_dir=$(cat .fx-build-dir) \
    fidlc_tests_target=$(fx ninja -C $fx_build_dir -t targets all | grep -e 'unstripped.*fidlc-test:' | awk -F : '{ print $1; }') \
    fx ninja -C $fx_build_dir $fidlc_tests_target && ./$fx_build_dir/$fidlc_tests_target --gtest_filter 'EnumsTests.*'

fidlc 调试

若要在调试 build 中轻松运行测试,请略微设置环境:

fx set core.x64 --variant=host_asan --with //bundles/fidl:tests
export ASAN_SYMBOLIZER_PATH="$(find `pwd` -name llvm-symbolizer | grep clang | head -1)"

正确设置后,您可以使用之前列出的命令运行测试(无论是否经过过滤)。

如需逐步完成测试,您可以使用 GDB

fx_build_dir=$(cat .fx-build-dir) \
    fidlc_tests_target=$(fx ninja -C $fx_build_dir -t targets all | grep -e 'unstripped.*fidlc-test:' | awk -F : '{ print $1; }') \
    fx ninja -C $fx_build_dir $fidlc_tests_target && fx gdb --args ./$fx_build_dir/$fidlc_tests_target --gtest_filter 'AliasTests.invalid_recursive_alias'

fidlc 测试样式指南

使用 C++ 编写的所有 fidlc 编译器测试都必须符合以下规则:

  • 使用 TEST 宏编写的测试必须具有采用 <CATEGORY>Tests 格式的大写驼峰式大小写组名称。和 UpperCamelCased 测试用例名称。 例如:TEST(BitsTests, GoodValidBits) {...
  • 测试用例名称不应以“Test”开头或结尾,因为这会造成重复。
  • 用于测试解析和/或编译的测试用例名称必须添加以下任一前缀:
    • Good:当测试用例预计通过时。例如:GoodValidMethod
    • Bad:当测试用例预计通过时。例如:BadMustBeDense
    • Warn:当测试用例预计通过,但出现报告程序警告时。警告仅供在引入新检查时临时使用,因此移除检查后,前缀为 Warn 的测试应更改为 GoodBad。例如:WarnTooManyProvidedLibraries

此外,预计编译失败的测试用例应使用 ASSERT_ERRORED_DURING_COMPILEASSERT_ERRORED_TWICE_DURING_COMPILE 宏,以应对预计会出现一个和两个错误的情况。

fidlc 枚金牌

如需重新生成 fidlc JSON 黄金,请执行以下操作:

fidldev regen fidlc

这些“黄金”文件是示例,说明 JSON IR fidlc 会生成何种类型,并用于跟踪更改。每次 JSON IR 以任何方式发生更改时,都需要重新生成黄金文件,否则 json_generator_tests 会失败。

fidlgen(新 C++、HLCPP、Rust、Go、Dart)

构建:

fx build tools/fidl

运行以下命令:

$FUCHSIA_DIR/out/default/host_x64/fidlgen_{cpp,hlcpp,rust,go,dart}

您可以运行的一些测试示例:

fx test fidlgen_hlcpp_golden_tests
fx test fidlgen_golang_lib_tests
fx test dart-bindings-test
fidldev test --no-regen fidlgen

如需重新生成黄金,请执行以下操作:

fidldev regen fidlgen

fidlgen_banjo

构建:

fx build host_x64/fidlgen_banjo

运行测试:

fx build host_x64/fidlgen_banjo_unittests
./out/default/host_x64/fidlgen_banjo_unittests

绑定关系

fidldev 支持对每个绑定进行测试。某些绑定测试会在设备上运行,并且要求在模拟器中运行 Fuchsia。具体步骤如下:

Tab 1> fx build && fx serve

Tab 2> fx qemu -kN

-k 标志可启用 KVM。它并不是必需的,但如果没有它,模拟器会变慢。-N 标志用于启用网络。

然后,可以使用 fidldev 运行绑定测试:

fidldev test --no-regen hlcpp
fidldev test --no-regen llcpp
fidldev test --no-regen c
fidldev test --no-regen go
fidldev test --no-regen rust
fidldev test --no-regen dart

或者,针对已更改的测试文件运行不带参数的 fidldev:

fidldev test

如需运行特定测试或将标志传递给特定测试,请运行 fidldev 并添加 --dry-run--no-build--no-regen 标志,以获取所需的测试命令。

兼容性测试

有关兼容性测试的运作方式以及代码所在位置的详细信息,请参阅位于 //src/tests/fidl/compatibility 的自述文件。

如需运行兼容性测试,您首先需要在模拟器中运行 Fuchsia:

Tab 1> fx build && fx serve

Tab 2> fx qemu -kN

如需运行兼容性测试,请执行以下操作:

Tab 3> fx set core.x64 --with //src/tests/fidl/compatibility
Tab 3> fx test fidl-compatibility-test

GIDL

如需重新构建 GIDL,请执行以下操作:

fx build host-tools/gidl

测量胶带

fx set core.x64 --with //tools/fidl/measure-tape/src:host
fx build

所有测试

本部分提供了用于运行所有 FIDL 相关测试的完整 fx test 命令。 如果您想运行特定测试,请使用这些库,而不是 fidldev test

绑定测试

设备端测试通常覆盖范围比主机测试要广泛,这是因为仅支持在主机上运行部分功能。不过,主机测试对于调试阻止设备启动的问题非常有用。

设备中
名称 测试命令 覆盖率
C 运行时测试、编码表 fx test fidl_c_tests //sdk/lib/fidl_base
步行者、其他 fx test fidl-walker-tests //sdk/lib/fidl_base
Walker 测试,包含句柄关闭检查 fx test fidl-handle-closing-tests //sdk/lib/fidl_base
hlcpp 绑定测试(包括一致性测试) fx test fidl_hlcpp_unit_test_package fidl_hlcpp_conformance_test_package //sdk/lib/fidl
新的 C++ 线路测试 fx test //src/lib/fidl/llcpp //sdk/lib/fidl/cpp/wire
新的 C++ 测试 fx test //src/lib/fidl/cpp //src/lib/fidl/cpp
go 绑定测试 fx test go-fidl-tests //third_party/go/syscall/zx/fidl //third_party/go/syscall/zx/fidl/fidl_test //src/tests/fidl/go_bindings_test
Rust 绑定测试 fx test //src/lib/fidl/rust //src/lib/fidl/rust
主机
名称 测试命令 覆盖率
步行者、其他 fx test --host fidl-walker-host-tests //sdk/lib/fidl_base
hlcpp 单元测试 fx test --host fidl_hlcpp_unit_tests //sdk/lib/fidl
hlcpp 一致性测试 fx test --host fidl_hlcpp_conformance_tests //sdk/lib/fidl
C++ 电线类型一致性测试 fx test --host fidl_llcpp_conformance_tests //sdk/lib/fidl/cpp/wire
C++ 自然类型一致性测试 fx test --host fidl_cpp_conformance_tests //src/lib/fidl/cpp
防锈一致性测试 fx test --host fidl_rust_conformance_tests //src/lib/fidl/rust
Rust fidl 库测试 fx test --host fidl_rust_lib_tests //src/lib/fidl/rust
Go 一致性测试 fx test --host fidl_go_conformance_tests //third_party/go/syscall/zx/fidl
go fidl 测试(扩展) fx test --host go_extended_fidl_test //third_party/go/syscall/zx/fidl
进行不安全值测试 fx test --host go_unsafevalue_test //third_party/go/syscall/zx/fidl/internal/unsafevalue

保真测试

名称 测试命令 覆盖率
fidlgen 类型定义 fx test fidlgen_lib_test //tools/fidl/lib/fidlgen
fidlgen C++ 专用 IR fx test fidlgen_cpp_ir_test //tools/fidl/lib/fidlgen_cpp
fidlgen HLcpp fx test fidlgen_hlcpp_golden_tests //tools/fidl/fidlgen_hlcpp
fidlgen 新款 C++ fx test fidlgen_cpp_golden_tests //tools/fidl/fidlgen_cpp
Fildgen Golang fx test fidlgen_go_{lib,golden}_tests //tools/fidl/fidlgen_golang
铁锈色 fx test fidlgen_rust_{lib,golden}_tests //tools/fidl/fidlgen_rust
Fildgen Syzkaller fx test fidlgen_syzkaller_golden_tests //tools/fidl/fidlgen_syzkaller

其他

名称 测试命令 覆盖率
fidlc 编译器 fx test fidlc-test
fx test fidlc_golden_tests
//tools/fidl/fidlc
gidl 解析器 fx test gidl_parser_test //tools/fidl/gidl/parser
测量磁带测试 fx test measure-tape_test //tools/fidl/measure-tape
Rust IR 解析器 fx build //src/devices/tools/fidlgen_banjo/tests/parser

所有基准

基准测试可以直接运行,也可以通过以下两个测试运行程序之一运行:fuchsia_benchmarks(旧版)、SL4F(新版)。

chromeperf 的基准测试目前通过 fuchsia_benchmarks 运行程序生成,但正在向 SL4F 过渡。在过渡期间,应将基准测试集成到两个系统中。

直接运行基准测试

确保您的 build 中包含基准测试:

fx set core.x64 --with //src/tests/benchmarks

您需要 fx build 并重启 qemu,软件包才可用。

可用的基准:

名称 基准命令 备注
Go 基准 fx shell /bin/go_fidl_microbenchmarks
Rust 基准 fx shell /bin/rust_fidl_microbenchmarks /tmp/myresultsfile 结果可通过fx shell cat /tmp/myresultsfile/查看
C++ 传输类型基准 fx shell /bin/llcpp_fidl_microbenchmarks
lib/fidl 基准 fx shell /bin/lib_fidl_microbenchmarks
往返基准 fx shell /bin/roundtrip_fidl_benchmarks

使用 SL4F 基准运行程序运行所有基准

这会以与在 CQ 上运行基准相同的方式运行基准。SL4F 需要 terminal.x64 产品。使用 fx set 切换产品:

fx set terminal.x64 --with //bundles/buildbot/terminal

如需运行所有 FIDL 测试,请使用以下命令:

fx test --e2e fidl_microbenchmarks_test

所有重新生成命令

本部分会提供 fx check-goldens 命令,用于重新生成所有与 FIDL 相关的黄金文件。这是 fidldev regen 在后台使用的代码。

名称 重新生成命令 输入 输出
(全部金币) 外汇支票 - 黄金
金色 CANNOT TRANSLATE tools/fidl/fidlc/testdata tools/fidl/fidlc/goldens
保真金色 fx check-goldens $TOOL tools/fidl/fidlc/testdata tools/fidl/$TOOL/goldens
Filddoc Goldens CANNOT TRANSLATE tools/fidl/fidlc/testdata tools/fidl/fidldoc/goldens
金德尔人 Fx Check-goldens Gidl src/tests/fidl/conformance_suite/golden{.gidl,.test.fidl} tools/fidl/gidl/goldens
第三方 go fx exec $FUCHSIA_DIR/third_party/go/regen-fidl

使用 ninja 编译

在某些情况下,GN 可能会构建许多不需要的目标。您可以使用 ninja(而非 GN)构建特定目标。在大多数情况下,您可以通过 grep 作为二进制文件名称来确定 ninja 调用。

例如,您可以对 fidlgen_cpp 使用 grep

fx ninja -C out/default -t targets all | grep -e 'fidlgen_cpp:'

此示例会输出 ninja 目标列表,其中包括 host_x64/fidlgen_cpp。因此,如需构建 fidlgen_cpp,请运行以下 ninja 命令:

fx ninja -C out/default host_x64/fidlgen_cpp

调试(主机)

您可以通过多种方式调试主机二进制文件中的问题。本部分介绍了 fidlc --files test.fidl 崩溃的情况:

GDB

首先,使用 cd 方法转到 build 目录。您也可以留在 $FUCHSIA_DIR 中,但之后需要在 GDB 中运行 dir out/default,这样它才能查找源文件。

cd $FUCHSIA_DIR/out/default

接下来,启动 GDB。系统中的副本可能有效,但预构建的 fx gdb 更有可能与 Fuchsia 项目中的 build 工件搭配使用。如需查看预构建 GNU 工具的完整列表,请参阅 fx gnu --help

fx gdb --args host_x64/exe.unstripped/fidlc --files test.fidl

然后输入“r”以启动该程序。如需更多用途,并为您提供方便的快速参考,这份 GDB 备忘单非常有用。

ASan

确保您在编译时启用了 ASan:

fx set core.x64 --variant=host_asan
fx build host_x64/fidlc

然后运行 out/default/host_x64/fidlc --files test.fidl。该二进制文件应与 out/default/host_x64-asan/fidlc 相同。

Valgrind

在 Google Linux 计算机上,您可能需要安装标准版 Valgrind,而不是使用预安装的二进制文件:

sudo apt-get install valgrind

然后,执行以下操作:

valgrind -v -- out/default/host_x64/exe.unstripped/fidlc --files test.fidl

工作流

前往 fuchsia.io 和 fuchsia.net

如需更新所有已保存的 fidlgen 文件,请运行以下命令,系统将自动搜索并生成必要的 go 文件:

fx exec $FUCHSIA_DIR/third_party/go/regen-fidl

常见问题解答

为什么 C 后端不同于其他所有后端?

当前的 C 绑定已废弃。如需详细了解未来在 C 中使用 FIDL 的方式,请参阅 https://fxbug.dev/42159192

为什么不是所有后端都集中在一个工具中?

实际上,我们希望所有后端都位于单独的工具中!

未来,我们计划在所有各种工具(fidlcfidlfmt、各种后端)中创建一个脚本,以便轻松访问所有内容,并管理这些内容的链式处理。例如,应该可以在一个命令中生成 Go 绑定,例如:

fidl gen --library my_library.fidl --binding go --out-dir go/src/my/library

或者使用以下命令设置库的格式:

fidl fmt --library my_library.fidl -i