1Autogazelle: fast, automatic build file generation
2==================================================
3
4.. _cmd/autogazelle/autogazelle.bash: autogazelle.bash
5
6Autogazelle is a wrapper program that runs Gazelle as part of each
7Bazel command. You can add, delete, or rename source files, add imports, then
8just ``bazel build``. Your build files are updated automatically during the
9build.
10
11*Autogazelle is highly experimental and may change significantly in the future.
12Use with caution. See* `Limitations`_ *below.*
13
14Setting up autogazelle
15----------------------
16
17Before you begin
18~~~~~~~~~~~~~~~~
19
20Make sure the ``bazel_gazelle`` repository is declared in your ``WORKSPACE``.
21It should look the the snippet below, but the versions will likely be different.
22It may be possible to used Autogazelle from a vendored ``bazel_gazelle``
23repository, but this is not directly supported yet.
24
25.. code:: bzl
26
27 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
28
29 http_archive(
30 name = "io_bazel_rules_go",
31 integrity = "sha256-fHbWI2so/2laoozzX5XeMXqUcv0fsUrHl8m/aE8Js3w=",
32 urls = [
33 "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.44.2/rules_go-v0.44.2.zip",
34 "https://github.com/bazelbuild/rules_go/releases/download/v0.44.2/rules_go-v0.44.2.zip",
35 ],
36 )
37
38 http_archive(
39 name = "bazel_gazelle",
40 integrity = "sha256-MpOL2hbmcABjA1R5Bj2dJMYO2o15/Uc5Vj9Q0zHLMgk=",
41 urls = [
42 "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.35.0/bazel-gazelle-v0.35.0.tar.gz",
43 "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.35.0/bazel-gazelle-v0.35.0.tar.gz",
44 ],
45 )
46
47 load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
48 go_rules_dependencies()
49 go_register_toolchains()
50 load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
51 gazelle_dependencies()
52
53Make sure you have a ``gazelle`` rule declared in your root build file.
54It should look this this, probably with different options.
55
56.. code:: bzl
57
58 load("@bazel_gazelle//:def.bzl", "gazelle")
59
60 # gazelle:prefix github.com/example/project
61 gazelle(name = "gazelle")
62
63Installing the wrapper
64~~~~~~~~~~~~~~~~~~~~~~
65
66In order to run autogazelle as part of each Bazel command, you'll need to
67copy `cmd/autogazelle/autogazelle.bash`_ to ``tools/bazel`` within your
68repository. Make sure the script is executable. The ``bazel`` script in
69your ``PATH`` will execute this script instead of the real ``bazel`` binary
70if it's present and executable.
71
72Deleting build files
73~~~~~~~~~~~~~~~~~~~~
74
75If your build files are completely generated by Gazelle, you may want to
76delete them from source control, since they can be easily regenerated.
77When Gazelle generates new files, it names them ``BUILD.bazel`` by default,
78so you can add ``BUILD.bazel`` to your ``.gitignore`` file after deleting
79them.
80
81It's likely that you'll have some build files with manual modifications
82you want to keep around. At minimum, you'll need to keep the root build
83file since it contains the ``gazelle`` rule. The simplest way to keep these
84files is to name the ``BUILD`` instead of ``BUILD.bazel``. Bazel and Gazelle
85will both recognize files named ``BUILD``, and Git will not ignore them.
86
87Another option is to name your files ``BUILD.bazel.in`` or ``BUILD.in``.
88Autogazelle will copy these files to ``BUILD.bazel`` or ``BUILD`` when it
89starts running before invoking Gazelle.
90
91How autogazelle works
92---------------------
93
94Autogazelle has three components: a wrapper script, a client, and a server.
95
96The *wrapper script* is a bash script installed in ``tools/bazel`` in workspaces
97that use autogazelle. The ``bazel`` command installed in your ``PATH`` will look
98for an executable file at this location and will execute it instead of the real
99bazel. The script builds and runs the *autogazelle client* using ``bazel run``
100before invoking the real bazel binary with the original command-line arguments.
101
102The *client* is a Go program that attempts to connect to the *server*
103over a UNIX domain socket. If the server isn't running, the client will
104start it and connect. Once connected, the client will wait for the server
105to disconnect before exiting. The client does no other work.
106
107The *server* is a Go program (actually the same binary as the client, started
108with different options) that listens for connections on a UNIX domain socket.
109When it accepts a connection, it runs Gazelle using ``bazel run``, then closes
110the connection. The socket is just used to make the client wait until Gazelle
111completes; no information is exchanged, other than log messages. While the
112server is waiting for a connection, it watches the file system for changes that
113could affect build files. When the server runs Gazelle, it runs only in
114directories that have changed. This makes Gazelle run much faster. The server
115exits after being idle for an hour.
116
117Limitations
118-----------
119
120Dependency resolution
121~~~~~~~~~~~~~~~~~~~~~
122
123Autogazelle tries to run Gazelle quickly by only updating certain
124directories. To support this, it runs Gazelle with the flags ``-r=false``
125(don't recurse through selected directories) and ``-index=false`` (don't
126build an index of library targets for dependency resolution). This means
127that you'll need to set ``external = "vendored"`` explicitly on your ``gazelle``
128rule if you have a vendor directory, and you'll need to add
129``# gazelle:resolve`` directives in your root build files for any imports
130that should be resolved to custom names.
131
132Platform support
133~~~~~~~~~~~~~~~~
134
135Autogazelle uses UNIX-domain sockets to synchronize the client and server. This
136only works on UNIX-like platforms; these sockets are not supported on Windows.
137
138Autogazelle uses ``github.com/fsnotify/fsnotify`` to watch the file system. This
139library works on multiple platforms, but it won't work on file systems that
140don't support watches (e.g., NFS and most other network file systems).
141
142Autogazelle has only been tested on Linux. It is intended to work on macOS, but
143this has not been tested yet.
144
145Credits
146-------
147
148The original idea for running Gazelle automatically was proposed by Matthew
149Moore (@mattmoor). The initial plan was to run Gazelle in a repository rule
150which regenerate a repository full of build files on each run.
151
152Erick Fejta (@fejta) prototyped this idea for Kubernetes. You can find the
153prototype at https://github.com/kubernetes/test-infra/tree/master/autogo.
View as plain text