• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. _contrib-docs-build:
2
3=========================================
4Working with the pigweed.dev build system
5=========================================
6``pigweed.dev`` is built with Bazel. When you want to add or remove files
7used by ``pigweed.dev``, you'll need to interact with this Bazel-based
8documentation generation (docgen) system.
9
10Check out :ref:`contrib-docs-build-appendix-architecture` for a top-down explanation
11of the main components of the docgen system.
12
13.. _contrib-docs-build-quickstart:
14
15----------
16Quickstart
17----------
18#. Build the docs:
19
20   .. code-block:: console
21
22      $ bazelisk build //docs:docs
23
24#. Locally preview the docs:
25
26   .. code-block:: console
27
28      $ bazelisk run //docs:docs.serve
29
30.. _contrib-docs-build-setup:
31
32-----
33Setup
34-----
35Before you can do anything with the Bazel-based docgen system, you must
36complete this setup:
37
38#. Complete :ref:`docs-first-time-setup`.
39
40#. :ref:`docs-install-bazel`.
41
42.. _contrib-docs-build-files:
43
44---------------------------
45Add files to the docs build
46---------------------------
47
48.. _contrib-docs-build-files-doxygen:
49
50Add files to the C/C++ API reference auto-generation system (Doxygen)
51=====================================================================
52#. Package your headers into a ``filegroup``:
53
54   .. code-block:: py
55
56      filegroup(
57          name = "doxygen",
58          srcs = [
59              "public/pw_string/format.h",
60              "public/pw_string/string.h",
61              "public/pw_string/string_builder.h",
62              "public/pw_string/utf_codecs.h",
63              "public/pw_string/util.h",
64          ],
65      )
66
67#. Update ``doxygen_srcs`` in ``//docs/BUILD.bazel`` to take a
68   dependency on your new ``filegroup``:
69
70   .. code-block:: py
71
72      filegroup(
73          name = "doxygen_srcs",
74          srcs = [
75              # …
76              "//pw_string:doxygen",
77              # …
78          ]
79      )
80
81.. _Breathe directive: https://breathe.readthedocs.io/en/latest/directives.html
82
83#. Use a `Breathe directive`_ such as ``.. doxygenclass::`` to pull the API
84   reference content into a reStructuredText file.
85
86.. _contrib-docs-build-files-autodoc:
87
88Add files to the Python API reference auto-generation system (autodoc)
89======================================================================
90If you see an error like this:
91
92.. code-block:: text
93
94   sphinx.errors.SphinxWarning: autodoc: failed to import module 'benchmark'
95   from module 'pw_rpc'; the following exception was raised:
96   No module named 'pw_rpc.benchmark'
97
98.. inclusive-language: disable
99.. _autodoc: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html
100.. inclusive-language: enable
101
102It means that `autodoc`_ (the program we use to auto-generate Python API
103references) could not find the source code for the module that it was
104supposed to document. To fix this:
105
106#. Add your Python target as a dependency to the ``sphinx_build_binary``
107   rule in ``//docs/BUILD.bazel``:
108
109   .. code-block:: py
110
111      sphinx_build_binary(
112          name = "sphinx_build",
113          target_compatible_with = incompatible_with_mcu(),
114          deps = [
115              # …
116              "//pw_rpc/py:pw_rpc_benchmark",
117              # …
118          ],
119      )
120
121.. _contrib-docs-build-files-sphinx:
122
123Add reStructuredText files to Sphinx
124====================================
125#. Package your inputs into a ``sphinx_docs_library``:
126
127   .. code-block:: py
128
129      load("@rules_python//sphinxdocs:sphinx_docs_library.bzl", "sphinx_docs_library")
130      load("//pw_build:compatibility.bzl", "incompatible_with_mcu")
131
132      sphinx_docs_library(
133          name = "docs",
134          srcs = [
135              "docs.rst",
136          ],
137          prefix = "pw_elf/",
138          target_compatible_with = incompatible_with_mcu(),
139          visibility = ["//visibility:public"],
140      )
141
142#. Update ``docs`` in ``//docs/BUILD.bazel`` to take a dependency on
143   your new ``sphinx_docs_library``:
144
145   .. code-block:: py
146
147      sphinx_docs(
148          name = "docs",
149          # …
150          deps = [
151              # …
152              "//pw_elf:docs",
153              # …
154          ]
155      )
156
157.. _toctree: https://documatt.com/restructuredtext-reference/element/toctree.html
158
159#. Add your new reStructuredText files to an existing `toctree`_, or create a new one.
160
161.. _contrib-docs-build-files-source:
162
163Add source code to the docs build
164=================================
165Whenever possible, don't manually write code examples in your reStructuredText
166(reST) docs. These code examples will bitrot over time. Instead, put your code
167examples in real source code that can actually be built and tested, and then
168use Sphinx's ``literalinclude`` feature to insert the code example into your
169doc.
170
171#. Put your code example into a unit test:
172
173   .. code-block:: c++
174
175      // examples.cc
176
177      TEST(StringExamples, BufferExample) {
178        // START: BufferExample
179        // …
180        // END: BufferExample
181      }
182
183#. Include the code example in your reST:
184
185   .. code-block:: rest
186
187      .. literalinclude:: ./examples.cc
188         :language: cpp
189         :dedent:
190         :start-after: // START: BufferExample
191         :end-before: // END: BufferExample
192
193#. Add the source code file to the ``srcs`` list in your
194   ``sphinx_docs_library`` target:
195
196   .. code-block:: py
197
198      sphinx_docs_library(
199          name = "docs",
200          srcs = [
201              # …
202              "examples.cc",
203              # …
204          ],
205      )
206
207.. _contrib-docs-build-files-images:
208
209Add images
210==========
211Images should not be checked into the Pigweed repo.
212See :ref:`contrib-docs-website-images`.
213
214.. _contrib-docs-build-files-remove:
215
216----------------------------------------
217Remove or change files in the docs build
218----------------------------------------
219Here's the general workflow:
220
221#. Remove or change files that are used in the docs build.
222
223#. :ref:`contrib-docs-build-build`.
224
225#. When the docs build fails, Bazel's logs will tell you what you need to do
226   next. If Bazel's logs aren't informative, try some of the tips described
227   in :ref:`contrib-docs-build-debug`.
228
229You may need to do some or all of these steps:
230
231* In your module's ``BUILD.bazel`` files, update these rules:
232
233  * ``sphinx_docs_library`` targets (usually named ``docs``)
234
235  * ``filegroup`` targets named ``doxygen``
236
237* Update ``//docs/BUILD.bazel``.
238
239* :ref:`redirects <contrib-docs-website-redirects>`.
240
241.. _contrib-docs-build-build:
242
243--------------
244Build the docs
245--------------
246.. code-block:: console
247
248   $ bazelisk build //docs:docs
249
250.. _contrib-docs-build-build-watch:
251
252Watch the docs (automatically rebuild when files change)
253========================================================
254.. code-block:: console
255
256   $ bazelisk run //:watch build //docs:docs
257
258.. tip::
259
260   Try :ref:`locally previewing the docs <contrib-docs-build-preview>` in one console
261   tab and watching the docs in another tab.
262
263.. _contrib-docs-build-preview:
264
265------------------------
266Locally preview the docs
267------------------------
268.. code-block:: console
269
270   $ bazelisk run //docs:docs.serve
271
272A message like this should get printed to ``stdout``:
273
274.. code-block:: text
275
276   Serving...
277     Address: http://0.0.0.0:8000
278     Serving directory: /home/kayce/pigweed/pigweed/bazel-out/k8-fastbuild/bin/docs/docs/_build/html
279         url: file:///home/kayce/pigweed/pigweed/bazel-out/k8-fastbuild/bin/docs/docs/_build/html
280     Server CWD: /home/kayce/.cache/bazel/_bazel_kayce/9659373b1552c281136de1c8eeb3080d/execroot/_main/bazel-out/k8-fastbuild/bin/docs/docs.serve.runfiles/_main
281
282You can access the rendered docs at the URL that's printed next to
283**Address** (``http://0.0.0.0:8000`` in the example).
284
285.. _contrib-docs-build-list:
286
287---------------------
288List all docs sources
289---------------------
290.. _hermetic: https://bazel.build/basics/hermeticity
291
292Bazel builds the docs in a `hermetic`_ environment. All inputs to the docgen
293system must be copied into this hermetic environment. To check that you're
294copying your files to the correct directory, run this command:
295
296.. code-block:: console
297
298   $ bazelisk build //docs:_docs/_sources
299
300.. _contrib-docs-build-debug:
301
302--------------------
303Debug the docs build
304--------------------
305.. inclusive-language: disable
306.. _sphinx-build: https://www.sphinx-doc.org/en/master/man/sphinx-build.html
307.. _--verbose: https://www.sphinx-doc.org/en/master/man/sphinx-build.html#cmdoption-sphinx-build-v
308.. inclusive-language: enable
309
310When things go wrong, run this command to build the docs in a
311non-`hermetic`_ environment:
312
313.. code-block:: console
314
315   $ bazelisk run //docs:docs.run
316
317Also consider tweaking these ``extra_opts`` from the ``sphinx_docs`` rule in
318``//docs/BUILD.bazel``:
319
320* Comment out the ``--silent`` warning to get more verbose logging output.
321* Check `sphinx-build`_ to see what other options you might want to add or remove.
322  ``sphinx-build`` is the underlying command that the ``sphinx_docs`` Bazel rule runs.
323
324.. _contrib-docs-build-troubleshoot:
325
326---------------
327Troubleshooting
328---------------
329
330.. _contrib-docs-build-troubleshoot-autodoc:
331
332autodoc: failed to import module
333================================
334See :ref:`contrib-docs-build-files-autodoc`.
335
336.. _contrib-docs-build-appendix-architecture:
337
338-------------------------------
339Appendix: Architecture overview
340-------------------------------
341The outputs of some components of the docgen system are used as inputs
342to other components.
343
344.. mermaid::
345
346   flowchart LR
347
348     Doxygen --> Breathe
349     Breathe --> reST
350     reST --> Sphinx
351     Rust --> Sphinx
352     Python --> Sphinx
353
354.. _Doxygen: https://www.doxygen.nl/
355.. _Breathe: https://breathe.readthedocs.io/en/latest/
356.. _reStructuredText: https://docutils.sourceforge.io/rst.html
357.. _rustdoc: https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html
358.. inclusive-language: disable
359.. _autodoc: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html
360.. _Sphinx: https://www.sphinx-doc.org/en/master/
361.. inclusive-language: enable
362.. _static site generator: https://en.wikipedia.org/wiki/Static_site_generator
363
364* **Doxygen**: We feed a bunch of C/C++ headers to `Doxygen`_. Doxygen parses each
365  header and generates XML metadata for all of the classes, functions, structs,
366  etc. that it finds. We also publish the Doxygen-generated HTML as a separate
367  subsite. This subsite is available at
368  `pigweed.dev/doxygen <https://pigweed.dev/doxygen>`_.
369
370* **Breathe**: We provide the Doxygen XML metadata to `Breathe`_ so that C/C++ API
371  reference content can be inserted into our reStructuredText files.
372
373* **reST**: We gather up all the `reStructuredText`_ (reST) source files
374  that are scattered across the Pigweed repository. Pigweed docs are authored in
375  reST. We don't use Markdown.
376
377* **Rust**: `rustdoc`_ generates Rust API reference content, similar to how
378  Doxygen generates C/C++ API reference content. The Rust API references are output
379  as HTML. It's essentially a separate documentation subsite that is not integrated
380  with the rest of ``pigweed.dev`` (yet). This subsite is available at URLs like
381  `pigweed.dev/rustdoc/pw_bytes/ <https://pigweed.dev/rustdoc/pw_bytes/>`_.
382
383* **Python**: We use Sphinx's `autodoc`_ feature to auto-generate Python API
384  reference content. In order for this to work, the Python modules must be
385  listed as dependencies of the ``//docs:docs`` target.
386
387* **Sphinx**: Once all the other inputs are ready, we can use `Sphinx`_
388  (essentially a `static site generator`_) to build the ``pigweed.dev``
389  website.
390