tree: a1e73c6b93e36a7cd6d53a23967729988d6d2530
  1. .bazelci/
  2. android/
  3. closure/
  4. cpp/
  5. csharp/
  6. d/
  7. example/
  8. github.com/
  9. go/
  10. internal/
  11. java/
  12. nodejs/
  13. objc/
  14. php/
  15. protobuf/
  16. python/
  17. ruby/
  18. rust/
  19. scala/
  20. swift/
  21. test_workspaces/
  22. tools/
  23. .bazelignore
  24. .bazelrc
  25. .gitignore
  26. .pre-commit-config.yaml
  27. aspect.bzl
  28. BUILD.bazel
  29. deps.bzl
  30. LICENSE
  31. Makefile
  32. plugin.bzl
  33. README.md
  34. WORKSPACE
README.md

Protobuf and gRPC rules for Bazel

Bazel rules for building Protocol Buffers and gRPC :rocket:

Build Status

Contents:

Overview

These rules provide Protocol Buffers (Protobuf) and gRPC rules for a range of languages and services.

Each supported language ({lang} below) is generally split into four rule flavours:

  • {lang}_proto_compile: Provides generated files from the Protobuf protoc plugin for the language. e.g for C++ this provides the generated *.pb.cc and *.pb.h files.

  • {lang}_proto_library: Provides a language-specific library from the generated Protobuf protoc plugin outputs, along with necessary dependencies. e.g for C++ this provides a Bazel native cpp_library created from the generated *.pb.cc and *pb.h files, with the Protobuf library linked. For languages that do not have a ‘library’ concept, this rule may not exist.

  • {lang}_grpc_compile: Provides generated files from both the Protobuf and gRPC protoc plugins for the language. e.g for C++ this provides the generated *.pb.cc, *.grpc.pb.cc, *.pb.h and *.grpc.pb.h files.

  • {lang}_proto_library: Provides a language-specific library from the generated Protobuf and gRPC protoc plugins outputs, along with necessary dependencies. e.g for C++ this provides a Bazel native cpp_library created from the generated *.pb.cc, *.grpc.pb.cc, *.pb.h and *.grpc.pb.h files, with the Protobuf and gRPC libraries linked. For languages that do not have a ‘library’ concept, this rule may not exist.

Therefore, if you are solely interested in the generated source code artifacts, use the {lang}_{proto|grpc}_compile rules. Otherwise, if you want a ready-to-go library, use the {lang}_{proto|grpc}_library rules.

These rules are derived from the excellent stackb/rules_proto and add aspect-based compilation to all languages, allowing for all proto_library options to be expressed in user code.

Installation

Add rules_proto your WORKSPACE file:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "rules_proto_grpc",
    urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/archive/587162914bcce77abffd4146a8f2834b220abee9.tar.gz"],
    sha256 = "395408a3dc9c3db2b5c200b8722a13a60898c861633b99e6e250186adffd1370",
    strip_prefix = "rules_proto_grpc-587162914bcce77abffd4146a8f2834b220abee9",
)

Important: Follow instructions in the language-specific README.md for additional workspace dependencies that may be required.

Rules

