protobuf C++ 编译器的 bazel 规则
bazel rules for the protobuf C++ compiler
我正在使用 Bazel 和 Google 的协议缓冲区。我想添加一个 Bazel 规则,这样我就可以从 .proto
文件生成 C++ API。在 GNU make 中,我会做(简化示例):
%.h: %.cc
%.cc: %.proto
protoc --cpp_out=. $<
我如何使用 Bazel 完成相同的任务(即每当 mymessage.proto
发生变化时生成 API)?
有几种方法。作为一次性的,您可以创建一个 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')
然后你可以依赖 //foo:my-proto
来自 cc_library
s、cc_binary
s 和 cc_test
s。
最后,您可能想要遵循 https://github.com/bazelbuild/bazel/issues/52(并且只使用 mzhaom 的宏)。
我尝试了上面的方法,但它似乎没有用,我在尝试创建两个目录时从 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
目录中。
然后您可以将原型构建包含在您的 cc_library
中作为 :my-proto
。
更新:
要使这一切正常工作,请执行以下操作:
将以下内容添加到您的 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",
)
创建一个 .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],
)
在您的构建文件中,添加 load(':protobuf.bzl', 'cpp_proto')
您现在可以这样使用宏了:
cpp_proto(
name = "my-proto",
src = "my-proto.proto"
)
cc_library(
name = "my-program",
srcs = ["my-program.cc"],
deps = [
":my-proto",
],
)
我在 https://github.com/pubref/rules_protobuf 整理了一套 protobuf 生成规则。除了许多其他语言外,它还支持 C++。希望你觉得它有用。
对 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
到 "import" .proto 文件到 Bazel,然后 cc_proto_library
将它编译成 C++。协议缓冲区编译器和运行时默认分别取自 @com_google_protobuf//:protoc
和 @com_google_protobuf_cc//:cc_toolchain
。
这种分离的原因是为了启用需要编译成多种语言的大型原型图。
我正在使用 Bazel 和 Google 的协议缓冲区。我想添加一个 Bazel 规则,这样我就可以从 .proto
文件生成 C++ API。在 GNU make 中,我会做(简化示例):
%.h: %.cc
%.cc: %.proto
protoc --cpp_out=. $<
我如何使用 Bazel 完成相同的任务(即每当 mymessage.proto
发生变化时生成 API)?
有几种方法。作为一次性的,您可以创建一个 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')
然后你可以依赖 //foo:my-proto
来自 cc_library
s、cc_binary
s 和 cc_test
s。
最后,您可能想要遵循 https://github.com/bazelbuild/bazel/issues/52(并且只使用 mzhaom 的宏)。
我尝试了上面的方法,但它似乎没有用,我在尝试创建两个目录时从 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
目录中。
然后您可以将原型构建包含在您的 cc_library
中作为 :my-proto
。
更新: 要使这一切正常工作,请执行以下操作:
将以下内容添加到您的 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", )
创建一个 .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], )
在您的构建文件中,添加
load(':protobuf.bzl', 'cpp_proto')
您现在可以这样使用宏了:
cpp_proto( name = "my-proto", src = "my-proto.proto" ) cc_library( name = "my-program", srcs = ["my-program.cc"], deps = [ ":my-proto", ], )
我在 https://github.com/pubref/rules_protobuf 整理了一套 protobuf 生成规则。除了许多其他语言外,它还支持 C++。希望你觉得它有用。
对 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
到 "import" .proto 文件到 Bazel,然后 cc_proto_library
将它编译成 C++。协议缓冲区编译器和运行时默认分别取自 @com_google_protobuf//:protoc
和 @com_google_protobuf_cc//:cc_toolchain
。
这种分离的原因是为了启用需要编译成多种语言的大型原型图。