Imported Upstream version 1.21.0
[platform/upstream/grpc.git] / bazel / protobuf.bzl
1 """Utility functions for generating protobuf code."""
2
3 _PROTO_EXTENSION = ".proto"
4
5 def well_known_proto_libs():
6     return [
7         "@com_google_protobuf//:any_proto",
8         "@com_google_protobuf//:api_proto",
9         "@com_google_protobuf//:compiler_plugin_proto",
10         "@com_google_protobuf//:descriptor_proto",
11         "@com_google_protobuf//:duration_proto",
12         "@com_google_protobuf//:empty_proto",
13         "@com_google_protobuf//:field_mask_proto",
14         "@com_google_protobuf//:source_context_proto",
15         "@com_google_protobuf//:struct_proto",
16         "@com_google_protobuf//:timestamp_proto",
17         "@com_google_protobuf//:type_proto",
18         "@com_google_protobuf//:wrappers_proto",
19     ]
20
21 def get_proto_root(workspace_root):
22     """Gets the root protobuf directory.
23
24     Args:
25       workspace_root: context.label.workspace_root
26
27     Returns:
28       The directory relative to which generated include paths should be.
29     """
30     if workspace_root:
31         return "/{}".format(workspace_root)
32     else:
33         return ""
34
35 def _strip_proto_extension(proto_filename):
36     if not proto_filename.endswith(_PROTO_EXTENSION):
37         fail('"{}" does not end with "{}"'.format(
38             proto_filename,
39             _PROTO_EXTENSION,
40         ))
41     return proto_filename[:-len(_PROTO_EXTENSION)]
42
43 def proto_path_to_generated_filename(proto_path, fmt_str):
44     """Calculates the name of a generated file for a protobuf path.
45
46     For example, "examples/protos/helloworld.proto" might map to
47       "helloworld.pb.h".
48
49     Args:
50       proto_path: The path to the .proto file.
51       fmt_str: A format string used to calculate the generated filename. For
52         example, "{}.pb.h" might be used to calculate a C++ header filename.
53
54     Returns:
55       The generated filename.
56     """
57     return fmt_str.format(_strip_proto_extension(proto_path))
58
59 def _get_include_directory(include):
60     directory = include.path
61     prefix_len = 0
62     if not include.is_source and directory.startswith(include.root.path):
63         prefix_len = len(include.root.path) + 1
64
65     if directory.startswith("external", prefix_len):
66         external_separator = directory.find("/", prefix_len)
67         repository_separator = directory.find("/", external_separator + 1)
68         return directory[:repository_separator]
69     else:
70         return include.root.path if include.root.path else "."
71
72 def get_include_protoc_args(includes):
73     """Returns protoc args that imports protos relative to their import root.
74
75     Args:
76       includes: A list of included proto files.
77
78     Returns:
79       A list of arguments to be passed to protoc. For example, ["--proto_path=."].
80     """
81     return [
82         "--proto_path={}".format(_get_include_directory(include))
83         for include in includes
84     ]
85
86 def get_plugin_args(plugin, flags, dir_out, generate_mocks):
87     """Returns arguments configuring protoc to use a plugin for a language.
88
89     Args:
90       plugin: An executable file to run as the protoc plugin.
91       flags: The plugin flags to be passed to protoc.
92       dir_out: The output directory for the plugin.
93       generate_mocks: A bool indicating whether to generate mocks.
94
95     Returns:
96       A list of protoc arguments configuring the plugin.
97     """
98     augmented_flags = list(flags)
99     if generate_mocks:
100         augmented_flags.append("generate_mock_code=true")
101     return [
102         "--plugin=protoc-gen-PLUGIN=" + plugin.path,
103         "--PLUGIN_out=" + ",".join(augmented_flags) + ":" + dir_out,
104     ]