StatusLanguageRuleDescription
Build StatusAndroidandroid_proto_compileGenerates an Android protobuf .jar artifact (example)
Build StatusAndroidandroid_grpc_compileGenerates Android protobuf+gRPC .jar artifacts (example)
Build StatusAndroidandroid_proto_libraryGenerates an Android protobuf library using android_library from rules_android (example)
Build StatusAndroidandroid_grpc_libraryGenerates Android protobuf+gRPC library using android_library from rules_android (example)
Build StatusClosureclosure_proto_compileGenerates Closure protobuf .js files (example)
Build StatusClosureclosure_proto_libraryGenerates a Closure library with compiled protobuf .js files using closure_js_library from rules_closure (example)
Build StatusC++cpp_proto_compileGenerates C++ protobuf .h & .cc artifacts (example)
Build StatusC++cpp_grpc_compileGenerates C++ protobuf+gRPC .h & .cc artifacts (example)
Build StatusC++cpp_proto_libraryGenerates a C++ protobuf library using cc_library, with dependencies linked (example)
Build StatusC++cpp_grpc_libraryGenerates a C++ protobuf+gRPC library using cc_library, with dependencies linked (example)
Build StatusC#csharp_proto_compileGenerates C# protobuf .cs artifacts (example)
Build StatusC#csharp_grpc_compileGenerates C# protobuf+gRPC .cs artifacts (example)
-C#csharp_proto_libraryGenerates a C# protobuf library using core_library from rules_dotnet (example)
-C#csharp_grpc_libraryGenerates a C# protobuf+gRPC library using core_library from rules_dotnet (example)
Build StatusDd_proto_compileGenerates D protobuf .d artifacts (example)
Build StatusDd_proto_libraryGenerates a D protobuf library using d_library from rules_d (example)
Build StatusGogo_proto_compileGenerates Go protobuf .go artifacts (example)
Build StatusGogo_grpc_compileGenerates Go protobuf+gRPC .go artifacts (example)
Build StatusGogo_proto_libraryGenerates a Go protobuf library using go_library from rules_go (example)
Build StatusGogo_grpc_libraryGenerates a Go protobuf+gRPC library using go_library from rules_go (example)
Build StatusJavajava_proto_compileGenerates a Java protobuf srcjar artifact (example)
Build StatusJavajava_grpc_compileGenerates a Java protobuf+gRPC srcjar artifact (example)
Build StatusJavajava_proto_libraryGenerates a Java protobuf library using java_library (example)
Build StatusJavajava_grpc_libraryGenerates a Java protobuf+gRPC library using java_library (example)
Build StatusNode.jsnodejs_proto_compileGenerates Node.js protobuf .js artifacts (example)
Build StatusNode.jsnodejs_grpc_compileGenerates Node.js protobuf+gRPC .js artifacts (example)
Build StatusObjective-Cobjc_proto_compileGenerates Objective-C protobuf .m & .h artifacts (example)
Build StatusObjective-Cobjc_grpc_compileGenerates Objective-C protobuf+gRPC .m & .h artifacts (example)
Build StatusObjective-Cobjc_proto_libraryGenerates an Objective-C protobuf library using objc_library (example)
Build StatusPHPphp_proto_compileGenerates PHP protobuf .php artifacts (example)
Build StatusPHPphp_grpc_compileGenerates PHP protobuf+gRPC .php artifacts (example)
Build StatusPythonpython_proto_compileGenerates Python protobuf .py artifacts (example)
Build StatusPythonpython_grpc_compileGenerates Python protobuf+gRPC .py artifacts (example)
Build StatusPythonpython_proto_libraryGenerates a Python protobuf library using py_library (example)
Build StatusPythonpython_grpc_libraryGenerates a Python protobuf+gRPC library using py_library (example)
Build StatusRubyruby_proto_compileGenerates Ruby protobuf .rb artifacts (example)
Build StatusRubyruby_grpc_compileGenerates Ruby protobuf+gRPC .rb artifacts (example)
Build StatusRubyruby_proto_libraryGenerates a Ruby protobuf library using ruby_library from rules_ruby (example)
Build StatusRubyruby_grpc_libraryGenerates a Ruby protobuf+gRPC library using ruby_library from rules_ruby (example)
Build StatusRustrust_proto_compileGenerates Rust protobuf .rs artifacts (example)
Build StatusRustrust_grpc_compileGenerates Rust protobuf+gRPC .rs artifacts (example)
Build StatusRustrust_proto_libraryGenerates a Rust protobuf library using rust_library from rules_rust (example)
Build StatusRustrust_grpc_libraryGenerates a Rust protobuf+gRPC library using rust_library from rules_rust (example)
Build StatusScalascala_proto_compileGenerates a Scala protobuf .jar artifact (example)
Build StatusScalascala_grpc_compileGenerates Scala protobuf+gRPC .jar artifacts (example)
Build StatusScalascala_proto_libraryGenerates a Scala protobuf library using scala_library from rules_scala (example)
Build StatusScalascala_grpc_libraryGenerates a Scala protobuf+gRPC library using scala_library from rules_scala (example)
-Swiftswift_proto_compileGenerates Swift protobuf .swift artifacts (example)
-Swiftswift_grpc_compileGenerates Swift protobuf+gRPC .swift artifacts (example)
-Swiftswift_proto_libraryGenerates a Swift protobuf library (example)
-Swiftswift_grpc_libraryGenerates a Swift protobuf+gRPC library (example)
Build StatusGo (gogoprotobuf)gogo_proto_compileGenerates gogo protobuf .go artifacts (example)
Build StatusGo (gogoprotobuf)gogo_grpc_compileGenerates gogo protobuf+gRPC .go artifacts (example)
Build StatusGo (gogoprotobuf)gogo_proto_libraryGenerates a Go gogo protobuf library using go_library from rules_go (example)
Build StatusGo (gogoprotobuf)gogo_grpc_libraryGenerates a Go gogo protobuf+gRPC library using go_library from rules_go (example)
Build StatusGo (gogoprotobuf)gogofast_proto_compileGenerates gogofast protobuf .go artifacts (example)
Build StatusGo (gogoprotobuf)gogofast_grpc_compileGenerates gogofast protobuf+gRPC .go artifacts (example)
Build StatusGo (gogoprotobuf)gogofast_proto_libraryGenerates a Go gogofast protobuf library using go_library from rules_go (example)
Build StatusGo (gogoprotobuf)gogofast_grpc_libraryGenerates a Go gogofast protobuf+gRPC library using go_library from rules_go (example)
Build StatusGo (gogoprotobuf)gogofaster_proto_compileGenerates gogofaster protobuf .go artifacts (example)
Build StatusGo (gogoprotobuf)gogofaster_grpc_compileGenerates gogofaster protobuf+gRPC .go artifacts (example)
Build StatusGo (gogoprotobuf)gogofaster_proto_libraryGenerates a Go gogofaster protobuf library using go_library from rules_go (example)
Build StatusGo (gogoprotobuf)gogofaster_grpc_libraryGenerates a Go gogofaster protobuf+gRPC library using go_library from rules_go (example)
Build Statusgrpc-gatewaygateway_grpc_compileGenerates grpc-gateway .go files (example)
Build Statusgrpc-gatewaygateway_swagger_compileGenerates grpc-gateway swagger .json files (example)
Build Statusgrpc-gatewaygateway_grpc_libraryGenerates grpc-gateway library files (example)
Build Statusgrpc.jsgrpcjs_grpc_compileGenerates protobuf closure grpc .js files (example)
Build Statusgrpc.jsgrpcjs_grpc_libraryGenerates protobuf closure library .js files (example)
Build StatusgRPC-Webclosure_grpc_compileGenerates Closure *.js protobuf+gRPC files (example)
Build StatusgRPC-Webcommonjs_grpc_compileGenerates CommonJS *.js protobuf+gRPC files (example)
Build StatusgRPC-Webcommonjs_dts_grpc_compileGenerates commonjs_dts *.js protobuf+gRPC files (example)
Build StatusgRPC-Webts_grpc_compileGenerates CommonJS *.ts protobuf+gRPC files (example)
Build StatusgRPC-Webclosure_grpc_libraryGenerates protobuf closure library *.js files (example)

