Go 我可以在Bazel中生成生成生成文件吗?

Go 我可以在Bazel中生成生成生成文件吗?,go,build,bazel,Go,Build,Bazel,我想使用go lint工具为bazel生成一个构建文件 我将有一个go二进制文件,它将执行类似于以下bash脚本的操作: #!/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

我想使用go lint工具为bazel生成一个构建文件

我将有一个go二进制文件,它将执行类似于以下bash脚本的操作:

#!/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
这就产生了:

# 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 = [
    ],
)
当然,上面的构建文件还不起作用,但我想首先确保我所采用的方法是有效的

  • 如何在bazel中指定预构建阶段
  • 可能吗
通常情况下,您无法生成生成文件,它们必须在生成开始时存在。Bazel的一般构建阶段包括:

  • 分析在命令行上指定的目标
  • 在指定的每个目录中查找生成文件
  • 解析那些目标提到的构建文件(等等)
  • 生成要执行的操作树(例如,“运行shell脚本”)
  • 实际执行操作
因此,在执行脚本时,读取构建文件的时间已经很长了

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

也就是说

Skylark远程存储库确实允许您执行代码在其他存储库中写入文件,包括构建文件。因此,从理论上讲,你可以有(未经测试的):

然后在工作区文件中执行以下操作:

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

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

谢谢!我想知道这是否是bazel项目的公认行为?有什么缺点吗?我的意思是,它有点黑客和脆弱(您正在手动指定可能更改的目录)。为什么Skylark远程存储库允许这样做?预期用途是什么?@JosephGarvin为了能够支持没有构建文件的第三方软件包/存储库(例如,包括下载的zip文件的头文件),我们在Google通常会在需要时手动运行代码生成器(也可以在IDE中自动运行),并在源代码管理中签入输出。
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)}
)
load('//path/to/your:genrepo.bzl', 'generated_repo')
generated_repo(
    name = "pwd",
    paths = ["src", "test", "third_party"],
)