我正在使用Bazel和Google的协议缓冲区。我想添加一个Bazel规则,以便可以从.proto文件生成C++ API。在GNU make中,我会这样做(简化示例):
%.h: %.cc
%.cc: %.proto
protoc --cpp_out=. $<
我该如何使用Bazel实现相同的功能(即在mymessage.proto更改时生成API)?
我正在使用Bazel和Google的协议缓冲区。我想添加一个Bazel规则,以便可以从.proto文件生成C++ API。在GNU make中,我会这样做(简化示例):
%.h: %.cc
%.cc: %.proto
protoc --cpp_out=. $<
我尝试了上述方法,但似乎并没有起作用。在尝试创建两个目录时,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
。
更新: 要使整个过程正常工作,请执行以下操作:
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",
],
)
protoc
调用中添加 --proto_path
。 - morxacc_proto_library
。详情请见:http://bazel.build/blog/2017/02/27/protocol-buffers.html。简而言之,在设置一次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++代码。协议缓冲区的编译器和运行时默认从@com_google_protobuf//:protoc
和@com_google_protobuf_cc//:cc_toolchain
获取。
这种分离的原因是为了支持需要编译为多种语言的大型proto图。
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文件中定义一个宏(macro)。宏本质上是调用构建规则的函数:
# 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],
)
load('//foo:bar.bzl', 'cpp_proto')
cpp_proto('my-proto', 'my_proto.proto')
那么你可以在 cc_library
, cc_binary
和 cc_test
中使用 //foo:my-proto
.
最后,您可能希望遵循 https://github.com/bazelbuild/bazel/issues/52 (并只是使用 mzhaom 的宏)。