构建器
Buildozer 是重写多行的命令行工具 巴泽尔 使用 BUILD 文件 标准命令.
安装
- 构建二进制并把它放入您的 $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联 合 国 扩展名,其中指定的顶级变量包含返回值 页:1use_extension电话.use_repo_remove <use_extension variable name> <repo(s)>数字 : 确保给定的寄存器 没有 通过use_repo页:1 上一级变量包含返回的扩展名 数值 ause_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: 属性信息类型