1 """Generates C++ grpc stubs from proto_library rules.
3 This is an internal rule used by cc_grpc_library, and shouldn't be used
7 def generate_cc_impl(ctx):
8 """Implementation of the generate_cc rule."""
9 protos = [f for src in ctx.attr.srcs for f in src.proto.direct_sources]
10 includes = [f for src in ctx.attr.srcs for f in src.proto.transitive_imports]
12 # label_len is length of the path from WORKSPACE root to the location of this build file
14 # proto_root is the directory relative to which generated include paths should be
17 # The +1 is for the trailing slash.
18 label_len += len(ctx.label.package) + 1
19 if ctx.label.workspace_root:
20 label_len += len(ctx.label.workspace_root) + 1
21 proto_root = "/" + ctx.label.workspace_root
23 if ctx.executable.plugin:
24 outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.h" for proto in protos]
25 outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.cc" for proto in protos]
26 if ctx.attr.generate_mocks:
27 outs += [proto.path[label_len:-len(".proto")] + "_mock.grpc.pb.h" for proto in protos]
29 outs += [proto.path[label_len:-len(".proto")] + ".pb.h" for proto in protos]
30 outs += [proto.path[label_len:-len(".proto")] + ".pb.cc" for proto in protos]
31 out_files = [ctx.actions.declare_file(out) for out in outs]
32 dir_out = str(ctx.genfiles_dir.path + proto_root)
35 if ctx.executable.plugin:
36 arguments += ["--plugin=protoc-gen-PLUGIN=" + ctx.executable.plugin.path]
37 flags = list(ctx.attr.flags)
38 if ctx.attr.generate_mocks:
39 flags.append("generate_mock_code=true")
40 arguments += ["--PLUGIN_out=" + ",".join(flags) + ":" + dir_out]
41 tools = [ctx.executable.plugin]
43 arguments += ["--cpp_out=" + ",".join(ctx.attr.flags) + ":" + dir_out]
46 # Import protos relative to their workspace root so that protoc prints the
47 # right include paths.
48 for include in includes:
49 directory = include.path
50 if directory.startswith("external"):
51 external_sep = directory.find("/")
52 repository_sep = directory.find("/", external_sep + 1)
53 arguments += ["--proto_path=" + directory[:repository_sep]]
55 arguments += ["--proto_path=."]
56 # Include the output directory so that protoc puts the generated code in the
58 arguments += ["--proto_path={0}{1}".format(dir_out, proto_root)]
59 arguments += [proto.path for proto in protos]
61 # create a list of well known proto files if the argument is non-None
62 well_known_proto_files = []
63 if ctx.attr.well_known_protos:
64 f = ctx.attr.well_known_protos.files.to_list()[0].dirname
65 if f != "external/com_google_protobuf/src/google/protobuf":
66 print("Error: Only @com_google_protobuf//:well_known_protos is supported")
68 # f points to "external/com_google_protobuf/src/google/protobuf"
69 # add -I argument to protoc so it knows where to look for the proto files.
70 arguments += ["-I{0}".format(f + "/../..")]
71 well_known_proto_files = [f for f in ctx.attr.well_known_protos.files]
74 inputs = protos + includes + well_known_proto_files,
77 executable = ctx.executable._protoc,
78 arguments = arguments,
81 return struct(files=depset(out_files))
85 "srcs": attr.label_list(
88 providers = ["proto"],
92 providers = ["files_to_run"],
95 "flags": attr.string_list(
99 "well_known_protos" : attr.label(
102 "generate_mocks" : attr.bool(
106 "_protoc": attr.label(
107 default = Label("//external:protocol_compiler"),
112 # We generate .h files, so we need to output to genfiles.
113 output_to_genfiles = True,
114 implementation = generate_cc_impl,
117 def generate_cc(well_known_protos, **kwargs):
118 if well_known_protos:
119 _generate_cc(well_known_protos="@com_google_protobuf//:well_known_protos", **kwargs)
121 _generate_cc(**kwargs)