4 minutes
Written: 2020-09-22 06:58 +0000
Updated: 2024-08-06 00:52 +0000
Documenting C++ with Doxygen and Sphinx - Exhale
This post is part of the C++ documentation practices series.
This post outlines a basic workflow for C++ projects using Doxygen, Sphinx, and Exhale.
Background
My project proposal for documenting Symengine was recently accepted for the Google Summer of Docs initiative. In the past I have been more than happy to document C++ code using only Doxygen (with pretty fantastic results), while keeping example usage separate (d-SEAMS wiki). Though this is still a feasible method, a monolithic multi-project setup might benefit from Sphinx, which is what will be covered.
Goals
A couple of goals informed this approach:
- We expect our documentation to link to the source files
- We expect a lot of Python developers to contribute
- Hence Sphinx
- We would like to write
.ipynb
files into the docs- Another reason to use Sphinx (via MyST{NB})
Folder Structure
1tree -d $prj/ -L 2
. | ||
---|---|---|
├── | docs | |
│ | ├── | Doxygen |
│ | └── | Sphinx |
├── | nix | |
│ | └── | pkgs |
├── | projects | |
│ | └── | symengine |
└── | scripts | |
8 | directories |
Essentially we have a scripts
directory to store basic build scripts, and two kinds of documentation folders.
Basic Doxygen
The doxygen
setup is beautifully simple:
1cd docs/Doxygen
2doxygen -g
3# Easier to edit
4mv Doxyfile Doxyfile.cfg
Since Doxyfile
should be updated by subsequent versions of doxygen
, it is
best to separate the project settings. We will therefore modify some basic
settings in a separate file
1touch Doxyfile-prj.cfg
2vim Doxyfile-prj.cfg # or whatever
Edit the file to be (minimally):
1@INCLUDE = "./Doxyfile.cfg"
2GENERATE_HTML = NO
3GENERATE_XML = YES
4XML_PROGRAMLISTING = NO
5
6# Project Stuff
7PROJECT_NAME = "myProject"
8PROJECT_BRIEF = "Dev docs"
9OUTPUT_DIRECTORY = "./gen_docs"
10
11# Inputs
12INPUT = "./../../projects/symengine/symengine"
13RECURSIVE = NO
With this we will now be able to obtain the xml
files for the rest of this setup.
Exhale
For our first attempt, we will focus on the automation of Sphinx using the exhale tool.
1# Basic setup
2poetry init
3poetry add exhale breathe
Now we can generate the basic Sphinx structure.
1# Separate source and build
2sphinx-quickstart --sep --makefile docs/Sphinx \
3 --project "My Proj" \
4 --author "Juurj" \
5 --release "latest" \
6 --language "en"
This allows us to generate the Sphinx documentation we require, with some changes to the docs/Sphinx/source/config.py
file (lifted from the exhale documentation):
1extensions = [
2 'breathe',
3 'exhale',
4]
5
6# -- Exhale configuration ---------------------------------------------------
7# Setup the breathe extension
8breathe_projects = {
9 "My Proj": "./../../Doxygen/gen_docs/xml"
10}
11breathe_default_project = "My Proj"
12
13 # Setup the exhale extension
14exhale_args = {
15 # These arguments are required
16 "containmentFolder": "./api",
17 "rootFileName": "library_root.rst",
18 "rootFileTitle": "Library API",
19 "doxygenStripFromPath": "..",
20 # Suggested optional arguments
21 "createTreeView": True,
22 # TIP: if using the sphinx-bootstrap-theme, you need
23 # "treeViewIsBootstrap": True,
24}
25
26# Tell sphinx what the primary language being documented is.
27primary_domain = 'cpp'
28
29# Tell sphinx what the pygments highlight language should be.
30highlight_language = 'cpp'
We also need to add the output to the index.rst
use the following:
1.. toctree::
2 :maxdepth: 2
3 :caption: Contents:
4
5 api/library_root
At this point we are ready to manually build our documentation.
1cd docs/Doxygen
2doxygen Doxyfile-prj.cfg
3cd ../Sphinx
4make html
This is still pretty cumbersome though. We can view our documentation in a more pleasant manner with darkhttpd
.
1darkhttpd docs/Sphinx/build/html
With this we now beautify the documentation (with the sphinx_book_theme):
1poetry add sphinx-book-theme
We need to set the theme as well (in the Sphinx config.py
file):
1html_theme = 'sphinx_book_theme'
This leads to some pretty documentation.
Conclusions
At this point, we have a basic setup, which we can tweak with a bunch of themes, and/or different parsers, but this is still pretty rough around the edges. However, a caveat of this setup is that the actual contents of the source are not visible in the generated documentation. In the next post, we will look at automating this setup for deploying with Travis.
Series info
C++ documentation practices series
- Documenting C++ with Doxygen and Sphinx - Exhale <-- You are here!
- Publishing Doxygen and Sphinx with Nix and Rake