diff options
Diffstat (limited to 'proto/core.rst')
-rw-r--r-- | proto/core.rst | 500 |
1 files changed, 500 insertions, 0 deletions
diff --git a/proto/core.rst b/proto/core.rst new file mode 100644 index 00000000..9c765729 --- /dev/null +++ b/proto/core.rst @@ -0,0 +1,500 @@ +Go Protocol buffers +=================== + +.. _proto_library: https://docs.bazel.build/versions/master/be/protocol-buffer.html#proto_library +.. _default Go plugin: https://github.com/golang/protobuf +.. _common plugins: #predefined-plugins +.. _Go providers: /go/providers.rst +.. _GoLibrary: /go/providers.rst#golibrary +.. _GoSource: /go/providers.rst#gosource +.. _GoArchive: /go/providers.rst#goarchive +.. _Gazelle: https://github.com/bazelbuild/bazel-gazelle +.. _Make variable substitution: https://docs.bazel.build/versions/master/be/make-variables.html#make-var-substitution +.. _Bourne shell tokenization: https://docs.bazel.build/versions/master/be/common-definitions.html#sh-tokenization +.. _gogoprotobuf: https://github.com/gogo/protobuf +.. _compiler.bzl: compiler.bzl + +.. role:: param(kbd) +.. role:: type(emphasis) +.. role:: value(code) +.. |mandatory| replace:: **mandatory value** + +rules_go provides rules that generate Go packages from .proto files. These +packages can be imported like regular Go libraries. + +.. contents:: :depth: 2 + +----- + +Overview +-------- + +Protocol buffers are built with the three rules below. ``go_proto_library`` and +``go_proto_compiler`` may be loaded from ``@io_bazel_rules_go//proto:def.bzl``. + +* `proto_library`_: This is a Bazel built-in rule. It lists a set of .proto + files in its ``srcs`` attribute and lists other ``proto_library`` dependencies + in its ``deps`` attribute. ``proto_library`` rules may be referenced by + language-specific code generation rules like ``java_proto_library`` and + ``go_proto_library``. +* `go_proto_library`_: Generates Go code from .proto files using one or more + proto plugins, then builds that code into a Go library. ``go_proto_library`` + references ``proto_library`` sources via the ``proto`` attribute. They may + reference other ``go_proto_library`` and ``go_library`` dependencies via the + ``deps`` attributes. ``go_proto_library`` rules can be depended on or + embedded directly by ``go_library`` and ``go_binary``. +* `go_proto_compiler`_: Defines a protoc plugin. By default, + ``go_proto_library`` generates Go code with the `default Go plugin`_, but + other plugins can be used by setting the ``compilers`` attribute. A few + `common plugins`_ are provided in ``@io_bazel_rules_go//proto``. + +The ``go_proto_compiler`` rule produces a `GoProtoCompiler`_ provider. If you +need a greater degree of customization (for example, if you don't want to use +protoc), you can implement a compatible rule that returns one of these. + +The ``go_proto_library`` rule produces the normal set of `Go providers`_. This +makes it compatible with other Go rules for use in ``deps`` and ``embed`` +attributes. + +Avoiding conflicts +------------------ + +When linking programs that depend on protos, care must be taken to ensure that +the same proto isn't registered by more than one package. This may happen if +you depend on a ``go_proto_library`` and a vendored ``go_library`` generated +from the same .proto files. You may see compile-time, link-time, or run-time +errors as a result of this. + +There are two main ways to avoid conflicts. + +Option 1: Use go_proto_library exclusively +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can avoid proto conflicts by using ``go_proto_library`` to generate code +at build time and avoiding ``go_library`` rules based on pre-generated .pb.go +files. + +Gazelle generates rules in this mode by default. When .proto files are present, +it will generate ``go_proto_library`` rules and ``go_library`` rules that embed +them (which are safe to use). Gazelle will automatically exclude .pb.go files +that correspond to .proto files. If you have .proto files belonging to multiple +packages in the same directory, add the following directives to your +root build file: + +.. code:: bzl + + # gazelle:proto package + # gazelle:proto_group go_package + +rules_go provides ``go_proto_library`` rules for commonly used proto libraries. +The Well Known Types can be found in the ``@io_bazel_rules_go//proto/wkt`` +package. There are implicit dependencies of ``go_proto_library`` rules +that use the default compiler, so they don't need to be written +explicitly in ``deps``. You can also find rules for Google APIs and gRPC in +``@go_googleapis//``. You can list these rules with the commands: + +.. code:: bash + + $ bazel query 'kind(go_proto_library, @io_bazel_rules_go//proto/wkt:all)' + $ bazel query 'kind(go_proto_library, @go_googleapis//...)' + +Some commonly used Go libraries, such as ``github.com/golang/protobuf/ptypes``, +depend on the Well Known Types. In order to avoid conflicts when using these +libraries, separate versions of these libraries are provided with +``go_proto_library`` dependencies. Gazelle resolves imports of these libraries +automatically. For example, it will resolve ``ptypes`` as +``@com_github_golang_protobuf//ptypes:go_default_library_gen``. + +Option 2: Use pre-generated .pb.go files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can also avoid conflicts by generating .pb.go files ahead of time and using +those exclusively instead of using ``go_proto_library``. This may be a better +option for established Go projects that also need to build with ``go build``. + +Gazelle can generate rules for projects built in this mode. Add the following +comment to your root build file: + +.. code:: bzl + + # gazelle:proto disable_global + +This prevents Gazelle from generating ``go_proto_library`` rules. .pb.go files +won't be excluded, and all special cases for imports (such as ``ptypes``) are +disabled. + +If you have ``go_repository`` rules in your ``WORKSPACE`` file that may +have protos, you'll also need to add +``build_file_proto_mode = "disable_global"`` to those as well. + +.. code:: bzl + + go_repository( + name = "com_example_some_project", + importpath = "example.com/some/project", + tag = "v0.1.2", + build_file_proto_mode = "disable_global", + ) + +A note on vendored .proto files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, Bazel assumes imports in .proto files are relative to a repository +root directory. This means, for example, if you import ``"foo/bar/baz.proto"``, +that file must be in the directory ``foo/bar``, not +``vendor/example.com/repo/foo/bar``. + +To deal with this, use the `strip_import_prefix` option in the proto_library_ +for the vendored file. + +API +--- + +go_proto_library +~~~~~~~~~~~~~~~~ + +``go_proto_library`` generates a set of .go files from a set of .proto files +(specified in a ``proto_library`` rule), then builds a Go library from those +files. ``go_proto_library`` can be imported like any ``go_library`` rule. + +Providers +^^^^^^^^^ + +* GoLibrary_ +* GoSource_ +* GoArchive_ + +Attributes +^^^^^^^^^^ + ++---------------------+----------------------+-------------------------------------------------+ +| **Name** | **Type** | **Default value** | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`name` | :type:`string` | |mandatory| | ++---------------------+----------------------+-------------------------------------------------+ +| A unique name for this rule. | +| | +| By convention, and in order to interoperate cleanly with Gazelle_, this | +| should be a name like ``foo_go_proto``, where ``foo`` is the Go package name | +| or the last component of the proto package name (hopefully the same). The | +| ``proto_library`` referenced by ``proto`` should be named ``foo_proto``. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`proto` | :type:`label` | |mandatory| | ++---------------------+----------------------+-------------------------------------------------+ +| Points to the ``proto_library`` containing the .proto sources this rule | +| should generate code from. Avoid using this argument, use ``protos`` instead. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`protos` | :type:`label` | |mandatory| | ++---------------------+----------------------+-------------------------------------------------+ +| List of ``proto_library`` targets containing the .proto sources this rule should generate | +| code from. This argument should be used instead of ``proto`` argument. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`deps` | :type:`label_list` | :value:`[]` | ++---------------------+----------------------+-------------------------------------------------+ +| List of Go libraries this library depends on directly. Usually, this will be | +| a list of ``go_proto_library`` rules that correspond to the ``deps`` of the | +| ``proto_library`` rule referenced by ``proto``. | +| | +| Additional dependencies may be added by the proto compiler. For example, the | +| default compiler implicitly adds dependencies on the ``go_proto_library`` | +| rules for the Well Known Types. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`importpath` | :type:`string` | |mandatory| | ++---------------------+----------------------+-------------------------------------------------+ +| The source import path of this library. Other libraries can import this | +| library using this path. This must be specified in ``go_proto_library`` or | +| inherited from one of the targets in ``embed``. | +| | +| ``importpath`` must match the import path specified in ``.proto`` files using | +| ``option go_package``. The option determines how ``.pb.go`` files generated | +| for protos importing this proto will import this package. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`importmap` | :type:`string` | :value:`""` | ++---------------------+----------------------+-------------------------------------------------+ +| The Go package path of this library. This is mostly only visible to the | +| compiler and linker, but it may also be seen in stack traces. This may be | +| set to prevent a binary from linking multiple packages with the same import | +| path, e.g., from different vendor directories. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`embed` | :type:`label_list` | :value:`[]` | ++---------------------+----------------------+-------------------------------------------------+ +| List of Go libraries that should be combined with this library. The ``srcs`` | +| and ``deps`` from these libraries will be incorporated into this library when it | +| is compiled. Embedded libraries must have the same ``importpath`` and | +| Go package name. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`gc_goopts` | :type:`string_list` | :value:`[]` | ++---------------------+----------------------+-------------------------------------------------+ +| List of flags to add to the Go compilation command when using the gc | +| compiler. Subject to `Make variable substitution`_ and `Bourne shell tokenization`_. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`compiler` | :type:`label` | :value:`None` | ++---------------------+----------------------+-------------------------------------------------+ +| Equivalent to ``compilers`` with a single label. | ++---------------------+----------------------+-------------------------------------------------+ +| :param:`compilers` | :type:`label_list` | :value:`["@io_bazel_rules_go//proto:go_proto"]` | ++---------------------+----------------------+-------------------------------------------------+ +| List of rules producing `GoProtoCompiler`_ providers (normally | +| `go_proto_compiler`_ rules). This is usually understood to be a list of | +| protoc plugins used to generate Go code. See `Predefined plugins`_ for | +| some options. | ++---------------------+----------------------+-------------------------------------------------+ + +Example: Basic proto +^^^^^^^^^^^^^^^^^^^^ + +Suppose you have two .proto files in separate packages: foo/foo.proto and +bar/bar.proto. foo/foo.proto looks like this: + +.. code:: proto + + syntax = "proto3"; + + option go_package = "example.com/repo/foo"; + + import "google/protobuf/any.proto"; + import "bar/bar.proto"; + + message Foo { + bar.Bar x = 1; + google.protobuf.Any y = 2; + }; + +In foo/BUILD.bazel, we need to declare a ``proto_library`` rule that lists +foo.proto in its ``srcs`` attribute. Since we import some other protos, we +also need a label in ``deps`` for each imported package. We will need to +create another ``proto_library`` in bar/BUILD.bazel, but we can use an +existing library for any.proto, since it's one of the Well Known Types. + +.. code:: bzl + + proto_library( + name = "foo_proto", + srcs = ["foo.proto"], + deps = [ + "//bar:bar_proto", + "@com_google_protobuf//:any_proto", + ], + visibility = ["//visibility:public"], + ) + +In order to these this proto in Go, we need to declare a ``go_proto_library`` +that references to ``proto_library`` to be built via the ``proto`` attribute. +Like ``go_library``, an ``importpath`` attribute needs to be declared. +Ideally, this should match the ``option go_package`` declaration in the .proto +file, but this is not required. We also need to list Go packages that the +generated Go code imports in the ``deps`` attributes. Generally, ``deps`` +in ``go_proto_library`` will correspond with ``deps`` in ``proto_library``, +but the Well Known Types don't need to be listed (they are added automatically +by the compiler in use). + +.. code:: bzl + + load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") + + go_proto_library( + name = "foo_go_proto", + importpath = "example.com/repo/foo", + proto = ":foo_proto", + visibility = ["//visibility:public"], + deps = ["//bar:bar_go_proto"], + ) + +This library can be imported like a regular Go library by other rules. + +.. code:: bzl + + load("@io_bazel_rules_go//go:def.bzl", "go_binary") + + go_binary( + name = "main", + srcs = ["main.go"], + deps = ["//foo:foo_go_proto"], + ) + +If you need to add additional source files to a package built from protos, +you can do so with a separate ``go_library`` that embeds the +``go_proto_library``. + +.. code:: bzl + + load("@io_bazel_rules_go//go:def.bzl", "go_library") + + go_library( + name = "foo", + srcs = ["extra.go"], + embed = [":foo_go_proto"], + importpath = "example.com/repo/foo", + visibility = ["//visibility:public"], + ) + +For convenience, ``proto_library``, ``go_proto_library``, and ``go_binary`` +can all be generated by Gazelle_. + +Example: gRPC +^^^^^^^^^^^^^ + +To compile protos that contain service definitions, just use the ``go_grpc`` +plugin. + +.. code:: bzl + + load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") + + proto_library( + name = "foo_proto", + srcs = ["foo.proto"], + visibility = ["//visibility:public"], + ) + + go_proto_library( + name = "foo_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc"], + importpath = "example.com/repo/foo", + proto = ":foo_proto", + visibility = ["//visibility:public"], + deps = ["//bar:bar_go_proto"], + ) + +go_proto_compiler +~~~~~~~~~~~~~~~~~ + +``go_proto_compiler`` describes a plugin for protoc, the proto compiler. +Different plugins will generate different Go code from the same protos. +Compilers may be chosen through the ``compilers`` attribute of +``go_proto_library``. + +Several instances of this rule are listed in `Predefined plugins`_. You will +only need to use this rule directly if you need a plugin which is not there. + +Providers +^^^^^^^^^ + +* GoProtoCompiler_ +* GoLibrary_ +* GoSource_ + +Attributes +^^^^^^^^^^ + ++-----------------------------+----------------------+-----------------------------------------------------+ +| **Name** | **Type** | **Default value** | ++-----------------------------+----------------------+-----------------------------------------------------+ +| :param:`name` | :type:`string` | |mandatory| | ++-----------------------------+----------------------+-----------------------------------------------------+ +| A unique name for this rule. | ++-----------------------------+----------------------+-----------------------------------------------------+ +| :param:`deps` | :type:`label_list` | :value:`[]` | ++-----------------------------+----------------------+-----------------------------------------------------+ +| List of Go libraries that Go code *generated by* this compiler depends on | +| implicitly. Rules in this list must produce the `GoLibrary`_ provider. This | +| should contain libraries for the Well Known Types at least. | ++-----------------------------+----------------------+-----------------------------------------------------+ +| :param:`options` | :type:`string_list` | :value:`[]` | ++-----------------------------+----------------------+-----------------------------------------------------+ +| List of command line options to be passed to the compiler. Each option will | +| be preceded by ``--option``. | ++-----------------------------+----------------------+-----------------------------------------------------+ +| :param:`suffix` | :type:`string` | :value:`.pb.go` | ++-----------------------------+----------------------+-----------------------------------------------------+ +| File name suffix of generated Go files. ``go_proto_compiler`` assumes that | +| one Go file will be generated for each input .proto file. Output file names | +| will have the .proto suffix removed and this suffix appended. For example, | +| ``foo.proto`` will become ``foo.pb.go``. | ++-----------------------------+----------------------+-----------------------------------------------------+ +| :param:`valid_archive` | :type:`bool` | :value:`True` | ++-----------------------------+----------------------+-----------------------------------------------------+ +| Whether code generated by this compiler can be compiled into a standalone | +| archive file without additional sources. | ++-----------------------------+----------------------+-----------------------------------------------------+ +| :param:`import_path_option` | :type:`bool` | :value:`True` | ++-----------------------------+----------------------+-----------------------------------------------------+ +| When true, the ``importpath`` attribute from ``go_proto_library`` rules | +| using this compiler will be passed to the compiler on the command line as | +| ``--option import_path={}``. | ++-----------------------------+----------------------+-----------------------------------------------------+ +| :param:`plugin` | :type:`label` | :value:`@com_github_golang_protobuf//protoc-gen-go` | ++-----------------------------+----------------------+-----------------------------------------------------+ +| The plugin to use with protoc via the ``--plugin`` option. This rule must | +| produce an executable file. | ++-----------------------------+----------------------+-----------------------------------------------------+ + +Predefined plugins +------------------ + +Several ``go_proto_compiler`` rules are predefined in +``@io_bazel_rules_go//proto``. + +* ``go_proto``: default plugin from github.com/golang/protobuf. +* ``go_grpc``: default gRPC plugin. +* ``go_proto_validate``: validator plugin from + github.com/mwitkow/go-proto-validators. Generates ``Validate`` methods. +* gogoprotobuf_ plugins for the variants ``combo``, ``gofast``, ``gogo``, + ``gogofast``, ``gogofaster``, ``gogoslick``, ``gogotypes``, ``gostring``. + For each variant, there is a regular version (e.g., ``gogo_proto``) and a + gRPC version (e.g., ``gogo_grpc``). + +Providers +--------- + +Providers are objects produced by Bazel rules and consumed by other rules that +depend on them. See `Go providers`_ for information about Go providers, +specifically GoLibrary_, GoSource_, and GoArchive_. + +GoProtoCompiler +~~~~~~~~~~~~~~~ + +GoProtoCompiler is the provider returned by the ``go_proto_compiler`` rule and +anything compatible with it. The ``go_proto_library`` rule expects any rule +listed in its ``compilers`` attribute to provide ``GoProtoCompiler``. If the +``go_proto_compiler`` rule doesn't do what you need (e.g., you don't want to +use protoc), you can write a new rule that produces this. + +``GoProtoCompiler`` is loaded from ``@io_bazel_rules_go//proto:def.bzl``. + +``GoProtoCompiler`` has the fields described below. Additional fields may be +added to pass information to the ``compile`` function. This interface is +*not final* and may change in the future. + ++-----------------------------+-------------------------------------------------+ +| **Name** | **Type** | ++-----------------------------+-------------------------------------------------+ +| :param:`deps` | :type:`Target list` | ++-----------------------------+-------------------------------------------------+ +| A list of Go libraries to be added as dependencies to any | +| ``go_proto_library`` compiled with this compiler. Each target must provide | +| GoLibrary_, GoSource_, and GoArchive_. This list should include libraries | +| for the Well Known Types and anything else considered "standard". | ++-----------------------------+-------------------------------------------------+ +| :param:`compile` | :type:`Function` | ++-----------------------------+-------------------------------------------------+ +| A function which declares output files and actions when called. See | +| `compiler.bzl`_ for details. | ++-----------------------------+-------------------------------------------------+ +| :param:`valid_archive` | :type:`bool` | ++-----------------------------+-------------------------------------------------+ +| Whether the compiler produces a complete Go library. Compilers that just add | +| methods to structs produced by other compilers will set this to false. | ++-----------------------------+-------------------------------------------------+ + +Dependencies +------------ + +In order to support protocol buffers, rules_go declares the external +repositories listed below in ``go_rules_dependencies()``. These repositories +will only be downloaded if proto rules are used. + +* ``@com_google_protobuf (github.com/google/protobuf)``: Well Known Types and + general proto support. +* ``@com_github_golang_protobuf (github.com/golang/protobuf)``: standard + Go proto plugin. +* ``@com_github_mwitkow_go_proto_validators + (github.com/mwitkow/go-proto-validators)``: validator plugin. +* ``@com_github_gogo_protobuf (github.com/gogo/protobuf)``: gogoprotobuf + plugins. +* ``@org_golang_google_grpc (github.com/grpc/grpc-go``: gRPC support. +* gRPC dependencies + + * ``@org_golang_x_net (golang.org/x/net)`` + * ``@org_golang_x_text (golang.org/x/text)`` + * ``@org_golang_google_genproto (google.golang.org/genproto)`` |