我正在尝试使用Bazel's Protocol Buffer Rules来编译(生成)Python语言绑定和任何依赖项。我的项目布局很简单,只有一个目录proto
,包含.proto
文件和BUILD
文件。
WORKSPACE
BUILD.six
|-- proto
| |-- example.proto
| |-- BUILD
我的WORKSPACE
文件:
workspace(name = "com_example")
http_archive(
name = "com_google_protobuf",
strip_prefix = "protobuf-3.4.1",
urls = ["https://github.com/google/protobuf/archive/v3.4.1.zip"],
)
new_http_archive(
name = "six_archive",
build_file = "six.BUILD",
url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz",
)
bind(
name = "six",
actual = "@six_archive//:six",
)
在我的WORKSPACE
文件中,为了便于阅读,省略了下载文件的预期SHA-256哈希值。由于http_archive包含Bazel WORKSPACE
和BUILD
文件,因此使用了ProtoBuf GitHub repo WORKSPACE规则。
{6}必须使用new_http_archive,因为它不是Bazel工作区。另外值得注意的是,我的WORKSPACE
文件(来自Bazel文档)必须提供Bazel transitive dependencies:
Bazel只读取WORKSPACE文件中列出的依赖项。如果你的 project(A)依赖于列出依赖项的另一个项目(B) 在其WORKSPACE文件中的第三个项目(C),您将必须添加两个B. 和C到项目的WORKSPACE文件。
six.BUILD
直接来自回购并在本地保存:
我的BUILD
文件
load("@com_google_protobuf//:protobuf.bzl", "py_proto_library")
py_proto_library(
name = "py",
use_grpc_plugin = True,
deps = [
"@com_google_protobuf//:protobuf_python",
":example_proto",
],
visibility = ["//visibility:public"],
# protoc = "@com_google_protobuf//:protoc",
)
proto_library(
name = "example_proto",
srcs = ["example.proto"],
)
建设时出现问题:
bazel build //proto:py
输出(为便于阅读而格式化):
proto/BUILD:3:1:
no such target '//:protobuf_python':
target 'protobuf_python' not declared in package '' defined by BUILD and referenced by '//proto:py'.
ERROR: Analysis of target '//proto:py' failed; build aborted.
但是,从命令行构建外部依赖项有效:
bazel build @com_google_protobuf//:protobuf_python
输出(为了便于阅读而截断):
INFO: Found 1 target...
...
INFO: Elapsed time: 51.577s, Critical Path: 8.63s
protobuf_python
目标已明确定义且公开:
答案 0 :(得分:2)
问题是你的目标(// proto:py)取决于//:protobuf_python,而不是@com_gooogle_protobuf //:protobuf_python。您可以使用bazel查询进行确认。
$ bazel query --output build //proto:py
# proto/BUILD:3:1
py_library(
name = "py",
visibility = ["//visibility:public"],
generator_name = "py",
generator_function = "py_proto_library",
generator_location = "proto/BUILD:3",
deps = ["//:protobuf_python", "@com_google_protobuf//:protobuf_python", "//proto:example_proto"],
imports = [],
srcs = [],
)
您可以在deps列表中看到它。所以现在的问题是,为什么它取决于那个?你当然没有把它设定在那里。答案是,由于py_proto_library是一个宏,它可以做任何想做的事。
特别是宏的这些行会给你带来麻烦:
https://github.com/google/protobuf/blob/6032746882ea48ff6d983df8cb77e2ebf399bf0c/protobuf.bzl#L320 https://github.com/google/protobuf/blob/6032746882ea48ff6d983df8cb77e2ebf399bf0c/protobuf.bzl#L373-L374
py_proto_library有一个名为default_runtime的属性,它附加到deps列表。默认值为":protobuf_python"。但是只有在声明protobuf_python的同一个存储库中使用宏时才有效。
因此,您可以通过在py_proto_librarys属性中设置default_runtime = "@com_google_protobuf//:protobuf_python"
来解决此问题。