为什么公开显示的Bazel ProtoBuf目标“未声明”

时间:2017-10-07 10:42:39

标签: git protocol-buffers bazel

我正在尝试使用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 WORKSPACEBUILD文件,因此使用了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目标已明确定义且公开:

1 个答案:

答案 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"来解决此问题。