1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
|
.. _quickstart_guide:
Quickstart Guide
========================================================================================
You will need to edit **2** files: ``conf.py`` to configure the extensions, and
``index.rst`` (or whatever document you choose) to include the generated api in a
``toctree`` directive. Both ``conf.py`` and ``index.rst`` are part of a default Sphinx
documentation project, the next section will walk you through how to create a new Sphinx
project and the subsequent sections explain the modifications required on each document.
.. contents:: Contents
:local:
:backlinks: none
Getting Started with Sphinx
----------------------------------------------------------------------------------------
To get a project started with Sphinx, we will want to run the ``sphinx-quickstart``
utility. Assuming you are already working in a git repository, the canonical location
to do this in would be ``{repo_root}/docs``. So let's go ahead and make that folder
and get our Sphinx project started:
.. code-block:: console
$ cd /path/to/my/repo
$ mkdir docs
$ cd docs
The output below is getting broken up into sections to explain what is happening, but
when you run this from your terminal you will need to of course complete it from start
to finish.
.. code-block:: console
$ sphinx-quickstart
Welcome to the Sphinx 4.3.1 quickstart utility.
Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).
Selected root path: .
You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: n
The default choice ``n`` says "keep things together". This is my personal preference,
but it is not overwhelmingly significant.
+-----------------------------+---------------------------+
| Choosing ``n`` | Choosing ``y`` |
+=============================+===========================+
| .. code-block:: text | .. code-block:: text |
| | |
| docs/ | docs/ |
| ├── _build | ├── build |
| │ build artifacts | │ build artifacts |
| │ go here | │ go here |
| ├── conf.py | ├── make.bat |
| ├── index.rst | ├── Makefile |
| ├── make.bat | └── source |
| ├── Makefile | ├── conf.py |
| ├── _static | ├── index.rst |
| └── _templates | ├── _static |
| | └── _templates |
+-----------------------------+---------------------------+
The main thing to understand is that where Exhale is concerned, **all relative paths
specified in any configuration variables are relative to wherever** ``conf.py``
**lives**. The ``build artifacts go here`` section is to just explain that if you do
``make html``, then in the ``n`` case a folder ``docs/_build/html`` will be created, and
in the ``y`` case it will be in ``docs/build/html``. Repeat for ``make linkcheck``.
In either case, you will definitely want to add ``docs/_build`` or ``docs/build`` to
your ``.gitignore`` or related version control ignore file.
The only other thing worth pointing out here is that by default sphinx creates the
``_static`` and ``_templates`` directories for you. At first start, you don't use those
but:
``_static``
Where you would track things like a ``custom.css`` stylesheet, any logo icons,
a ``custom.js`` javascript file, etc. See :confval:`sphinx:html_static_path`.
``_templates``
Where you would store custom jinja2 templates to override settings in your chosen
:confval:`sphinx:html_theme`. The templates are read from
:confval:`sphinx:templates_path` which defaults to ``_templates``. See also:
`Sphinx Templating <https://www.sphinx-doc.org/en/master/development/templating.html>`_.
Finishing the ``sphinx-quickstart`` command output, we enter the relevant metadata about
our project so that sphinx can populate as much as possible of our ``conf.py`` for us:
.. code-block:: console
$ sphinx-quickstart
...
The project name will occur in several places in the built documentation.
> Project name: Super Project
> Author name(s): Myself ThePerson, Robotic Armistice
> Project release []: 0.1.0
If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.
For a list of supported codes, see
https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language.
> Project language [en]:
Creating file /path/to/docs/conf.py.
Creating file /path/to/docs/index.rst.
Creating file /path/to/docs/Makefile.
Creating file /path/to/docs/make.bat.
Finished: An initial directory structure has been created.
You should now populate your master file /path/to/docs/index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck
There is also the official `Sphinx Quickstart Guide`__ with more information on builders
and whatnot.
__ https://www.sphinx-doc.org/en/master/usage/quickstart.html
Bonus: Sphinx Good-to-Know
****************************************************************************************
The ``conf.py`` file generated does not have a whole lot left in it anymore, but it's
worth pointing out a couple of important usage features of the ``conf.py`` file that are
not immediately obvious until you start working.
Where do Magic Variables Come From?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Any variable listed on :py:mod:`Sphinx Configurations Module <sphinx:conf>` can be added
to this ``conf.py`` file. There are a **lot** of options available to you, it's worth
taking a scroll through to see what kind of customization can be done! For example, see
the docs on :confval:`sphinx:rst_epilog` -- that makes it so that you could inject your
own custom (and even programmatically defined) substitutions to make life easy.
Do I have to Write reStructuredText?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**No**, this is not a requirement. However, it needs to be enabled in your project
since Exhale generates ``.rst`` documents. You will want to modify the
:confval:`sphinx:source_suffix` value in ``conf.py`` to include markdown, if that is
what you want to write in. You may also be interested in looking at
`MyST <https://myst-parser.readthedocs.io/en/latest/sphinx/intro.html>`_ if you want to
write in markdown, but need to call "directives". These -- directives -- are what
Exhale needs to do its thing.
.. _setup_app:
WTF is ``setup(app)``?!
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
One of my most favorite, but not very well documented, features of ``conf.py`` is that
effectively **every** sphinx project is a Sphinx Extension of sorts. At the bottom of
your ``conf.py`` file, if you add a magic ``def setup(app):`` method then you will be
able to do all sorts of things like adding custom `"roles"`__ or "directives". The main
point is that ``app`` is going to be a :class:`~sphinx:sphinx.application.Sphinx`
instance so any method there is fair game.
__ https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html
Noting that in recent times, adding a custom ``_static/custom.css`` file or
``_static/super_hack.js`` file has become easier via the
:confval:`sphinx:html_css_files` and :confval:`sphinx:html_js_files`, this example is
just to demonstrate that using those configuration values could also be accomplished
like this:
.. code-block:: py
# See discussion above about html_static_path, let's assume that the files
# docs/_static/custom.css and docs/_static/super_hack.js exist.
html_static_path = ["_static"]
# ... other configurations ...
def setup(app):
app.add_css_file("custom.css")
app.add_js_file("super_hack.js", async="async")
In most cases, you won't really have a need for the ``setup(app)`` method, but as soon
as you want to do anything beyond what the default configurations in Sphinx allow,
you'll be able to do it in this method.
Setup the Extensions in ``conf.py``
----------------------------------------------------------------------------------------
Assuming your Doxygen documentation is in order, and you already have your Sphinx
project ready to go, we need to configure the Breathe and Exhale extensions. For this
guide I assume the following directory structure::
my_project/
│
├── docs/
│ ├── conf.py
│ └── index.rst
│
├── include/
│ └── common.hpp
│
└── src/
└── common.cpp
This structure is not required, but you'll need to change values accordingly.
.. warning::
When using *relative* paths, these are always relative to ``conf.py``. In the above
structure I do **not** have a "separate source and build directory" from Sphinx. If
you do, make sure you are using the correct paths.
.. code-block:: py
# The `extensions` list should already be in here from `sphinx-quickstart`
extensions = [
# there may be others here already, e.g. 'sphinx.ext.mathjax'
'breathe',
'exhale'
]
# Setup the breathe extension
breathe_projects = {
"My Project": "./_doxygen/xml"
}
breathe_default_project = "My Project"
# Setup the exhale extension
exhale_args = {
# These arguments are required
"containmentFolder": "./api",
"rootFileName": "library_root.rst",
"doxygenStripFromPath": "..",
# Heavily encouraged optional argument (see docs)
"rootFileTitle": "Library API",
# Suggested optional arguments
"createTreeView": True,
# TIP: if using the sphinx-bootstrap-theme, you need
# "treeViewIsBootstrap": True,
"exhaleExecutesDoxygen": True,
"exhaleDoxygenStdin": "INPUT = ../include"
}
# Tell sphinx what the primary language being documented is.
primary_domain = 'cpp'
# Tell sphinx what the pygments highlight language should be.
highlight_language = 'cpp'
With the above settings, Exhale would produce the ``docs/api`` folder, the file
``docs/api/library_root.rst`` (among many others), and it would use Doxygen to parse
``docs/../include`` and save the output in ``docs/_doxygen``. Meaning the following
structure would be created::
my_project/
├── docs/
│ ├── api/
│ │ └── library_root.rst
│ │
│ ├── conf.py
│ ├── index.rst
│ │
│ └── _doxygen/
│ └── xml/
│ └── index.xml
│
├── include/
│ └── common.hpp
│
└── src/
└── common.cpp
.. note::
You are by no means required to use Exhale to generate Doxygen. If you choose not to
I assume you have the wherewithal to figure it out on your own. See also the
:ref:`setup_app` section, in that method would be a good place to invoke doxygen.
Or use CMake. Or whatever.
Make Your Documentation Link to the Generated API
----------------------------------------------------------------------------------------
So the final step is, in your ``index.rst`` or some other ``toctree`` directive, tell
Sphinx to link in the generated ``"{containmentFolder}/{rootFileName}"`` document:
.. raw:: html
<div class="highlight-rest">
<div class="highlight">
<pre>
.. toctree::
:maxdepth: 2
about
<b>api/library_root</b></pre>
</div>
</div>
.. _quickstart_clean_target:
Optional: Create a Proper Clean Target
----------------------------------------------------------------------------------------
The ``sphinx-quickstart`` utility will create a ``Makefile`` for you, you are advised
to create an *explicit* ``clean`` target that removes the generated utilities.
1. You can just as easily specify to ``breathe_projects`` a path such as
``_build/_doxygen/xml``, or ``../build/_doxygen/xml`` if you have separate source
and build directories. This will ensure that a ``make clean`` will delete these.
To avoid confusing users who are new to Sphinx, I encourage something in the same
directory as ``conf.py`` for simplicity.
2. The generated API **must** appear in the Sphinx source directory. If you put it
under ``_build``, it will not get parsed.
So bust out the ``Makefile`` provided by Sphinx Quickstart and add ``clean`` to the
``.PHONY`` line, and the ``clean`` target as shown below (assuming you've been using
the paths specified above):
.. code-block:: make
.PHONY: help Makefile clean
clean:
rm -rf _doxygen/ api/
@$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.. danger::
``make`` **requires** ``TAB`` characters! If you just copy-pasted that, **you got
space characters** (sorry).
.. note::
The above code **must** appear **before** the ``%: Makefile`` "catch-all" target that
Sphinx produced by default. Otherwise...well the catch-all target catches all!
Hosting your Documentation Online
----------------------------------------------------------------------------------------
Now that you have a sphinx project able to build your documentation, you will want to
find a home to host your project online. If you just want to get documentation out
the door, try `Read the Docs <https://docs.readthedocs.io/en/stable/tutorial/>`_. You
can also do something like `GitHub Pages <https://pages.github.com/>`_, but that process
is a little bit more involved since you'll need to deploy to a ``gh-pages`` branch.
Search online for ``sphinx github pages``, hopefully over time somebody will create a
better GitHub action that allows e.g., versioned hosting of docs.
|