Custom Plugins#

Custom plugins are supported by rules_proto_grpc, through the use of the proto_plugin Starlark rule to create a plugin target in a BUILD file and by then creating a rule that uses proto_compile_impl with the new plugin.

To add a new plugin, you can generally follow the pattern seen in the multiple language examples in this repository; simpler languages such as C++ are generally more understandable as examples. In short, the basic idea is:

  1. In a BUILD file, load the proto_plugin rule with load("@rules_proto_grpc//:defs.bzl", "proto_plugin") and use this to define all of the behaviour of your particular protoc plugin using the available attrs (listed in full below). The minimum required specification for a plugin needs a name, tool and one of outputs, out or output_directory. The tool attr is a label that refers to the binary target for the plugin itself and can be select()’ed based on your platform. The choice of output type depends on the sort of files your plugin generates (pick one!):

    • outputs: Provide a list of strings patterns that predicts the pattern of files generated by the plugin. Use this type for plugins that produce one output file per input proto file, such as Python producing a .py file.

    • out: The name of a single output file generated by the plugin. Use this type for plugins that produce a single output file per call to protoc, such as Java producing a .jar file.

    • output_directory: Set to true if your plugin generates files in a non-predictable way, for example if the output paths depend on the service names within the files.

load("@rules_proto_grpc//:defs.bzl", "proto_plugin")

proto_plugin(
    name = "example_plugin",
    outputs = ["{protopath}_example.py"],  # {protopath} gets replaced with relative path to each .proto file
    tool = "//label/of/plugin:binary",  # Point this at your plugin binary target, use select if desired
)
  1. In a .bzl file, create a compilation rule using the below template, substituting the plugin target label created above where indicated. The proto_compile_attrs contains a set of attrs that the proto_compile_impl rule implementation expects.

load("@rules_proto//proto:defs.bzl", "ProtoInfo")
load(
    "@rules_proto_grpc//:defs.bzl",
    "ProtoPluginInfo",
    "proto_compile_attrs",
    "proto_compile_impl",
)

# Create compile rule
example_compile = rule(
    implementation = proto_compile_impl,
    attrs = dict(
        proto_compile_attrs,
        _plugins = attr.label_list(
            providers = [ProtoPluginInfo],
            default = [
                Label("//<LABEL OF YOUR PLUGIN>"),
            ],
            doc = "List of protoc plugins to apply",
        ),
    ),
    toolchains = [str(Label("@rules_proto_grpc//protobuf:toolchain_type"))],
)

API Reference#

proto_plugin#

Attributes for proto_plugin#

Name

Type

Mandatory

Default

Description

tool

label

true

The label of plugin binary target. Can be the output of select() to support multiple platforms. If absent, it is assumed the plugin is built-in to protoc itself and builtin_plugin_name will be used if available, otherwise the plugin name

protoc_plugin_name

string

false

""

The name used for the plugin binary on the protoc command line. Useful for targeting built-in plugins. Uses the plugin name when not set

options

string_list

false

[]

A list of options to pass to the compiler for this plugin

outputs

string_list

false

[]

Templates for output filenames generated on a per-proto basis, such as ‘{basename}_pb2.py’. The {basename} template string will be replaced with the file basename and {protopath} with be replaced with the relative path to the .proto file after prefix mangling. If no template variables are present, the string is assumed to be a suffix of the file basename

out

string

false

Template for the output filename generated on a per-plugin basis; to be used in the value for –NAME-out=OUT. The {name} template variable will be replaced with the target name

output_directory

bool

false

False

Flag that indicates that the plugin should only output a directory. Used for plugins that have no direct mapping from source file name to output name. Cannot be used in conjunction with outputs or out

extra_protoc_args

string_list

false

[]

A list of extra command line arguments to pass directly to protoc, not as plugin options

env

string_dict

false

{}

A dictionary of key-value environment variables to use when invoking protoc for this plugin. Must be empty if use_built_in_shell_environment is true

exclusions

string_list

false

[]

Exclusion filters to apply when generating outputs with this plugin. Used to prevent generating files that are included in the protobuf library, for example. Can exclude either by proto name prefix or by proto folder prefix

data

label_list

false

[]

Additional files required for running the plugin

use_built_in_shell_environment

bool

false

True

Flag to indicate whether the tool should use the built in shell environment

separate_options_flag

bool

false

False

Flag to indicate if plugin options should be sent to protoc via the separate –{lang}_opts argument

empty_template

label

false

Template file to use to fill missing outputs when the fixer is required. If not provided, the fixer is not run

quirks

string_list

false

[]

List of quirks that toggle behaviours in compilation. The QUIRK_OUT_PASS_ROOT quirk enables passing the output directory to a plugin that outputs only a single file. The QUIRK_DIRECT_MODE quirk disables use of descriptors from proto_library and passes the files directly to protoc