ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Bazel 规则集发布实战指南:从仓库布局、MODULE.bazel 到 CI/CD 与文档化的完整部署流程

Bazel 规则集发布实战指南:从仓库布局、MODULE.bazel 到 CI/CD 与文档化的完整部署流程 Bazel 规则集发布实战指南从仓库布局、MODULE.bazel 到 CI/CD 与文档化的完整部署流程【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel本指南面向准备将自己的 Bazel 规则集ruleset发布给他人使用的规则作者rule writer。文章以官方「Deploying Rules」文档为主体系统讲解规则仓库的命名与托管规范、标准目录布局、Bazel 模块Bzlmod集成方式、CI/CD 与文档自动化等发布全流程并结合本仓库Bazel 自身源码中的实际实现佐证底层原理。读完本文你将掌握一套可复用的规则集发布清单从仓库初始化、defs.bzl导出约定、toolchain 注册策略到发布公告中可直接粘贴到用户MODULE.bazel的bazel_dep片段。一、为什么需要专门的发布指南规则rules是 Bazel 生态系统的扩展单元用于支持各类语言与工具链的构建。Bazel 本身是“可扩展的构建系统”其大量能力正是通过社区规则集体现的——例如 Go 规则、C/C 规则、Java 规则 等均可参见 规则推荐列表。官方之所以专门撰写部署指南是因为规则集的发布与普通应用代码不同它要同时服务“规则作者”与“规则用户”两个群体牵涉到仓库命名、模块命名、toolchain 注册、测试与文档等一整套约定。本文依据 docs/rules/deploying.mdx 展开并对照 Bazel 主仓库即当前仓库中的真实代码与配置帮助你理解这些约定背后的原因。二、托管与命名规则rules_前缀约定2.1 仓库命名格式新规则应当托管在你自己组织organization下的独立 GitHub 仓库中官方推荐使用统一的命名格式$ORGANIZATION/rules_$NAME例如bazelbuild/rules_go、bazelbuild/rules_java。如果你认为规则应该归属于bazelbuild组织可以在 GitHub Discussions 发起讨论否则就遵循org_rules_lang的约定。2.2 仓库元数据规范为了让用户能快速检索和理解规则官方给出了明确的元数据模板项目示例仓库名称bazelbuild/rules_go仓库描述Go rules for Bazel仓库标签golang、bazelREADME.md标题Go rules for Bazel注意 README 标题要链接到 https://bazel.build为不熟悉 Bazel 的用户提供正确入口。规则可以按语言如 Scala、运行时平台如 Android或框架如 Spring进行归类分组。三、标准仓库布局让用户一眼看懂你的规则集每个规则仓库都应遵循统一布局方便用户快速上手。官方以虚构的mockascript语言为例给出了完整结构/ LICENSE README MODULE.bazel mockascript/ constraints/ BUILD runfiles/ BUILD runfiles.mocs BUILD defs.bzl tests/ BUILD some_test.sh another_test.py examples/ BUILD bin.mocs lib.mocs test.mocs下面逐项解析每个组成部分。3.1 MODULE.bazel定义用户引用你的模块名在项目根目录的MODULE.bazel中定义用户引用规则时使用的模块名。若规则属于bazelbuild组织必须使用rules_lang形式否则使用org_rules_lang形式如build_stack_rules_proto。文档假设仓库属于bazelbuild组织则module(name rules_mockascript)对照本仓库根目录的 MODULE.bazel可以看到 Bazel 自身正是这样声明模块的module( name bazel, version 10.0.0-prerelease, repo_name io_bazel, )Bazel 自己也是一个 Bazel 模块其bazel_dep声明如rules_go、rules_python、rules_java、rules_cc等正好展示了规则集之间如何通过 Bzlmod 相互依赖。3.2 README规则集的“门面”顶层必须有一个README简要描述规则集的功能以及用户期望的 API。3.3 Rulesdefs.bzl作为统一入口规则集通常包含多个规则。约定是创建以语言命名的目录并在其中提供入口文件defs.bzl导出所有规则同时放置BUILD文件使该目录成为一个 package/ mockascript/ BUILD defs.bzlBazel 主仓库内部同样遵循这一模式——例如 src/main/starlark/builtins_bzl 目录下的defs.bzl风格文件以及tools/build_defs/、tools/build_rules/等目录中大量.bzl入口文件都体现了“以.bzl文件为 API 入口”的约定。值得说明的是随着规则从 Bazel 主仓库剥离社区更倾向于把defs.bzl放在独立规则仓库中。3.4 Constraints自定义平台约束的存放位置如果你的规则定义了 toolchain 规则很可能会需要自定义constraint_setting和/或constraint_value。约定是将它们放入//LANG/constraintspackage/ mockascript/ constraints/ BUILD BUILD defs.bzl为什么 constraints 如此重要文档明确指出所有规则用户都会用这些约束在BUILD文件中执行平台相关的逻辑例如使用select()。自定义约束本质上是在定义“整个 Bazel 生态都要说的语言”。因此先查阅 bazelbuild/platforms 中已有的约束遵循最佳实践若约束与语言无关考虑直接贡献到 platforms 仓库而非重复发明谨慎引入新的自定义约束。从本仓库 MODULE.bazel 可以看到platforms模块version 1.1.0正是通过bazel_dep引入的它提供了跨语言通用的平台约束定义。3.5 Runfiles 库统一的//LANG/runfiles约定如果你的规则为访问 runfiles 提供标准库应将其放在//LANG/runfiles目标位置即//LANG/runfiles:runfiles的缩写。需要访问数据依赖的用户目标通常会把该目标加入deps属性。Bazel 主仓库为各语言提供了 runfiles 支持作为参考实现例如Ctools/cpp/runfiles/runfiles.h该头文件目前是 rules_cc 的转发器指向rules_cc//cc/runfilesBashtools/bash/runfiles/BUILDJavatools/java/runfiles/BUILDPythontools/python/runfiles。此外仓库 examples 中还提供了runfile.cc、runfile.sh、runfile.py、runfile.go等各语言 runfiles 使用示例可帮助规则作者理解 runfiles 库的目标形态。runfiles 相关概念可参考 runfiles 概念文档。四、仓库规则Repository rules与 MODULE.bazel 集成4.1 外部依赖声明规则集可能有外部依赖需要在MODULE.bazel中通过bazel_dep声明。本仓库的 MODULE.bazel 是极佳的参考范例——它声明了 30 个模块依赖并说明了间接依赖的处理方式# Indirect module dependencies. Minimal versions are specified for compatibility; # repo_nameNone avoids accidental usages bazel_dep(name buildozer, version 8.5.1, repo_name None) bazel_dep(name rules_swift, version 3.3.0) # with repo_name None, version drops to 2.4.0从源码结构看repo_name None用于避免用户代码意外直接引用这些间接依赖是一种依赖隔离的实践。规则作者可以借鉴这种“显式声明 隔离间接依赖”的写法。4.2 注册 toolchain规则集也可以在MODULE.bazel中注册 toolchain。这里有一个重要的性能与架构考量文档特别强调在分析阶段解析 toolchain 时Bazel 需要分析所有已注册的toolchain目标但不需要分析toolchain.toolchain属性引用的所有目标。这意味着如果注册 toolchain 需要在仓库中执行复杂计算应当考虑把“含toolchain目标”的仓库与“含LANG_toolchain目标”的仓库拆分。前者总是会被拉取fetched后者只在用户真正需要构建LANG代码时才被拉取从而避免不必要的仓库获取开销。toolchain规则的底层实现在 Bazel 源码中为 src/main/java/com/google/devtools/build/lib/rules/platform/ToolchainRule.java其关键属性在 platforms-and-toolchains 参考文档 中有完整说明属性说明name必填目标唯一名称toolchain_type必填toolchain_type目标的 label表示该 toolchain 所服务的角色toolchain必填被选中时实际提供的工具/工具套件目标exec_compatible_with默认[]执行平台必须满足的constraint_value列表target_compatible_with默认[]目标平台必须满足的constraint_value列表target_settings默认[]目标配置必须满足的config_setting列表use_target_platform_constraints默认False为True时继承当前目标平台的约束toolchain 机制的动机可参考 toolchains 扩展文档规则作者不应把编译器硬编码为规则的私有属性而应通过toolchain_type 平台约束让 Bazel 在执行平台/目标平台之间自动选择合适工具。4.3 发布公告中的 Release snippet发布新版本时在你的发布公告中提供一段用户可直接复制粘贴到MODULE.bazel的片段通常形式为bazel_dep(name rules_LANG, version VERSION)例如用户引入rules_go时会写bazel_dep(name rules_go, version 0.59.0)本仓库 MODULE.bazel 中真实使用了这一形式。这种“一键粘贴”的发布片段是降低用户使用门槛的关键细节。五、测试与示例保障规则质量5.1 测试组织方式规则集必须包含验证规则按预期工作的测试。测试可以放在规则所服务语言的惯用位置如*_test规则的标准位置或顶层的tests/目录。Bazel 主仓库的测试布局极具参考价值src/test/javaJava 规则测试、src/test/shellShell 集成测试、src/test/pyPython 测试分别对应不同语言的测试组织方式。此外tools/build_rules/test_rules.bzl 展示了“用规则测试规则”的元编程思路——它利用sh_test和 runfiles 工具为 Bazel 自身的测试提供支撑。5.2 Examples 目录可选但推荐提供examples/目录展示规则几种基本用法对用户非常有帮助。本仓库的 examples 目录含 cpp、go、py、shell、java-native、java-starlark、windows 等子目录就是最佳示范每种语言都有可运行的示例构建目标与 README 说明。六、CI/CD让规则集持续集成与自动发版6.1 GitHub Actions 与可复用工作流许多规则集使用 GitHub Actions。官方推荐直接参考 rules-template 中的.github/workflows配置其简化方案基于 bazel-contrib 组织托管的“可复用工作流”reusable workflowci.yaml在每个 PR 和main分支提交上运行测试release.yaml每次向仓库推送 tag 时触发发布。本仓库的 .github/workflows 展示了真实大型仓库的 CI 组织方式cherry-pick、labeler、stale、release-helper、scorecard 等工作流可从中观察成熟项目的自动化运维实践。6.2 加入 bazelbuild 组织后的持续集成如果你的仓库隶属于bazelbuild组织可以申请将其加入 ci.bazel.build 持续集成平台从而获得组织级的 CI 支持。七、文档自动化Stardoc 与 docs/ 目录规则 API 文档应当自动生成避免手工维护导致文档与代码脱节。官方建议使用 Stardoc按 Stardoc 规范为规则编写注释即可自动生成 API 文档。本仓库的 MODULE.bazel 也声明了对stardoc模块的依赖bazel_dep(name stardoc, version 0.8.0, repo_name io_bazel_skydoc)说明 Bazel 自身就在用 Stardoc 生成文档参考 rules-template 的 docs/ 文件夹它展示了如何在 Starlark 文件更新时保持docs/目录下的 Markdown 内容始终同步。从文档工程角度看Bazel 官方文档自身也是版本化生成的本仓库 docs/versions 下维护了 7.6.1 至 9.1.0 等多个版本的文档快照docs/versions/index.mdx 作为版本索引这体现了大型项目“文档与版本绑定、自动更新”的最佳实践。八、FAQ 深度解读为什么规则不放进 Bazel 主仓库8.1 解耦规则与 Bazel 发布周期官方明确回答尽可能将规则与 Bazel 发布周期解耦。原因有三职责更清晰能明确每个规则的所有者减轻 Bazel 核心开发者的负担用户更灵活解耦后用户可以更方便地修改、升级、降级和替换规则贡献门槛更低向规则仓库贡献代码通常比向 Bazel 核心贡献更轻量甚至可能拥有该仓库的完整提交权限而获取 Bazel 核心的提交权限要复杂得多。8.2 代价一次性安装更复杂解耦的代价是用户需要一次性在MODULE.bazel中声明对规则集的依赖即上文的bazel_dep片段。这是为了长期灵活性而接受的一次性成本。8.3 历史迁移从//tools/build_rules到独立仓库Bazel 历史上所有规则都位于主仓库的//tools/build_rules或//tools/build_defs目录下。当前仓库仍保留少量规则例如 tools/build_rules、tools/build_defs 下的残留但官方正在持续把剩余规则迁移出去。这解释了为什么本文档强调“新规则应放到独立仓库”——这是 Bazel 生态的既定演进方向。九、规则集发布完整清单综合全文一份可落地的发布清单如下命名仓库命名为$ORGANIZATION/rules_$NAME设置好描述、标签与 README 标题模块MODULE.bazel中module(name rules_LANG)或org_rules_LANG布局LICENSE、README、MODULE.bazel齐全语言目录内含BUILDdefs.bzl入口约束放//LANG/constraintsrunfiles 库放//LANG/runfiles依赖与 toolchain用bazel_dep声明外部依赖register_toolchains注册工具链必要时拆分 toolchain 仓库以减少不必要的拉取测试提供tests/或语言惯用测试位置确保规则行为可验证示例可选提供examples/展示基本用法CI/CD配置ci.yamlPR/主分支测试与release.yamltag 触发发版文档用 Stardoc 注释规则、自动生成 API 文档保持docs/与代码同步发布公告中包含bazel_dep(name rules_LANG, version VERSION)一键粘贴片段。遵循以上约定你的规则集就能无缝融入 Bazel 生态让用户以标准、可预期的方式发现、安装和使用你的规则。【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表