Fix github archive stripPrefix ref
2 files changed
tree: b800c9cb4f81d016bfe570c23c970b39ee210633
  1. android/
  2. closure/
  3. cpp/
  4. csharp/
  5. dart/
  6. example/
  7. github.com/
  8. go/
  9. java/
  10. node/
  11. objc/
  12. php/
  13. python/
  14. ruby/
  15. rust/
  16. scala/
  17. swift/
  18. tools/
  19. .bazelrc
  20. .gitignore
  21. .pre-commit-config.yaml
  22. BUILD.bazel
  23. compile.bzl
  24. deps.bzl
  25. LICENSE
  26. Makefile
  27. Makefile.examples
  28. plugin.bzl
  29. README.md
  30. WORKSPACE
README.md

rules_proto

Bazel skylark rules for building protocol buffers +/- gRPC :sparkles:.

These rules are the successor to https://github.com/pubref/rules_protobuf and are in a pre-release status. The primary goals are:

  1. Interoperate with the native proto_library rules and other proto support in the bazel ecosystem as much as possible.
  2. Provide a proto_plugin rule to support custom protoc plugins.
  3. Minimal dependency loading. Proto rules should not pull in more dependencies than they absolutely need.

NOTE: in general, try to use the native proto library rules when possible to minimize external dependencies in your project. Add rules_proto when you have more complex proto requirements such as when dealing with multiple output languages, gRPC, unsupported (native) language support, or custom proto plugins.

Installation

Add rules_proto your WORKSPACE:

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

http_archive(
    name = "build_stack_rules_proto",
    urls = ["https://github.com/stackb/rules_proto/archive/d86ca6bc56b1589677ec59abfa0bed784d6b7767.tar.gz"],
    sha256 = "36f11f56f6eb48a81eb6850f4fb6c3b4680e3fc2d3ceb9240430e28d32c47009",
    strip_prefix = "rules_proto-d86ca6bc56b1589677ec59abfa0bed784d6b7767",
)

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

