【问题标题】:Can I generate a BUILD file in Bazel?我可以在 Bazel 中生成 BUILD 文件吗?
【发布时间】:2016-07-13 17:47:06
【问题描述】:

我想使用 go lint 工具为 bazel 生成 BUILD 文件。

我会有一个执行类似 bash 脚本的 go 二进制文件:

#!/bin/bash

cat <<EOF > BUILD
# THIS FILE IS AUTOGENERATED

package(default_visibility = ["//visibility:public"])

load("//go:def.bzl", "go_prefix", "go_library", "go_binary", "go_test")
EOF

for pkg in `go list -f {{.ImportPath}} ./...`; do
    go list -f "`cat test.in`" $pkg >> "BUILD";
done

buildifier -mode fix BUILD

test.in 文件包含:

{{ if eq .Name "main" }}
go_binary
{{else}}
go_library
{{end}}
("{{.Name}}",
    srcs=[
        {{range .GoFiles}}
            "{{.}}",
        {{end}} 
    ],
    deps=[
        {{range .Imports}}
            "{{.}}",
        {{end}} 
    ],
    csrcs=[
        {{range .CgoFiles}}
            "{{.}}",
        {{end}} 
    ],
    swig_srcs=[
        {{range .SwigFiles}}
            "{{.}}",
        {{end}} 
    ],
    cxxswig=[
        {{range .SwigCXXFiles}}
            "{{.}}",
        {{end}} 
    ],
    cflags=[
        {{range .CgoCFLAGS}}
            "{{.}}",
        {{end}} 
    ],
    cxxflags=[
        {{range .CgoCXXFLAGS}}
            "{{.}}",
        {{end}} 
    ],
    cppflags=[
        {{range .CgoCPPFLAGS}}
            "{{.}}",
        {{end}} 
    ],           
    {{ with $ctx := context}}
        {{$ctx.InstallSuffix}}
    {{end}}    
)

这会产生:

# THIS FILE IS AUTOGENERATED

package(default_visibility = ["//visibility:public"])

load("//go:def.bzl", "go_prefix", "go_library", "go_binary", "go_test")

go_library

(
    "tensorflow",
    srcs = [
        "doc.go",
        "gen.go",
        "graph.go",
        "session.go",
    ],
    deps = [
        "C",
        "encoding/binary",
        "fmt",
        "github.com/golang/protobuf/proto",
        "github.com/tensorflow/tensorflow/tensorflow/contrib/go/proto",
        "math",
        "reflect",
        "runtime",
        "strings",
        "unsafe",
    ],
    csrcs = [
        "lib.go",
        "tensor.go",
    ],
    swig_srcs = [
    ],
    cxxswig = [
        "tensorflow.swigcxx",
    ],
    cflags = [
        "-I/Users/fmilo/workspace/gopath/src/github.com/tensorflow/tensorflow/tensorflow/contrib/go/../../../",
    ],
    cxxflags = [
        "-I/Users/fmilo/workspace/gopath/src/github.com/tensorflow/tensorflow/tensorflow/contrib/go/../../../",
        "-std=c++11",
    ],
    cppflags = [
    ],
)

go_library

(
    "tensorflow",
    srcs = [
        "allocation_description.pb.go",
        "attr_value.pb.go",
        "config.pb.go",
        "cost_graph.pb.go",
        "device_attributes.pb.go",
        "event.pb.go",
        "function.pb.go",
        "graph.pb.go",
        "kernel_def.pb.go",
        "log_memory.pb.go",
        "master.pb.go",
        "memmapped_file_system.pb.go",
        "meta_graph.pb.go",
        "named_tensor.pb.go",
        "op_def.pb.go",
        "queue_runner.pb.go",
        "saved_tensor_slice.pb.go",
        "saver.pb.go",
        "step_stats.pb.go",
        "summary.pb.go",
        "tensor.pb.go",
        "tensor_description.pb.go",
        "tensor_shape.pb.go",
        "tensor_slice.pb.go",
        "tensorflow_server.pb.go",
        "test_log.pb.go",
        "tf_ops_def.go",
        "types.pb.go",
        "variable.pb.go",
        "versions.pb.go",
        "worker.pb.go",
    ],
    deps = [
        "fmt",
        "github.com/golang/protobuf/proto",
        "github.com/golang/protobuf/ptypes/any",
        "math",
    ],
    csrcs = [
    ],
    swig_srcs = [
    ],
    cxxswig = [
    ],
    cflags = [
    ],
    cxxflags = [
    ],
    cppflags = [
    ],
)

