【问题标题】:bazel rules for the protobuf C++ compilerprotobuf C++ 编译器的 bazel 规则
【发布时间】:2016-08-23 19:42:54
【问题描述】:

我正在使用 Bazel 和 Google 的协议缓冲区。我想添加一个 Bazel 规则,以便我可以从 .proto 文件生成 C++ API。在 GNU make 中,我会这样做(简化示例):

%.h: %.cc
%.cc: %.proto
    protoc --cpp_out=. $<

我怎样才能使用 Bazel 完成相同的操作(即每当mymessage.proto 更改时生成 API)?

【问题讨论】:

标签: c++ protocol-buffers bazel


【解决方案1】:

我尝试了上述方法,但它似乎不起作用,我从protoc 收到一个错误,因为我试图创建两个目录,然后my-proto.h 目录不存在。相反,我做到了

genrule(
    name = "my-proto-gen",
    outs = ["my-proto.pb.h my-proto.pb.cc"],
    cmd = "$(location //third_party/protobuf:protoc) --cpp_out=$(GENDIR) $<",
    srcs = ["my-proto.proto"],
    tools = ["//third_party/protobuf:protoc"],
)

cc_library(
    name = "my-proto",
    srcs = ["my-proto.pb.cc"],
    hdrs = ["my-proto.pb.h"]
)

实际上只是检查是否创建了头文件并创建了bazel-genfiles 目录。

然后,您可以将 proto 构建包含在您的 cc_library 中作为 :my-proto。

更新: 要使这一切正常工作,请执行以下操作:

  1. 将以下内容添加到您的 WORKSPACE 文件中。这会下载 protobuf 库:

    http_archive(
        name = "protobuf",
        url = "https://github.com/google/protobuf/releases/download/v3.0.0/protobuf-cpp-3.0.0.zip",
        strip_prefix = "protobuf-3.0.0",
    )
    
  2. 创建一个 .bzl 文件(比如说 protobuf.bzl)并输入以下内容:

    def cpp_proto(name, src):
      native.genrule(
          name = "%s-gen" % name,
          outs = ["%s.pb.cc" % name, "%s.pb.h" % name],
          cmd = "$(location @protobuf//:protoc) --cpp_out=$(GENDIR) $<",
          srcs = [src],
          tools = ["@protobuf//:protoc"],
      )
    
      native.cc_library(
          name = name,
          srcs = ["%s.pb.cc" % name],
          hdrs = ["%s.pb.h" % name],
      )
    
  3. 在您的构建文件中,添加load(':protobuf.bzl', 'cpp_proto')

  4. 您现在可以像这样使用宏:

    cpp_proto(
        name = "my-proto",
        src = "my-proto.proto"
    )
    
    cc_library(
        name = "my-program",
        srcs = ["my-program.cc"],
        deps = [
            ":my-proto",
        ],
    )
    

【讨论】:

  • 这仅适用于 proto 文件在工作区中的情况。如果它在子文件夹中,则生成的文件不在 bazel 期望它们所在的文件夹中并且失败。我需要将--proto_path 添加到protoc 调用中。
【解决方案2】:

对 cc_proto_library 的原生支持最近登陆 Bazel:http://bazel.build/blog/2017/02/27/protocol-buffers.html。

tl;dr,在设置您的WORKSPACE 文件一次后,

cc_proto_library(
    name = "person_cc_proto",
    deps = [":person_proto"],
)

proto_library(
    name = "person_proto",
    srcs = ["person.proto"],
    deps = [":address_proto"],
)

...

那么,

$ bazel build :person_cc_proto

https://github.com/cgrushko/proto_library 有一个例子。

要点是您定义一个proto_library 将.proto 文件“导入”到Bazel,并定义cc_proto_library 将其编译为C++。默认情况下,protocol buffer 编译器和运行时分别取自 @com_google_protobuf//:protoc 和 @com_google_protobuf_cc//:cc_toolchain。

这种分离的原因是为了启用需要编译成多种语言的大型原型图。

【讨论】:

    【解决方案3】:

    有几种方法。作为一次性的,您可以创建一个 genrule 来对某些输入执行命令:

    genrule(
        name = "my-proto-gen",
        outs = ["my-proto.cc", "my-proto.h"],
        cmd = "$(location //path/to:protoc) --cpp_out=$@ $<",
        srcs = ["my-proto.proto"],
        tools = ["//path/to:protoc"],
    )
    
    cc_library(
        name = "my-proto",
        srcs = ["my-proto.cc"],
        hdrs = ["my-proto.h"],
    )
    

    根据您的制作规则,我假设您想要多次执行此操作。在这种情况下,您可以在 .bzl 文件中定义 宏。宏基本上是调用构建规则的函数:

    # In, say, foo/bar.bzl.
    def cpp_proto(name, src):
      native.genrule(
          name = "%s-gen" % name,
          outs = ["%s.cc" % name, "%s.h" % name],
          cmd = "$(location //path/to:protoc) --cpp_out=$@ $<",
          srcs = [src],
          tools = ["//path/to:protoc"],
      )
    
      native.cc_library(
          name = name,
          srcs = ["%s.cc" % name],
          hdrs = ["%s.h" % name],
      )
    

    然后在 foo/BUILD 中,您可以导入并使用您的宏来简洁地调用规则:

    load('//foo:bar.bzl', 'cpp_proto')
    cpp_proto('my-proto', 'my_proto.proto')
    

    那么你可以依赖cc_librarys、cc_binarys和cc_tests中的//foo:my-proto。

    最后,您可能想关注https://github.com/bazelbuild/bazel/issues/52(并且只需使用 mzhaom 的宏)。

    【讨论】:

    • 感谢mzhaom宏的指针,我不知何故错过了它。但是,我真的不明白如何使用它。线程末尾还建议了另外两个替代方案,但我无法让它们中的任何一个运行。原生 protobuf 支持似乎缺少 cpp 部分,而且 pubref 规则总是抛出异常。
    【解决方案4】:

    我在https://github.com/pubref/rules_protobuf 汇总了一组 protobuf 生成规则。除了许多其他语言之外,它还支持 C++。希望对您有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-13
      • 1970-01-01
      • 1970-01-01
      • 2015-06-17
      • 2022-06-15
      • 1970-01-01
      相关资源
      最近更新 更多