"""Utility functions for generating protobuf code.""" _PROTO_EXTENSION = ".proto" def well_known_proto_libs(): return [ "@com_google_protobuf//:any_proto", "@com_google_protobuf//:api_proto", "@com_google_protobuf//:compiler_plugin_proto", "@com_google_protobuf//:descriptor_proto", "@com_google_protobuf//:duration_proto", "@com_google_protobuf//:empty_proto", "@com_google_protobuf//:field_mask_proto", "@com_google_protobuf//:source_context_proto", "@com_google_protobuf//:struct_proto", "@com_google_protobuf//:timestamp_proto", "@com_google_protobuf//:type_proto", "@com_google_protobuf//:wrappers_proto", ] def get_proto_root(workspace_root): """Gets the root protobuf directory. Args: workspace_root: context.label.workspace_root Returns: The directory relative to which generated include paths should be. """ if workspace_root: return "/{}".format(workspace_root) else: return "" def _strip_proto_extension(proto_filename): if not proto_filename.endswith(_PROTO_EXTENSION): fail('"{}" does not end with "{}"'.format( proto_filename, _PROTO_EXTENSION, )) return proto_filename[:-len(_PROTO_EXTENSION)] def proto_path_to_generated_filename(proto_path, fmt_str): """Calculates the name of a generated file for a protobuf path. For example, "examples/protos/helloworld.proto" might map to "helloworld.pb.h". Args: proto_path: The path to the .proto file. fmt_str: A format string used to calculate the generated filename. For example, "{}.pb.h" might be used to calculate a C++ header filename. Returns: The generated filename. """ return fmt_str.format(_strip_proto_extension(proto_path)) def _get_include_directory(include): directory = include.path prefix_len = 0 if not include.is_source and directory.startswith(include.root.path): prefix_len = len(include.root.path) + 1 if directory.startswith("external", prefix_len): external_separator = directory.find("/", prefix_len) repository_separator = directory.find("/", external_separator + 1) return directory[:repository_separator] else: return include.root.path if include.root.path else "." def get_include_protoc_args(includes): """Returns protoc args that imports protos relative to their import root. Args: includes: A list of included proto files. Returns: A list of arguments to be passed to protoc. For example, ["--proto_path=."]. """ return [ "--proto_path={}".format(_get_include_directory(include)) for include in includes ] def get_plugin_args(plugin, flags, dir_out, generate_mocks): """Returns arguments configuring protoc to use a plugin for a language. Args: plugin: An executable file to run as the protoc plugin. flags: The plugin flags to be passed to protoc. dir_out: The output directory for the plugin. generate_mocks: A bool indicating whether to generate mocks. Returns: A list of protoc arguments configuring the plugin. """ augmented_flags = list(flags) if generate_mocks: augmented_flags.append("generate_mock_code=true") return [ "--plugin=protoc-gen-PLUGIN=" + plugin.path, "--PLUGIN_out=" + ",".join(augmented_flags) + ":" + dir_out, ]