Example Usage

These steps walk through the steps to go from a raw .proto file to a C++ library:

Step 1: Write a Protocol Buffer file (example: thing.proto):

syntax = "proto3";

package example;

import "google/protobuf/any.proto";

message Thing {
    string name = 1;
    google.protobuf.Any payload = 2;
}

Step 2: Write a BAZEL.build file with a native proto_library rule:

proto_library(
    name = "thing_proto",
    srcs = ["thing.proto"],
    deps = ["@com_google_protobuf//:any_proto"],
)

In this example we have a dependency on a well-known type any.proto, hence the proto_library to proto_library dependency ("@com_google_protobuf//:any_proto")

Step 3: Add a cpp_proto_compile rule (substitute cpp_ for the language of your choice).

NOTE: In this example thing.proto does not include service definitions (gRPC). For protos with services, use the cpp_grpc_compile rule instead.

# BUILD.bazel
load("@rules_proto_grpc//cpp:defs.bzl", "cpp_proto_compile")

cpp_proto_compile(
    name = "cpp_thing_proto",
    deps = [":thing_proto"],
)

But wait, before we can build this, we need to load the dependencies necessary for this rule (from cpp/README.md):

Step 4: Load the workspace macro corresponding to the build rule.

# WORKSPACE
load("@rules_proto_grpc//cpp:deps.bzl", "cpp_deps")

cpp_deps()

We're now ready to build the rule:

Step 5: Build it!

