Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bazel rules for the protobuf C++ compiler

I'm using Bazel and Google's protocol buffers. I want to add a Bazel rule so I can generate the C++ API from the .proto files. In GNU make, I would do (simplified example):

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

How can I accomplish the same (i.e. generate the API whenever mymessage.proto changes) using Bazel?

like image 250
morxa Avatar asked Aug 23 '16 19:08

morxa


People also ask

What is Protobuf C?

This is protobuf-c, a C implementation of the Google Protocol Buffers data serialization format. It includes libprotobuf-c , a pure C library that implements protobuf encoding and decoding, and protoc-c , a code generator that converts Protocol Buffer . proto files to C descriptor code.

What is a Bazel rule?

A rule defines a series of actions that Bazel performs on inputs to produce a set of outputs, which are referenced in providers returned by the rule's implementation function. For example, a C++ binary rule might: Take a set of . cpp source files (inputs). Run g++ on the source files (action).

Does Protobuf have inheritance?

Protobuf doesn't support inheritance. Having a common header and using composition is the best solution. You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.


2 Answers

I tried the above and it didn't seem to work, I got an error from protoc for trying to create two directories, then that the my-proto.h directory didn't exist. Instead, I did

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"]
)

Which actually just checks to see that the header file is created and creates it bazel-genfiles directory.

You can then include the proto build in your cc_library as :my-proto.

UPDATE: To get this entire thing to work, do the following:

  1. Add the following to your WORKSPACE file. This downloads the protobuf library:

    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. Create a .bzl file (let's say protobuf.bzl) and put in the following:

    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. In your build files, add in load(':protobuf.bzl', 'cpp_proto')

  4. You can now use the macro as such:

    cpp_proto(
        name = "my-proto",
        src = "my-proto.proto"
    )
    
    cc_library(
        name = "my-program",
        srcs = ["my-program.cc"],
        deps = [
            ":my-proto",
        ],
    )
    
like image 145
Sam Avatar answered Oct 13 '22 20:10

Sam


Native support for cc_proto_library has recently landed in Bazel: http://bazel.build/blog/2017/02/27/protocol-buffers.html.

tl;dr, after setting your WORKSPACE file once,

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

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

...

Then,

$ bazel build :person_cc_proto

There's an example at https://github.com/cgrushko/proto_library.

The gist is that you define a proto_library to "import" you .proto file into Bazel, and cc_proto_library to compile it to C++. The protocol buffer compiler and runtimes are taken by default from @com_google_protobuf//:protoc and @com_google_protobuf_cc//:cc_toolchain, respectively.

The reason for this separation is to enable large proto graphs that need to be compiled to multiple languages.

like image 31
user1071136 Avatar answered Oct 13 '22 18:10

user1071136