概览
FIDL 工具链大致由三部分组成:
- 前端,又称
fidlc- 解析并验证
.fidl文件 - 计算各种结构的大小、对齐方式和偏移量
- 生成 JSON IR(中间表示法)
- 解析并验证
- 后端
- 基于 IR(C 后端除外)
- 生成特定于目标语言的代码,该代码与相应语言的库相关联
- 运行时库
- 实现消息的编码/解码/验证
- 方法调度机制
代码位置
编译器前端
前端位于 //tools/fidl/fidlc/,测试位于 //tools/fidl/fidlc/tests。
编译器后端
| 目标 | Codegen | 运行时库 | 测试 |
|---|---|---|---|
| HLCPP(旧版) | /tools/fidl/fidlgen_hlcpp | /sdk/lib/fidl/hlcpp | (与运行时库位于同一位置) |
| 新 C++ | /tools/fidl/fidlgen_cpp | /sdk/lib/fidl/cpp | /src/lib/fidl/llcpp 和 /sdk/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 工具本身的源代码和 build 模板。 |
| /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 或 screen 也有助于远程工作,以保留历史记录并管理 shell 中的多个会话。
- Fuchsia 文档中提供了有关设置语言服务器的说明:
- 适用于 C++ 的 clangd
- 适用于 Rust 的 rust-analyzer
- 重新换行扩展程序可用于自动将行重新排版为特定长度(例如在编辑 Markdown 文件时)。
如需为绑定黄金文件启用自动语法突出显示功能,请更新
file.associations设置:"files.associations": { "*.json.golden": "json", "*.rs.golden": "rust", "*.cc.golden": "cpp", "*.h.golden": "cpp", "*.go.golden": "go", },
提交消息样式指南
撰写更改消息时,请遵循提交消息样式指南。
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-test //bundles/fidl:tests
如果您使用的是 LSC:
fx set terminal.x64 --with //bundles/kitchen_sink \
symbolizer
如需对回溯进行符号化处理,您需要一个范围内的符号化器:
export ASAN_SYMBOLIZER_PATH="$(find `pwd` -name llvm-symbolizer | grep clang | head -1)"
快速测试 build
FIDL 是系统非常深层的一部分,因此修改它通常会导致“重建世界”,小小的更改可能会触发数万个编译操作,并导致 build 耗时数分钟。如果您只是想构建并运行一些 FIDL 测试,而不是整个系统,那么这种方法可能会很慢且很麻烦。
fx 工具支持按需发布小范围的 build 和软件包,可帮助您应对这种情况。如需启用此功能,请在 ~/.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 更改为 debug 或 none。
为避免意外提交此更改,请运行以下命令:
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宏编写的测试必须具有 UpperCamelCase 格式的组名称<CATEGORY>Tests。以及采用 UpperCamelCase 格式的测试用例名称。 例如:TEST(BitsTests, GoodValidBits) {...。 - 测试用例名称不应以“Test”开头或结尾,因为这会造成冗余。
- 测试解析和/或编译的测试用例名称必须以以下前缀之一开头:
Good:测试用例预计会通过时。示例:GoodValidMethod。Bad:测试用例预计会通过时。示例:BadMustBeDense。Warn:测试用例预计会通过,但会显示报告程序警告。警告旨在用于引入新检查时的临时用途,因此,当移除检查时,以Warn为前缀的测试应更改为Good或Bad。示例:WarnTooManyProvidedLibraries。
此外,如果测试用例预期会出现编译失败,则应分别在预期出现一个和两个错误时使用 ASSERT_ERRORED_DURING_COMPILE 和 ASSERT_ERRORED_TWICE_DURING_COMPILE 宏。
fidlc 金币
如需重新生成 fidlc JSON 标准输出,请执行以下操作:
fidldev regen fidlc
这些“黄金”文件是 fidlc 生成的 JSON IR 的示例,用于跟踪更改。每次以任何方式更改 JSON IR 时,都必须重新生成标准文件,否则 json_generator_tests 会失败。
fidlgen(新 C++、HLCPP、Rust、Go)
构建:
fx build tools/fidl
运行以下命令:
$FUCHSIA_DIR/out/default/host_x64/fidlgen_{cpp,hlcpp,rust,go}
您可以运行以下一些示例测试:
fx test fidlgen_hlcpp_golden_tests
fx test fidlgen_golang_lib_tests
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 来测试已更改的文件:
fidldev test
如需运行特定测试或将标志传递给特定测试,请运行 fidldev 并使用 --dry-run、--no-build、--no-regen 标志来获取所需的测试命令。
兼容性测试
如需详细了解兼容性测试的运作方式以及代码所在的位置,请参阅 //src/tests/fidl/compatibility 中的 README。
如需运行兼容性测试,您首先需要在模拟器中运行 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
所有测试
本部分提供了完整的 fx test 命令,用于运行所有与 FIDL 相关的测试。如果您想运行特定测试,请使用这些参数,而不是 fidldev test。
绑定测试
由于主机仅支持运行部分功能,因此设备端测试的覆盖范围通常比主机端测试更广。不过,主机测试有助于调试阻止设备启动的问题。
已保存在设备上
| 名称 | 测试命令 | 覆盖率 |
|---|---|---|
| c 运行时测试,编码表 | fx test fidl_c_tests |
//sdk/lib/fidl_base |
| walker, misc | 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 //sdk/lib/fidl/cpp |
//sdk/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 unittests | 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 |
//sdk/lib/fidl/cpp |
| Rust 一致性测试 | 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 |
| 进行 unsafevalue 测试 | fx test --host go_unsafevalue_test |
//third_party/go/syscall/zx/fidl/internal/unsafevalue |
fidlgen 测试
| 名称 | 测试命令 | 覆盖率 |
|---|---|---|
| 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 |
| fidlgen golang | fx test fidlgen_go_{lib,golden}_tests |
//tools/fidl/fidlgen_golang |
| fidlgen rust | fx test fidlgen_rust_{lib,golden}_tests |
//tools/fidl/fidlgen_rust |
| fidlgen syzkaller | fx test fidlgen_syzkaller_golden_tests |
//tools/fidl/fidlgen_syzkaller |
其他
| 名称 | 测试命令 | 覆盖率 |
|---|---|---|
| fidlc 编译器 | fx test fidlc-testfx 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 runner 生成,但正在过渡到 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
所有重新生成命令
此部分提供了用于重新生成所有 FIDL 相关黄金文件的 fx check-goldens 命令。这是 fidldev regen 在后台使用的内容。
| 名称 | 重新生成命令 | 输入 | 输出 |
|---|---|---|---|
| (所有金牌) | fx check-goldens | ||
| fidlc golden | fx check-goldens fidlc | tools/fidl/fidlc/testdata | tools/fidl/fidlc/goldens |
| fidlgen golden | fx check-goldens $TOOL | tools/fidl/fidlc/testdata | tools/fidl/$TOOL/goldens |
| fidldoc goldens | fx check-goldens fidldoc | tools/fidl/fidlc/testdata | tools/fidl/fidldoc/goldens |
| gidl 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。
为什么不将所有后端都放在一个工具中?
我们实际上希望所有后端都位于单独的工具中!
未来,我们计划针对所有各种工具(fidlc、fidlfmt、各种后端)编写一个脚本,以便轻松访问所有内容,并管理这些内容的链接。
例如,应该可以通过一个命令(例如:)生成 Go 绑定。
fidl gen --library my_library.fidl --binding go --out-dir go/src/my/library
或者,使用以下命令就地格式化库:
fidl fmt --library my_library.fidl -i