$ bazel build //example/proto:cpp_thing_proto
Target //example/proto:cpp_thing_proto up-to-date:
  bazel-genfiles/example/proto/cpp_thing_proto/example/proto/thing.pb.h
  bazel-genfiles/example/proto/cpp_thing_proto/example/proto/thing.pb.cc

If we were only interested in the generated file artifacts, the cpp_grpc_compile rule would be fine. However, for convenience we‘d rather have the outputs compiled into an *.so file. To do that, let’s change the rule from cpp_proto_compile to cpp_proto_library:

# BUILD.bazel
load("@rules_proto_grpc//cpp:defs.bzl", "cpp_proto_library")

cpp_proto_library(
    name = "cpp_thing_proto",
    deps = [":thing_proto"],
)
$ bazel build //example/proto:cpp_thing_proto
Target //example/proto:cpp_thing_proto up-to-date:
  bazel-bin/example/proto/libcpp_thing_proto.a
  bazel-bin/example/proto/libcpp_thing_proto.so  bazel-genfiles/example/proto/cpp_thing_proto/example/proto/thing.pb.h
  bazel-genfiles/example/proto/cpp_thing_proto/example/proto/thing.pb.cc

This way, we can use //example/proto:cpp_thing_proto as a dependency of any other cc_library or cc_binary rule as per normal.

NOTE: the cpp_proto_library implicitly calls cpp_proto_compile, and we can access that rule by adding _pb at the end of the rule name, like bazel build //example/proto:cpp_thing_proto_pb.

Developers

Code Layout

Each language {lang} has a top-level subdirectory that contains:

  1. {lang}/README.md: Generated documentation for the language rules.

  2. {lang}/deps.bzl: Macro functions that declare repository rule dependencies for that language.

  3. {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.

  4. {lang}/BUILD.bazel: proto_plugin() declarations for the available plugins for the language.

  5. example/{lang}/{rule}/: Generated WORKSPACE and BUILD.bazel demonstrating standalone usage of the rules.

  6. {lang}/example/routeguide/: Example routeguide example implementation, if possible.

The repository root directory contains the base rule defintions:

  • plugin.bzl: A build rule that defines the name, tool binary, and options for a particular proto plugin.

  • aspect.bzl: Contains the implementation of the compilation aspect. This is shared by all rules and is the heart of rules_proto; it calls protoc with a given list of plugins and generates output files.

Additional protoc plugins and their rules are scoped to the github repository name where the plugin resides.

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.md should be placed in tools/rulegen/README.header.md or tools/rulegen/README.footer.md. Changes to generated rules should be put in the source files (example: tools/rulegen/java.go).

How-it-works

Briefly, here's how the rules work:

  1. Using the proto_library graph, an aspect walks through the ProtoInfo providers on the deps attribute to {lang}_{proto|grpc}_compile. This finds all the directly and transitively required proto files., along with their options.

  2. At each node visited by the aspect, protoc is invoked with the relevant plugins and options to generate the desired outputs.

  3. Once the aspect stage is complete, all generated outputs are optionally gathered into a final output tree.

  4. For {lang}_{proto|grpc}_library rules, the generated outputs are then aggregated into a language-specific library. e.g a .so file for C++.

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//:plugin.bzl", "proto_plugin").
  2. Define the rule, giving it a name, options (not mandatory), tool, and outputs.
  3. tool is a label that refers to the binary executable for the plugin itself.
  4. 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.
  5. Create a compilation rule and aspect using the following template:
load("@rules_proto_grpc//:plugin.bzl", "ProtoPluginInfo")
load(
    "@rules_proto_grpc//:aspect.bzl",
    "ProtoLibraryAspectNodeInfo",
    "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,
        deps = attr.label_list(
            mandatory = True,
            providers = [ProtoInfo, ProtoLibraryAspectNodeInfo],
            aspects = [example_compile],
        ),
    ),
)

# Create macro for converting attrs and passing to compile
def example_compile(**kwargs):
    _rule(
        verbose_string = "{}".format(kwargs.get("verbose", 0)),
        merge_directories = True,
        **{k: v for k, v in kwargs.items() if k != "merge_directories"}
    )

License

This project is derived from stackb/rules_proto under the Apache 2.0 license and this project therefore maintains the terms of that license.

Contributing

Contributions welcome; please create Issues or PRs.