@bazel/buildozer

中文文档
8.2.1发布于 2025/06/10Apache-2.0零依赖近 30 天下载 2万

一个使用标准命令重写多个 BUILD 文件的命令行工具

中文使用文档
文档目录11 节
  1. 安装
  2. 使用量
  3. 目标
  4. 选项
  5. 编辑命令
  6. 打印命令
  7. 转换标签
  8. 一次做多个更改
  9. 使用 Buildozer 在记忆中
  10. 错误代码
  11. 源结构

构建器

Buildozer 是重写多行的命令行工具 巴泽尔 使用 BUILD 文件 标准命令.

安装

  1. 构建二进制并把它放入您的 $GOPATH/ bin :
go install github.com/bazelbuild/buildtools/buildozer@latest

使用量

buildozer [OPTIONS] ['command arg...'...|-f FILE] [label]...

这里, label... 是Bazel标签的(空格分隔,可能为空)列表, 比如说 //path/to/pkg1:rule1 relative/path/to/pkg2:rule2。除此之外 指定软件包的 Bazel 标签语法, Buildozer 也允许 包件部分以引用类似 BUILD 的文件, 例如 //WORKSPACE:all 或者说 toolchains/BUILD.tpl:host_toolchain。 。 。 .

Builder 命令作为单一位置参数传递,因此必须 引出(或以其他方式逃脱)。 多个命令和多个标签可以是 通过了。 Buildoze将对所有目标执行所有命令. (所以如果你没有) 指定至少一个命令和一个目标,不会发生任何事。 ) 命令为 按顺序执行,文件会平行处理.

何时 -f FILE 使用文字命令, 构建者读取命令 从 FILE。 。 。 . FILE 可能会是 -,在此情况下,命令从 标准输入.

命令文件的格式如下: 空行和行起始 与 # 忽略(包括主白空间)。 非无标志行由 联 合 国 |- 分离的命令和标签:

command arg arg...|command arg arg...|...|label|label|...

(事实上,命令和标签可以任意地出现互放. ) | 命令中的字符可以像 \|双空字节 (单位:千美元)\x00\x00)在命令文件中无效。 特别处理 允许从标准输入读取的标签。 当命令文件中的行 使用“*”的单标签,然后将命令适用于所有元素 名单 label... 从命令行.

目标

目标看起来像Bazel标签, 但可能存在一些差异 宏.

  • 使用标签标记指代一条规则: //buildtools/buildozer:edit
  • 使用 __pkg__ 引用软件包声明的后缀 : //buildtools/buildozer:__pkg__
  • 使用星号指代文件中的所有规则 : //pkg:*
  • 使用 ... 以指代目录中所有后裔 BUILD 文件: //pkg/...:*
  • 用%来指代所有某种规则: //pkg:%java_library
  • 使用百分数和数来指代一条从某一行开始的规则: //pkg:%123。 。 。 .
  • 使用特殊软件包名称 - 从标准读取 BUILD 文件 输入而不是从软件包目录中的本地文件 : -:all_tests。 。 。 . (据推测,两者使用a和b均无用。) - 软件包名称并使用 -f - 从标准输入读取命令的旗帜。 )

选项

备选办法包括:

  • -stdout : 将更改的 BUILD 文件写入 stdout
  • -buildifier : 使用特定的建构二进制格式输出。 如果为空, 则使用内置内容 .
  • -k : 应用所有命令, 即使有失败
  • -quiet : 压制信息信息
  • -shorten_labels : 将所添加的标签转换为短窗形, 例如 //foo: bar qq: bar
  • -types:过滤目标,只保留指定类型的目标,例如. buildozer -types go_library,go_binary 'print rule' '//buildtools/buildozer:*'
  • -eol-comments=false:在添加新评论时,将其放入单独一行.

见 buildozer -help 完整名单.

编辑命令

