验证bazel中的步骤

Ant*_*sse 8 bazel

我正在寻找一个好的食谱运行"检查"或巴泽尔"验证"的步骤,如go vet,gofmt,pylint,cppcheck.这些步骤不会创建任何输出文件.唯一重要的是返回代码(如测试).

现在我正在使用以下配方:

sh_test(
    name = "verify-pylint",
    srcs = ["verify-pylint.sh"],
    data = ["//:all-srcs"],
)
Run Code Online (Sandbox Code Playgroud)

而且verify-pylint.sh看起来是这样的:

find . -name '*.py' | xargs pylint
Run Code Online (Sandbox Code Playgroud)

这有两个问题:

  • 验证逻辑在shell脚本和BUILD文件之间分开.理想情况下,我希望两者都在同一个地方(在BUILD文件中)
  • 只要其中一个源文件发生更改(in //:all-srcs),就会在每个文件上bazel test verify-pylint重新运行pylint(这可能很昂贵/很慢).

在bazel运行这些步骤的惯用方法是什么?

Lás*_*zló 2

解决方案不止一种。

最简洁的方法是在构建时进行验证:genrule为要验证的每个文件(或一批文件)创建一个,如果验证成功,则 genrule 输出一些内容,如果失败,则规则不输出任何内容,这构建也会自动失败。

由于验证的成功取决于文件的内容,并且相同的输入应该产生相同的输出,因此genrules应该生成一个依赖于输入内容的输出文件。最方便的方法是,如果验证成功,则将文件的摘要写入输出,如果验证失败,则不输出。

为了使验证器可重用,您可以创建一个Skylark 宏并在所有包中使用它。

为了将所有这些放在一起,您可以编写如下内容。

内容//tools:py_verify_test.bzl

def py_verify_test(name, srcs, visibility = None):
    rules = {"%s-file%d" % (name, hash(s)): s for s in srcs}
    for rulename, src in rules.items():
        native.genrule(
            name = rulename,
            srcs = [s],
            outs = ["%s.md5" % rulename],
            cmd = "$(location //tools:py_verifier) $< && md5sum $< > $@",
            tools = ["//tools:py_verifier"],
            visibility = ["//visibility:private"],
        )

    native.sh_test(
        name = name,
        srcs = ["//tools:build_test.sh"],
        data = rules.keys(),
        visibility = visibility,
    )
Run Code Online (Sandbox Code Playgroud)

内容//tools:build_test.sh

#!/bin/true
# If the test rule's dependencies could be built,
# then all files were successfully verified at
# build time, so this test can merely return true.
Run Code Online (Sandbox Code Playgroud)

内容//tools:BUILD

# I just use sh_binary as an example, this could
# be a more complicated rule of course.
sh_binary(
    name = "py_verifier",
    srcs = ["py_verifier.sh"],
    visibility = ["//visibility:public"],
)
Run Code Online (Sandbox Code Playgroud)

任何想要验证文件的包的内容:

load("//tools:py_verify_test.bzl", "py_verify_test")

py_verify_test(
    name = "verify",
    srcs = glob(["**/*.py"]),
)
Run Code Online (Sandbox Code Playgroud)