go_library

(
    "tensorflow_error",
    srcs = [
        "error_codes.pb.go",
    ],
    deps = [
        "fmt",
        "github.com/golang/protobuf/proto",
        "math",
    ],
    csrcs = [
    ],
    swig_srcs = [
    ],
    cxxswig = [
    ],
    cflags = [
    ],
    cxxflags = [
    ],
    cppflags = [
    ],
)

go_library

(
    "tensorflow_grpc",
    srcs = [
        "master_service.pb.go",
        "worker_service.pb.go",
    ],
    deps = [
        "fmt",
        "github.com/golang/protobuf/proto",
        "math",
        "tensorflow/core/protobuf",
    ],
    csrcs = [
    ],
    swig_srcs = [
    ],
    cxxswig = [
    ],
    cflags = [
    ],
    cxxflags = [
    ],
    cppflags = [
    ],
)

当然,上面的 BUILD 文件还不能工作,但我想首先确保我所追求的方法是有效的。

  • 如何在 bazel 中指定预构建阶段?
  • 有可能吗?

【问题讨论】:

  • 我们在谷歌一般做的是在需要时手动运行代码生成器(也可以在IDE中自动运行),并在源代码管理中检查输出。

标签: go build bazel


【解决方案1】:

一般来说,您不能生成 BUILD 文件,它们必须在构建开始时就存在。 Bazel 的一般构建阶段是:

  • 解析您在命令行中指定的目标。
  • 在指定的每个目录中查找 BUILD 文件。
  • 解析那些目标提到的 BUILD 文件(等等)。
  • 生成要执行的操作树(例如,“运行 shell 脚本”)。
  • 实际执行操作。

所以,当你的脚本被执行时,读取 BUILD 文件的时间已经结束了。

此外,输出被放置在它们自己的目录中(在 bazel-out 下),因此它们甚至不会出现在您的源代码树中而不进行修改。

也就是说……

Skylark 远程存储库允许您执行代码以在其他存储库中写入文件,包括 BUILD 文件。所以理论上你可以有类似(未经测试)的东西:

def _gen_repo_impl(repo_ctx):
  # Writes external/reponame/BUILD
  repo_ctx.execute("/your/bash/script.sh")
  for path in repo_ctx.attr.paths:
    repo_ctx.symlink(path, path.basename)

generated_repo = repository_rule(
    implementation = _gen_repo_impl,
    attrs = {"paths": attr.label_list(allow_files = True)}
)

然后在您的 WORKSPACE 文件中,执行以下操作:

load('//path/to/your:genrepo.bzl', 'generated_repo')
generated_repo(
    name = "pwd",
    paths = ["src", "test", "third_party"],
)

然后您可以构建/依赖@pwd//...,并且存储库规则会生成一个外部存储库,其中包含指向 src、测试和第三方的符号链接(理论上...我的代码可能有一些拼写错误)。

【讨论】:

  • 谢谢!我想知道这是否是 bazel 项目的可接受行为?有什么缺点吗?
  • 我的意思是,它有点老套和脆弱(您手动指定可能会更改的目录)。
  • 为什么云雀远程仓库允许这样做?预期用途是什么?
  • @JosephGarvin 能够支持没有 BUILD 文件的第 3 方包/存储库(例如,包括下载的 zip 文件的标头)
猜你喜欢
  • 2020-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多