Buildozer 支持以下命令 ('command args':

  • add <attr> <value(s)>: 向规则的列表属性添加值。 如果有的话 值已经存在于列表中,而不是添加.
  • new_load <path> <[to=]from(s)>: 为给定路径添加负载语句, 导入符号。 之后,考虑运行 buildozer 'fix unusedLoads'。 。 。 .
  • replace_load <path> <[to=]from(s)>: 类似 new_load,但删除 在添加新负载之前,已有对请求符号的加载语句.
  • substitute_load <old_regexp> <new_template> 替换负载的模块 匹配 old_regexp 根据 new_template。正则表达式必须 跟着 RE2 语法。 。 。 . new_template 可能是简单的替换字符串,但它也可能扩展 使用 $0 或者说 $x。 。 。 .
  • comment <attr>? <value>? <comment>: 在规则、属性中添加一个注释, 或列表中的特定值。 注释中的空格应当与 后鞭击.
  • print_comment <attr>? <value>?
  • delete: 删除一条规则.
  • fix <fix(es)>?: 应用固定.
  • move <old_attr> <new_attr> <value(s)>: 移动 value(s) 从列表中 old_attr 列表中 new_attr。通配符 * 匹配所有值.
  • new <rule_kind> <rule_name> [(before|after) <relative_rule_name>]: 添加一个 bUILD 文件结尾处的新规则( 前后) <relative_rule>) (中文(简体) ). 这个 标识符 __pkg__ 可用于定位相对于包()的规则.
  • print <attr(s)>
  • remove <attr>: 删除属性 attr。通配符 * 全部匹配 属性除外 name。 。 。 .
  • remove <attr> <value(s)>: 删除 value(s) 从列表中 attr编辑 通配符 * 匹配所有属性。 列表中无 value(s) 为: 未修改.
  • remove_comment <attr>? <value>?: 删除该规则所附带的评论, 属性,或列表中的特定值.
  • remove_if_equal <attr> <value>: 删除属性 attr 如果其价值 等于 value。 。 。 .
  • rename <old_attr> <new_attr>: 重命名为 old_attr 改为 new_attr 必须 尚不存在.
  • replace <attr> <old_value> <new_value>: 替换 old_value 与 new_value 列表中 attr。通配符 * 匹配所有属性。 不包含 old_value 未修改.
  • substitute <attr> <old_regexp> <new_template>: 替换字符串 匹配 old_regexp 列表中 attr 根据 new_template。通配符 * 匹配所有属性。 正则表达式必须遵循 RE2 语法。 。 。 . new_template 可能 是一个简单的替换字符串,但它也可能扩展编号或命名 使用 $0 或者说 $x。没有匹配字符串的列表 old_regexp 未修改.
  • set <attr> <value(s)>:设置属性的值。 如果属性 它的旧值已被替换.
  • set_if_absent <attr> <value(s)>:设置属性的值。 如果 属性已经存在,没有采取任何行动.
  • set kind <value>: 设定目标类型为值.
  • set_select <attr> <key_1> <value_1> <key_n> <value_n>
  • copy <attr> <from_rule>: 复制值 attr 在规则之间 如果是 存在于 to_rule它将被覆盖.
  • copy_no_overwrite <attr> <from_rule>: 复制值 attr 介于 规则。 如果它存在于 to_rule,不采取行动.
  • dict_add <attr> <(key:value)(s)>: 设置命令键的值 属性 attr。如果键已经存在,它将 没有 被覆盖. 科隆字符可以包含在密钥中,而从":"中逃出的价值.
  • dict_set <attr> <(key:value)(s)>: 设置命令键的值 属性 attr。如果密钥已经存在,则其旧值将被替换. 科隆字符可以包含在密钥中,而从":"中逃出的价值.
  • dict_remove <attr> <key(s)>: 删除 dict 属性的密钥 attr。 。 。 .
  • dict_replace_if_equal <attr> <key> <old_value> <new_value>: 替换 old_value 与 new_value 键 key 在字典属性中 attr。 。 。 . 如果字典中没有键, 或者没有值 old_value,它会 没有 更新.
  • dict_list_add <attr> <key> <value(s)>: 将数值添加到列表中 dict 属性 attr。 。 。 .
  • format: 强迫所有文件格式化,即使这些文件没有被更改 其他命令.

这里, <attr> 代表属性( 存在) add编/rename(单位:千美元)delete(d等), 例如: srcs, (中文(简体) ), <value(s)> 代表属性等值. A '?' 表示前面的论点是可选的.

对所有符合条件的修补应用没有指定固定的固定命令. 使用 //path/to/pkg:__pkg__ 作为文件级别更改的标签, 如 new_load 财务报告和审定财务报表 new。 。 。 . 通过使用 %rule_kind 在标签末尾(见下文示例).

