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?
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.
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).
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.
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:
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",
)
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],
)
In your build files, add in load(':protobuf.bzl', 'cpp_proto')
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",
],
)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With