blob: 41bc0290316104359c61302172fe18a4b9b4dcab [file]
:author: rules_proto_grpc
:description: Changelog for the rules_proto_grpc Bazel rules
:keywords: Bazel, Protobuf, gRPC, Protocol Buffers, Rules, Build, Starlark, Developers
Developers
==========
Contributions are very welcome on this project. Issues should be raised for bugs and feature
requests. Pull requests should be targeted at the master branch and will run against CI.
.. note:: The rules in the repo are generated by the code in tools/rulegen and the output rules
should therefore not be edited directly. However, if you are not comfortable editing this code,
please submit a PR with just the output files edited and we'll help update the generator to get
the desired result.
Code Layout
-----------
Each language ``{lang}`` has a top-level subdirectory that contains:
1. ``docs/{lang}.rst``: Generated documentation for the language rules
1. ``{lang}/repositories.bzl``: Macro functions that declare repository rule dependencies for that language
2. ``{lang}/{rule}.bzl``: Rule implementations of the form ``{lang}_{kind}_{type}``, where ``kind`` is one of ``proto|grpc`` and
``type`` is one of ``compile|library``
3. ``{lang}/BUILD.bazel``: ``proto_plugin()`` declarations for the available plugins for the language
4. ``example/{lang}/{rule}/``: Generated ``WORKSPACE`` and ``BUILD.bazel`` demonstrating standalone usage of the rules
5. ``{lang}/example/routeguide/``: Example routeguide example implementation, if possible
Rule Generation
---------------
To help maintain consistency of the rule implementations and documentation, all of the rule implementations are
generated by the tool ``//tools/rulegen``. Changes in the main ``README.rst`` should be placed in
``tools/rulegen/README.header.rst`` or ``tools/rulegen/README.footer.rst```. Changes to generated rules should be put in the
source files (example: ``tools/rulegen/java.go``).
Developing Custom Plugins
-------------------------
Generally, follow the pattern seen in the multiple language examples in this
repository. The basic idea is:
1. Load the plugin rule: ``load("@rules_proto_grpc//:defs.bzl", "proto_plugin")``
2. Define the rule, giving it a ``name``, ``options`` (not mandatory), ``tool`` and ``outputs``. ``tool`` is a label that refers
to the binary executable for the plugin itself
3. Choose your output type (pick one!):
- ``outputs``: A list of strings patterns that predicts the pattern of files generated by the plugin. For plugins that
produce one output file per input proto file
- ``out``: The name of a single output file generated by the plugin
- ``output_directory``: Set to true if your plugin generates files in a non-predictable way. e.g. if the output paths
depend on the service names within the files
4. Create a compilation rule and aspect using the following template:
.. code-block:: python
load("@rules_proto//proto:defs.bzl", "ProtoInfo")
load(
"@rules_proto_grpc//:defs.bzl",
"ProtoLibraryAspectNodeInfo",
"ProtoPluginInfo",
"proto_compile_aspect_attrs",
"proto_compile_aspect_impl",
"proto_compile_attrs",
"proto_compile_impl",
)
# Create aspect
example_aspect = aspect(
implementation = proto_compile_aspect_impl,
provides = [ProtoLibraryAspectNodeInfo],
attr_aspects = ["deps"],
attrs = dict(
proto_compile_aspect_attrs,
_plugins = attr.label_list(
doc = "List of protoc plugins to apply",
providers = [ProtoPluginInfo],
default = [
Label("//<LABEL OF YOUR PLUGIN>"),
],
),
_prefix = attr.string(
doc = "String used to disambiguate aspects when generating outputs",
default = "example_aspect",
),
),
toolchains = ["@rules_proto_grpc//protobuf:toolchain_type"],
)
# Create compile rule to apply aspect
_rule = rule(
implementation = proto_compile_impl,
attrs = dict(
proto_compile_attrs,
protos = attr.label_list(
mandatory = False, # TODO: set to true in 4.0.0 when deps removed below
providers = [ProtoInfo],
doc = "List of labels that provide the ProtoInfo provider (such as proto_library from rules_proto)",
),
deps = attr.label_list(
mandatory = False,
providers = [ProtoInfo, ProtoLibraryAspectNodeInfo],
aspects = [example_aspect],
doc = "DEPRECATED: Use protos attr",
),
_plugins = attr.label_list(
providers = [ProtoPluginInfo],
default = [
Label("//<LABEL OF YOUR PLUGIN>"),
],
doc = "List of protoc plugins to apply",
),
),
toolchains = [str(Label("//protobuf:toolchain_type"))],
)
# Create macro for converting attrs and passing to compile
def example_compile(**kwargs):
_rule(
verbose_string = "{}".format(kwargs.get("verbose", 0)),
**kwargs
)