以下命令仅适用于 MODULE.bazel 文件(例如目标) //MODULE.bazel:all:

  • use_repo_add <use_extension variable name> <repo(s)>数字 : 确保通过 use_repo 联 合 国 扩展名,其中指定的顶级变量包含返回值 页:1 use_extension 电话.
  • use_repo_remove <use_extension variable name> <repo(s)>数字 : 确保给定的寄存器 没有 通过 use_repo 页:1 上一级变量包含返回的扩展名 数值 a use_extension 电话.
  • use_repo_add [dev] <extension .bzl file> <extension name> <repo(s)>数字 : 确保指定扩展生成的给定寄存器 通过 use_repo如果 dev 参数,扩展用法 与 dev_dependency = True 将被考虑。 扩展用途 与 isolated = True 被忽略.
  • use_repo_remove [dev] <extension .bzl file> <extension name> <repo(s)>数字 : 确保指定扩展生成的给定寄存器 没有 通过 use_repo如果 dev 参数,扩展名 用法为 dev_dependency = True 将被考虑。 延长 用法为 isolated = True 被忽略.

实例

# Edit //pkg:rule and //pkg:rule2, and add a dependency on //base
buildozer 'add deps //base' //pkg:rule //pkg:rule2

# A load for a skylark file in //pkg
buildozer 'new_load //tools/build_rules:build_test.bzl build_test' //pkg:__pkg__

# Replaces existing loads for build_test in //pkg
buildozer 'replace_load @rules_build//build:defs.bzl build_test' //pkg:__pkg__

# Replaces modules of loads using regular expressions.
#
# In this example
#     load("@rules_foo//foo:defs.bzl", "foo_library", "foo_test")
# will be replaced with
#     load("//third_party/build_defs/rules_foo/foo:defs.bzl", "foo_library", "foo_test")
buildozer 'substitute_load ^@([^/]*)//([^:].*)$ //third_party/build_defs/${1}/${2}' //pkg:__pkg__

# Change the default_visibility to public for the package //pkg
buildozer 'set default_visibility //visibility:public' //pkg:__pkg__

# Change all gwt_module targets to java_library in the package //pkg
buildozer 'set kind java_library' //pkg:%gwt_module

# Replace the dependency on pkg_v1 with a dependency on pkg_v2
buildozer 'replace deps //pkg_v1 //pkg_v2' //pkg:rule

# Replace all dependencies using regular expressions.
buildozer 'substitute deps //old/(.*) //new/${1}' //pkg:rule

# Delete the dependency on foo in every cc_library in the package
buildozer 'remove deps foo' //pkg:%cc_library

# Delete the testonly attribute in every rule in the package
buildozer 'remove testonly' '//pkg:*'

# Add a comment to the timeout attribute of //pkg:rule_test
buildozer 'comment timeout Delete\ this\ after\ 2015-12-31.' //pkg:rule_test

# Add a new rule at the end of the file
buildozer 'new java_library foo' //pkg:__pkg__

# Add a cc_binary rule named new_bin before the rule named tests
buildozer 'new cc_binary new_bin before tests' //:__pkg__

# Copy an attribute from `protolib` to `py_protolib`.
buildozer 'copy testonly protolib' //pkg:py_protolib

# Set two attributes in the same rule
buildozer 'set compile 1' 'set srcmap 1' //pkg:rule

# Make a default explicit in all soy_js rules in a package
buildozer 'set_if_absent allowv1syntax 1' //pkg:%soy_js

# Add an attribute new_attr with value "def_val" to all cc_binary rules
# Note that special characters will automatically be escaped in the string
buildozer 'add new_attr def_val' //:%cc_binary

打印命令

这些命令没有修改文件, 构建器在成功后返回 0 执行.

  • print <attribute(s)>: 对于每个目标,打印属性值 (见下文).
  • print_comment <attr>? <value>?: 打印与规则相关的注释, 列表中的属性或特定值.

打印命令打印属性的值。 如果目标没有 属性,在 stderr 上打印出警告.

有一些特殊的属性 print 命令 :

  • kind: 显示函数的名称
  • attrs: 显示规则的属性名称
  • label: 完全合格的标签
  • rule: 整个规则定义
  • startline: 规则在 BUILD 文件开始的行号
  • endline: 规则以 BUILD 文件结尾的行号
  • path: 包含规则的 BUILD 文件的绝对路径

实例

# Print the kind of a target
buildozer 'print kind' base  # output: cc_library

# Print the name of all cc_library in //base
buildozer 'print name' base:%cc_library

# Get the default visibility of the //base package
buildozer 'print default_visibility' base:%package

# Print labels of cc_library targets in //base that have a deps attribute
buildozer 'print label deps' base:%cc_library 2>/dev/null | cut -d' ' -f1

# Print the list of labels in //base that explicitly set the testonly attribute:
buildozer 'print label testonly' 'base:*' 2>/dev/null

