blob: f9df6b9f7153aee3688ab254ed88998cddc13b13 [file] [log] [blame] [edit]
Extending Gazelle
=================
.. Begin directives
.. _Language: https://godoc.org/github.com/bazelbuild/bazel-gazelle/language#Language
.. _`//internal/gazellebinarytest:go_default_library`: https://github.com/bazelbuild/bazel-gazelle/tree/master/internal/gazellebinarytest
.. _`//language/go:go_default_library`: https://github.com/bazelbuild/bazel-gazelle/tree/master/language/go
.. _`//language/proto:go_default_library`: https://github.com/bazelbuild/bazel-gazelle/tree/master/language/proto
.. _gazelle: https://github.com/bazelbuild/bazel-gazelle#bazel-rule
.. _go_binary: https://github.com/bazelbuild/rules_go/blob/master/go/core.rst#go-binary
.. _go_library: https://github.com/bazelbuild/rules_go/blob/master/go/core.rst#go-library
.. _proto godoc: https://godoc.org/github.com/bazelbuild/bazel-gazelle/language/proto
.. _proto.GetProtoConfig: https://godoc.org/github.com/bazelbuild/bazel-gazelle/language/proto#GetProtoConfig
.. _proto.Package: https://godoc.org/github.com/bazelbuild/bazel-gazelle/language/proto#Package
.. _rules_r: https://github.com/grailbio/rules_r
.. _bazel-skylib: https://github.com/bazelbuild/bazel-skylib/tree/main/gazelle/bzl
.. _bazel_rules_nodejs_contrib: https://github.com/ecosia/bazel_rules_nodejs_contrib#build-file-generation
.. _#803: https://github.com/bazelbuild/bazel-gazelle/issues/803
.. role:: cmd(code)
.. role:: flag(code)
.. role:: direc(code)
.. role:: param(kbd)
.. role:: type(emphasis)
.. role:: value(code)
.. |mandatory| replace:: **mandatory value**
.. End directives
Gazelle started out as a build file generator for Go projects, but it can be
extended to support other languages and custom sets of rules.
To extend Gazelle, you must do three things:
* Write a `go_library`_ with a function named ``NewLanguage`` that provides an
implementation of the Language_ interface. This interface provides hooks for
generating rules, parsing configuration directives, and resolving imports
to Bazel labels.
* Write a `gazelle_binary`_ rule. Include your library in the ``languages``
list.
* Write a `gazelle`_ rule that points to your ``gazelle_binary``. When you run
``bazel run //:gazelle``, your binary will be built and executed instead of
the default binary.
Supported languages
-------------------
Some extensions have been published by the community.
* `bazel-skylib`_ has an extension for generating ``bzl_library``.
* `rules_r`_ has an extension for generating rules for R package builds and
tests.
* Ecosia's `bazel_rules_nodejs_contrib`_ has an extension for generating
``js_library``, ``jest_node_test``, ``js_import``, and ``ts_library`` rules.
If you have an extension you'd like linked here, please open a PR!
Example
-------
**TODO:** Add a self-contained, concise, realistic example.
Gazelle itself is built using the model described above, so it may serve as
an example.
`//language/proto:go_default_library`_ and `//language/go:go_default_library`_
both implement the `Language`_
interface. There is also `//internal/gazellebinarytest:go_default_library`_,
a stub implementation used for testing.
``//cmd/gazelle`` is a ``gazelle_binary`` rule that includes both of these
libraries through the ``DEFAULT_LANGUAGES`` list (you may want to use
``DEFAULT_LANGUAGES`` in your own rule).
.. code:: bzl
load("@bazel_gazelle//:def.bzl", "DEFAULT_LANGUAGES", "gazelle_binary")
gazelle_binary(
name = "gazelle",
languages = DEFAULT_LANGUAGES,
visibility = ["//visibility:public"],
)
This binary can be invoked using a ``gazelle`` rule like this:
.. code:: bzl
load("@bazel_gazelle//:def.bzl", "gazelle")
# gazelle:prefix example.com/project
gazelle(
name = "gazelle",
gazelle = "//:my_gazelle_binary",
)
You can run this with ``bazel run //:gazelle``.
gazelle_binary
--------------
The ``gazelle_binary`` rule builds a Go binary that incorporates a list of
language extensions. This requires generating a small amount of code that
must be compiled into Gazelle's main package, so the normal `go_binary`_
rule is not used.
When the binary runs, each language extension is run sequentially. This affects
the order that rules appear in generated build files. Metadata may be produced
by an earlier extension and consumed by a later extension. For example, the
proto extension stores metadata in hidden attributes of generated
``proto_library`` rules. The Go extension uses this metadata to generate
``go_proto_library`` rules.
The following attributes are supported on the ``gazelle_binary`` rule.
+----------------------+---------------------+--------------------------------------+
| **Name** | **Type** | **Default value** |
+======================+=====================+======================================+
| :param:`languages` | :type:`label_list` | |mandatory| |
+----------------------+---------------------+--------------------------------------+
| A list of language extensions the Gazelle binary will use. |
| |
| Each extension must be a `go_library`_ or something compatible. Each extension |
| must export a function named ``NewLanguage`` with no parameters that returns |
| a value assignable to `Language`_. |
+----------------------+---------------------+--------------------------------------+
The following attributes are deprecated (`#803`_):
+----------------------+---------------------+--------------------------------------+
| **Name** | **Type** | **Default value** |
+======================+=====================+======================================+
| :param:`pure` | :type:`string` | :value:`auto` |
+----------------------+---------------------+--------------------------------------+
| Same meaning as `go_binary`_. It may be necessary to set this to avoid |
| command flags that affect both host and target configurations. |
+----------------------+---------------------+--------------------------------------+
| :param:`static` | :type:`string` | :value:`auto` |
+----------------------+---------------------+--------------------------------------+
| Same meaning as `go_binary`_. It may be necessary to set this to avoid |
| command flags that affect both host and target configurations. |
+----------------------+---------------------+--------------------------------------+
| :param:`race` | :type:`string` | :value:`auto` |
+----------------------+---------------------+--------------------------------------+
| Same meaning as `go_binary`_. It may be necessary to set this to avoid |
| command flags that affect both host and target configurations. |
+----------------------+---------------------+--------------------------------------+
| :param:`msan` | :type:`string` | :value:`auto` |
+----------------------+---------------------+--------------------------------------+
| Same meaning as `go_binary`_. It may be necessary to set this to avoid |
| command flags that affect both host and target configurations. |
+----------------------+---------------------+--------------------------------------+
| :param:`goos` | :type:`string` | :value:`auto` |
+----------------------+---------------------+--------------------------------------+
| Same meaning as `go_binary`_. It may be necessary to set this to avoid |
| command flags that affect both host and target configurations. |
+----------------------+---------------------+--------------------------------------+
| :param:`goarch` | :type:`string` | :value:`auto` |
+----------------------+---------------------+--------------------------------------+
| Same meaning as `go_binary`_. It may be necessary to set this to avoid |
| command flags that affect both host and target configurations. |
+----------------------+---------------------+--------------------------------------+
Interacting with protos
-----------------------
The proto extension (`//language/proto:go_default_library`_) gathers metadata
from .proto files and generates ``proto_library`` rules based on that metadata.
Extensions that generate language-specific proto rules (e.g.,
``go_proto_library``) may use this metadata.
For API reference, see the `proto godoc`_.
To get proto configuration information, call `proto.GetProtoConfig`_. This is
mainly useful for discovering the current proto mode.
To get information about ``proto_library`` rules, examine the ``OtherGen``
list of rules passed to ``language.GenerateRules``. This is a list of rules
generated by other language extensions, and it will include ``proto_library``
rules in each directory, if there were any. For each of these rules, you can
call ``r.PrivateAttr(proto.PackageKey)`` to get a `proto.Package`_ record. This
includes the proto package name, as well as source names, imports, and options.