| <!-- This file was previously generated by Stardoc but is now maintained |
| by humans. --> |
| |
| Extending Gazelle |
| ================= |
| |
| 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. By convention, the library's package name should match |
| the language (for example, `proto` or `bzl`). |
| * Write a [gazelle_binary](reference.md#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. |
| |
| Tests |
| ----- |
| |
| To write tests for your gazelle extension, you can use [gazelle_generation_test](reference.md#gazelle_generation_test), |
| which will run a gazelle binary of your choosing on a set of test workspaces. |
| |
| |
| Supported languages |
| ------------------- |
| |
| Moved to [/README.rst](/README.rst#supported-languages) |
| |
| 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). |
| |
| ```starlark |
| load("@bazel_gazelle//:def.bzl", "DEFAULT_LANGUAGES", "gazelle_binary") |
| |
| gazelle_binary( |
| name = "my_gazelle_binary", |
| languages = [ |
| "@rules_python_gazelle_plugin//python", # Use gazelle from rules_python. |
| "@bazel_gazelle//language/go", # Built-in rule from gazelle for Golang. |
| "@bazel_gazelle//language/proto", # Built-in rule from gazelle for Protos. |
| # Any languages that depend on Gazelle's proto plugin must come after it. |
| "@external_repository//language/gazelle", # External languages can be added here. |
| ], |
| visibility = ["//visibility:public"], |
| ) |
| ``` |
| |
| This binary can be invoked using a `gazelle` rule like this: |
| |
| ```starlark |
| 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`. |
| |
| Lazy indexing |
| ------------- |
| |
| Lazy indexing lets Gazelle run quickly without needing to read all build files |
| in a repo while still supporting index-based dependency resolution. This allows |
| Gazelle to update build files for specific directories in milliseconds rather |
| than seconds or minutes. |
| |
| Lazy indexing requires a small amount of user configuration, pointing to |
| directories that may contain libraries based on import strings read from source |
| files. It also requires support from language extensions to interpret that |
| configuration. Most language extensions should implement this, though the |
| implementation will be a bit different for each language. |
| |
| As an extended example, suppose a Go user has copied their module dependency |
| `example.com/b` into the directory `replace/b`. From some other directory `a`, |
| they import the package `example.com/b/c`. They then run |
| `gazelle update -r=false -index=lazy a` to generate a build file for `a` with |
| lazy indexing enabled. |
| |
| In this configuration, Gazelle doesn't automatically index `replace/b`, so |
| the user must add a directive to their top-level build file: |
| |
| ```starlark |
| # gazelle:go_search replace/b example.com/b |
| ``` |
| |
| This directive is interpreted by the Go extension. The user is telling Gazelle |
| to index the directory `replace/b/<suffix>` when it sees a Go package imported |
| with the string `example.com/b/<suffix>`. So in our example, when Gazelle sees |
| `example.com/b/c`, it indexes `replace/b/c` and makes all library targets |
| available for dependency resolution, including non-Go libraries that happen to |
| be there. |
| |
| To support this, the Go extension needs to: |
| |
| 1. Support the `go_search` directive in the `KnownDirectives` and `Configure` |
| methods of the |
| [`Configurer`](https://pkg.go.dev/github.com/bazelbuild/bazel-gazelle/config#Configurer) |
| implementation. This directive may be repeated and applies in subdirectories. |
| 1. Convert an import string like `example.com/b/c` into a list of directory |
| paths like `replace/b/c`. |
| 1. Return the directory paths through |
| [`GenerateResult.RelsToIndex`](https://pkg.go.dev/github.com/bazelbuild/bazel-gazelle/language#GenerateResult) |
| in the |
| [`Language.GenerateRules`](https://pkg.go.dev/github.com/bazelbuild/bazel-gazelle/language#Language) |
| method. |
| |
| Other extensions should follow a similar approach, though there are likely to |
| be differences in how `*_search` directives and import strings are interpreted. |
| For example, the protobuf and C++ extensions have `proto_search` and `cc_search` |
| directives which are similar to each other but not to Go: both languages |
| import libraries by file name and have similar conventions. |
| |
| 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. |
| |
| [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 |