# Print the entire definition (including comments) of the //base:heapcheck rule:
buildozer 'print rule' //base:heapcheck

转换标签

Buildoze在语法层面工作. 它不评价BUILD文件. 狦 需要查询 Bazel 拥有的信息, 请使用 bazel query。如果你有一个 bazel 标签列表, 有可能其中一部分是由 BUILD 生成的 扩展。 Budozer的标签与Bazel的标签略有不同. Bazel 关心生成的代码, 而 Buildoze 则查看 BUILD 文件 在宏观扩张之前.

要查看扩展的 BUILD 文件, 请尝试:

bazel query --output=build //path/to/BUILD

一次做多个更改

使用 buildozer -f <file> 从文件中装入命令和标签列表(参见 使用量 (见上文).

$ cat /tmp/cmds
# a comment
new cc_library foo|//buildtools/buildozer/BUILD
add deps //base //strings|add srcs foo.cc|//buildtools/buildozer:foo
add deps :foo|//buildtools/buildozer

$ buildozer -f /tmp/cmds
fixed //buildtools/buildozer/BUILD

命令列表一般会生成并可以大. 这是 效率 : 将命令分组, 这样每个文件都会被修改一次 。 文件为 平行处理.

或者,BUILD文件可以从标准输入读取并写入到 通过使用 - 软件包名称 :

$ cat /tmp/cmds
add deps //base //strings|-:foo|-:bar

$ cat some/path/BUILD | buildozer -f /tmp/cmds

此处写入更新结果 :foo 财务报告和审定财务报表 :bar 输入中的目标 BUILD 文件到标准输出.

Buildozer 命令也可以通过 shebang 线执行:

#!/usr/bin/env -S buildozer -f
#
# Adds //base and //string dependencies to :foo and :bar.

add deps //base //strings|-:foo|-:bar

使用 Buildozer 在记忆中

Builder 的一些客户端需要执行内存中的 builder 动作 (由于无法进入其文件系统的服务环境). 这可以使用, edit.ExecuteCommandsOnInlineFile,接受 命令和 BUILD 文件内容作为字节,应用更改并返回 原始文件内容 . 详情及执行情况见 /edit/buildozer.go

运行 Buildoze in-memory 的一些警告:

  • 该功能假定(并在一定程度上验证)所有命令都适用于 如果命令影响不同的文件, 则返回错误 路径.
  • 当引用目标时,该功能将无法可靠地确定目标是否 是本地或远程的。 因此,可在 输出. add dep //package/path:bar|//package/path:foo 将添加代码( d) //package/path:bar 而不是仅仅 :bar) (中文(简体) ).

错误代码

返回代码为:

  • 0 ,如果修改或只执行只读命令
  • 1 当出现使用错误时
  • 2 当至少一个命令失败时
  • 3 在无变化的情况下

源结构

  • buildozer/main.go : 构建器二进制的条目点
  • edit/buildozer.go : 执行建设者命令的功能
  • edit/edit.go: 执行ASTs上各种操作的图书馆功能. 这些
  • 函数由 builder.go 中的 impl 函数调用
  • edit/fix.go: 各项修正的功能 buildozer 'fix <fix(es)>' 命令,如清理未用载荷,将标签更改为标语等.
  • edit/types.go: 属性信息类型

版本与发布记录

@bazel/buildozer 共发布 39 个版本,首次发布于 2019/05/25;过去 12 个月发布了 0 个版本。

版本发布日期距今
8.2.1latest2025/06/101.4 年前
8.2.02025/04/301.5 年前
8.0.32025/02/051.8 年前
8.0.22025/01/301.8 年前
8.0.12025/01/161.8 年前
8.0.02025/01/091.8 年前

关于 @bazel/buildozer 的常见问题

@bazel/buildozer 是什么?

一个使用标准命令重写多个 BUILD 文件的命令行工具

如何安装 @bazel/buildozer?

在项目目录运行 npm install @bazel/buildozer,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 buildozer,可以用 npx buildozer 直接运行。

@bazel/buildozer 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/bazel__buildozer 是否存在。

@bazel/buildozer 可以商用吗?

@bazel/buildozer 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@bazel/buildozer 的下载量有多少?

根据 npm 官方下载统计,@bazel/buildozer 在 2026/10/08 – 2026/11/06 这 30 天内被下载 19,625 次,日均约 654 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bazel/buildozer 还在维护吗?

最新版本 8.2.1 发布于 2025/06/10(1.4 年前);至今共发布 39 个版本,其中过去 12 个月发布了 0 个;首次发布于 2019/05/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。