aboutsummaryrefslogtreecommitdiff
path: root/internal/cc_grpc_library.bzl
diff options
context:
space:
mode:
Diffstat (limited to 'internal/cc_grpc_library.bzl')
-rw-r--r--internal/cc_grpc_library.bzl118
1 files changed, 118 insertions, 0 deletions
diff --git a/internal/cc_grpc_library.bzl b/internal/cc_grpc_library.bzl
new file mode 100644
index 0000000..a6e8ab0
--- /dev/null
+++ b/internal/cc_grpc_library.bzl
@@ -0,0 +1,118 @@
+"""Rule for running the gRPC C++ code generator.
+
+This is a simplified and modernised version of the upstream gRPC
+`bazel/cc_grpc_library.bzl` file, which as of release v1.45
+(published 2022-03-19) does not support separating the `proto_library` and
+`cc_proto_library` targets into separate packages or repositories.
+
+The following logic should eventually find a home in upstream gRPC, rules_proto,
+or rules_cc so that the Bazel Remote APIs repository can be further decoupled
+from language-specific concerns.
+"""
+
+load("@com_github_grpc_grpc//bazel:protobuf.bzl", "get_include_protoc_args")
+
+_EXT_PROTO = ".proto"
+_EXT_PROTODEVEL = ".protodevel"
+_EXT_GRPC_HDR = ".grpc.pb.h"
+_EXT_GRPC_SRC = ".grpc.pb.cc"
+
+def _drop_proto_ext(name):
+ if name.endswith(_EXT_PROTO):
+ return name[:-len(_EXT_PROTO)]
+ if name.endswith(_EXT_PROTODEVEL):
+ return name[:-len(_EXT_PROTODEVEL)]
+ fail("{!r} does not end with {!r} or {!r}".format(
+ name,
+ _EXT_PROTO,
+ _EXT_PROTODEVEL,
+ ))
+
+def _proto_srcname(file):
+ """Return the Protobuf source name for a proto_library source file.
+
+ The source name is what the Protobuf compiler uses to identify a .proto
+ source file. It is relative to the compiler's `--proto_path` flag.
+ """
+ ws_root = file.owner.workspace_root
+ if ws_root != "" and file.path.startswith(ws_root):
+ return file.path[len(ws_root) + 1:]
+ return file.short_path
+
+def _cc_grpc_codegen(ctx):
+ """Run the gRPC C++ code generator to produce sources and headers"""
+ proto = ctx.attr.proto[ProtoInfo]
+ proto_srcs = proto.check_deps_sources.to_list()
+ proto_imports = proto.transitive_imports.to_list()
+
+ protoc_out = ctx.actions.declare_directory(ctx.attr.name + "_protoc_out")
+ protoc_outputs = [protoc_out]
+ rule_outputs = []
+
+ for proto_src in proto_srcs:
+ srcname = _drop_proto_ext(_proto_srcname(proto_src))
+ basename = _drop_proto_ext(proto_src.basename)
+
+ out_hdr = ctx.actions.declare_file(basename + _EXT_GRPC_HDR)
+ out_src = ctx.actions.declare_file(basename + _EXT_GRPC_SRC)
+
+ protoc_out_prefix = protoc_out.basename
+ protoc_out_hdr = ctx.actions.declare_file(
+ "{}/{}".format(protoc_out_prefix, srcname + _EXT_GRPC_HDR),
+ )
+ protoc_out_src = ctx.actions.declare_file(
+ "{}/{}".format(protoc_out_prefix, srcname + _EXT_GRPC_SRC),
+ )
+
+ rule_outputs.extend([out_hdr, out_src])
+ protoc_outputs.extend([protoc_out_hdr, protoc_out_src])
+
+ ctx.actions.expand_template(
+ template = protoc_out_hdr,
+ output = out_hdr,
+ substitutions = {},
+ )
+ ctx.actions.expand_template(
+ template = protoc_out_src,
+ output = out_src,
+ substitutions = {},
+ )
+
+ plugin = ctx.executable._protoc_gen_grpc
+ protoc_args = ctx.actions.args()
+ protoc_args.add("--plugin", "protoc-gen-grpc=" + plugin.path)
+ protoc_args.add("--grpc_out", protoc_out.path)
+
+ protoc_args.add_all(get_include_protoc_args(proto_imports))
+ protoc_args.add_all(proto_srcs, map_each = _proto_srcname)
+
+ ctx.actions.run(
+ executable = ctx.executable._protoc,
+ arguments = [protoc_args],
+ inputs = proto_srcs + proto_imports,
+ outputs = protoc_outputs,
+ tools = [plugin],
+ )
+
+ return DefaultInfo(files = depset(rule_outputs))
+
+cc_grpc_codegen = rule(
+ implementation = _cc_grpc_codegen,
+ attrs = {
+ "proto": attr.label(
+ mandatory = True,
+ allow_single_file = True,
+ providers = [ProtoInfo],
+ ),
+ "_protoc_gen_grpc": attr.label(
+ default = Label("@com_github_grpc_grpc//src/compiler:grpc_cpp_plugin"),
+ executable = True,
+ cfg = "host",
+ ),
+ "_protoc": attr.label(
+ default = Label("//external:protocol_compiler"),
+ executable = True,
+ cfg = "host",
+ ),
+ },
+)