Usage

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 hance the proto_library to proto_library dependency.

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("@build_stack_rules_proto//cpp:cpp_proto_compile.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("@build_stack_rules_proto//cpp:deps.bzl", "cpp_proto_compile")

cpp_proto_compile()

Note that the workspace macro has the same name of the build rule. Refer to the cpp/deps.bzl for details on what other dependencies are loaded.

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 for 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:

# WORKSPACE
load("@build_stack_rules_proto//cpp:deps.bzl", "cpp_proto_library")

cpp_proto_library()
# BUILD.bazel
load("@build_stack_rules_proto//cpp:cpp_proto_library.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.

Summary

  • There are generally four rule flavors for any language {lang}: {lang}_proto_compile, {lang}_proto_library, {lang}_grpc_compile, and {lang}_grpc_library.

  • If you are solely interested in the source code artifacts, use the {lang}_{proto|grpc}_compile rule.

  • If your proto file has services, use the {lang}_{grpc}_{compile|library} rule instead.

  • Load any external dependencies needed for the rule via the load("@build_stack_rules_proto//{lang}:deps.bzl", "{lang}_{proto|grpc}_{compile|library}").

Rules

LangRuleDescription
androidandroid_proto_compileGenerates android protobuf artifacts (example)
androidandroid_grpc_compileGenerates android protobuf+gRPC artifacts (example)
androidandroid_proto_libraryGenerates android protobuf library (example)
androidandroid_grpc_libraryGenerates android protobuf+gRPC library (example)
closureclosure_proto_compileGenerates closure *.js protobuf+gRPC files (example)
closureclosure_proto_libraryGenerates a closure_library with compiled protobuf *.js files (example)
cppcpp_proto_compileGenerates .h,.cc protobuf artifacts (example)
cppcpp_grpc_compileGenerates .h,.cc protobuf+gRPC artifacts (example)
cppcpp_proto_libraryGenerates .h,.cc protobuf library (example)
cppcpp_grpc_libraryGenerates .h,.cc protobuf+gRPC library (example)
csharpcsharp_proto_compileGenerates csharp protobuf artifacts (example)
csharpcsharp_grpc_compileGenerates csharp protobuf+gRPC artifacts (example)
csharpcsharp_proto_libraryGenerates csharp protobuf library (example)
csharpcsharp_grpc_libraryGenerates csharp protobuf+gRPC library (example)
dartdart_proto_compileGenerates dart protobuf artifacts (example)
dartdart_grpc_compileGenerates dart protobuf+gRPC artifacts (example)
dartdart_proto_libraryGenerates dart protobuf library (example)
dartdart_grpc_libraryGenerates dart protobuf+gRPC library (example)
gogo_proto_compileGenerates *.go protobuf artifacts (example)
gogo_grpc_compileGenerates *.go protobuf+gRPC artifacts (example)
gogo_proto_libraryGenerates *.go protobuf library (example)
gogo_grpc_libraryGenerates *.go protobuf+gRPC library (example)
javajava_proto_compileGenerates a srcjar with protobuf *.java files (example)
javajava_grpc_compileGenerates a srcjar with protobuf+gRPC *.java files (example)
javajava_proto_libraryGenerates a jar with compiled protobuf *.class files (example)
javajava_grpc_libraryGenerates a jar with compiled protobuf+gRPC *.class files (example)
nodenode_proto_compileGenerates node *.js protobuf artifacts (example)
nodenode_grpc_compileGenerates node *.js protobuf+gRPC artifacts (example)
nodenode_proto_libraryGenerates node *.js protobuf library (example)
nodenode_grpc_libraryGenerates node *.js protobuf+gRPC library (example)
objcobjc_proto_compileGenerates objc protobuf artifacts (example)
objcobjc_grpc_compileGenerates objc protobuf+gRPC artifacts (example)
phpphp_proto_compileGenerates php protobuf artifacts (example)
phpphp_grpc_compileGenerates php protobuf+gRPC artifacts (example)
pythonpython_proto_compileGenerates *.py protobuf artifacts (example)
pythonpython_grpc_compileGenerates *.py protobuf+gRPC artifacts (example)
pythonpython_proto_libraryGenerates *.py protobuf library (example)
pythonpython_grpc_libraryGenerates *.py protobuf+gRPC library (example)
rubyruby_proto_compileGenerates *.ruby protobuf artifacts (example)
rubyruby_grpc_compileGenerates *.ruby protobuf+gRPC artifacts (example)
rubyruby_proto_libraryGenerates *.rb protobuf library (example)
rubyruby_grpc_libraryGenerates *.rb protobuf+gRPC library (example)
rustrust_proto_compileGenerates rust protobuf artifacts (example)
rustrust_grpc_compileGenerates rust protobuf+gRPC artifacts (example)
rustrust_proto_libraryGenerates rust protobuf library (example)
rustrust_grpc_libraryGenerates rust protobuf+gRPC library (example)
scalascala_proto_compileGenerates *.scala protobuf artifacts (example)
scalascala_grpc_compileGenerates *.scala protobuf+gRPC artifacts (example)
scalascala_proto_libraryGenerates *.py protobuf library (example)
scalascala_grpc_libraryGenerates *.py protobuf+gRPC library (example)
swiftswift_proto_compileGenerates swift protobuf artifacts (example)
swiftswift_grpc_compileGenerates swift protobuf+gRPC artifacts (example)
swiftswift_proto_libraryGenerates swift protobuf library (example)
swiftswift_grpc_libraryGenerates swift protobuf+gRPC library (example)
gogogogo_proto_compileGenerates gogo protobuf artifacts (example)
gogogogo_grpc_compileGenerates gogo protobuf+gRPC artifacts (example)
gogogogo_proto_libraryGenerates gogo protobuf library (example)
gogogogo_grpc_libraryGenerates gogo protobuf+gRPC library (example)
gogogogofast_proto_compileGenerates gogofast protobuf artifacts (example)
gogogogofast_grpc_compileGenerates gogofast protobuf+gRPC artifacts (example)
gogogogofast_proto_libraryGenerates gogofast protobuf library (example)
gogogogofast_grpc_libraryGenerates gogofast protobuf+gRPC library (example)
gogogogofaster_proto_compileGenerates gogofaster protobuf artifacts (example)
gogogogofaster_grpc_compileGenerates gogofaster protobuf+gRPC artifacts (example)
gogogogofaster_proto_libraryGenerates gogofaster protobuf library (example)
gogogogofaster_grpc_libraryGenerates gogofaster protobuf+gRPC library (example)
grpc-gatewaygateway_grpc_compileGenerates grpc-gateway *.go files (example)
grpc-gatewaygateway_swagger_compileGenerates grpc-gateway swagger *.json files (example)
grpc-gatewaygateway_grpc_libraryGenerates grpc-gateway library files (example)
grpc.jsclosure_grpc_compileGenerates protobuf closure grpc *.js files (example)
grpc.jsclosure_grpc_libraryGenerates protobuf closure library *.js files (example)
grpc-webclosure_grpc_compileGenerates a closure *.js protobuf+gRPC files (example)
grpc-webcommonjs_grpc_compileGenerates a commonjs *.js protobuf+gRPC files (example)
grpc-webcommonjs_dts_grpc_compileGenerates a commonjs_dts *.js protobuf+gRPC files (example)
grpc-webts_grpc_compileGenerates a commonjs *.ts protobuf+gRPC files (example)
grpc-webclosure_grpc_libraryGenerates protobuf closure library *.js files (example)
ts-protoc-gents_proto_compileGenerates typescript protobuf t.ds files (example)

Transitivity

Briefly, here's how the rules work:

  1. Using the proto_library graph, collect all the *.proto files directly and transitively required for the protobuf compilation.

  2. Copy the *.proto files into a “staging” area in the bazel sandbox such that a single -I. will satisfy all imports.

  3. Call protoc OPTIONS FILELIST and generate outputs.

The concept of transitivity (as defined here) affects which files in the set *.proto files are named in the FILELIST. If we only list direct dependencies then we say transitive = False. If all files are named, then transitive = True. The set of files that can be included or excluded from the FILELIST are called transitivity rules, which can be defined on a per-rule or per-plugin basis. Please grep the codebase for examples of their usage.

TODO: explain this better and provide examples.

Code Layout

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

  1. {lang}/README.md: generated documentation for the rule(s).

  2. {lang}/deps.bzl: contains macro functions that declare repository rule dependencies for that language. The name of the macro corresponds to the name of the build rule you'd like to use.

  3. {lang}/{rule}.bzl: rule implementation(s) of the form {lang}_{kind}_{type}, where kind is one of proto|grpc and type is one of compile|library.

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

  5. {lang}/example/{rule}/: contains a generated WORKSPACE and BUILD.bazel demonstrating standalone usage.

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

The 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.

  • compile.bzl: A build rule that contains the proto_compile rule. This rule 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. For example, there are 3 grpc-web implementations in this repo: `github.com/improbable-eng/grpc-web, github.com/grpc/grpc-web, and github.com/stackb/grpc.js.

Developing Custom Plugins

Follow the pattern seen in the multiple examples in this repository. The basic idea is:

  1. Load the plugin rule: load("@build_stack_rules_proto//: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. outputs is a list of strings that predicts the pattern of files generated by the plugin. Specifying outputs is the only attribute that requires much mental effort. [TODO: article here with example writing a custom plugin].

Contributing

Contributions welcome; please create Issues or GitHub pull requests.