****** Sphinx ****** `Sphinx `_ is a documentation tool that is commonly used for writing code documentation (especially for python projects). It uses `restructured text `_ as the format for writing the documentation and compiles it into HTML, LaTeX/PDF, ... It can also highlight code syntax. .. tip:: These course notes are all written using Sphinx Despite its python origins, `sphinx can be used with Doxygen via Breathe `_ to allow for nice looking sphinx documentation to provide the C++ documentation Doxygen generates. Setting It Up ============= We can install Sphinx locally via: .. prompt:: bash pip3 install sphinx sphinx_rtd_theme breathe --user .. tip:: On the MathLab machines, python 2 is the default, which is why we are using ``pip3`` here, to ensure that we get python 3. .. tip:: For some reason, the MathLab machines don't include ``~/.local/bin`` in your Unix path, so we need to manually add it via: .. prompt:: bash export PATH=~/.local/bin:$PATH Now we want to change our code documentation from our handwritten ``index.html`` to a site generated by Sphinx. We'll take over the ``docs/`` directory: .. prompt:: bash cd docs/ rm index.html Then, in the ``docs/`` directory: .. prompt:: bash sphinx-quickstart Answer the following: * ``Separate source and build directories (y/n) [n]:`` : answer ``y`` * ``Project name:`` : answer "C++ Array" * ``Author names(s):`` : answer "PHY 504" * ``Project release []:`` : just hit enter * ``Project language [en]:`` : just hit enter You should now have the following files: :: build/ make.bat Makefile source/ you can delete ``make.bat``. To test things out, do: .. prompt:: bash make html Then you can view the default page via: .. prompt:: bash google-chrome build/html/index.html Customizing our page ==================== There are two important files in ``source/`` * ``conf.py`` : this controls the configuration of Sphinx * ``index.rst`` : this is the ReST file that will become ``index.rst``. Configuration ------------- Let's start by changing the configuration a bit: * in the ``extensions`` section, change it to read: .. code:: python extensions = ["breathe"] * change ``html_theme`` to be: .. code:: python html_theme = "sphinx_rtd_theme" Index ----- Let's have the ``index.rst`` page link to a page showing how the library works. Create a file ``using.rst`` with the following content: .. code:: ReST *********** Using Array *********** ``Array.H`` provides a simple 2-d contiguous array. We can use it as: .. code:: c++ #include #include "array.H" int main() { // create a 10x10 array Array x(10, 10); for (std::size_t row=0; row < x.nrows(); ++row) { for (std::size_t col=0; col < x.ncols(); ++col) { x(row, col) = static_cast (10*row + 100*col + 13); } } std::cout << x << std::endl; std::cout << "x.min() = " << x.min() << std::endl; // create a 4x3 array but fill it by looping over a flattened // view Array y(4, 3); double c{0}; for (auto &e : y.flat()) { e = c; c += 1; } std::cout << y << std::endl; Then add to ``index.rst`` just after the contents ``using``, so it reads like: .. code:: ReST .. toctree:: :maxdepth: 2 :caption: Contents: using Let's add what we've do so far to our git: .. prompt:: bash git add Makefile source/conf.py source/index.rst source/using.rst git commit We now need to change our GitHub action to build this new site and copy it over to the ``gh-pages`` branch. In the ``.github/workflows/gh-pages.yml`` file, change the sections: .. code:: yaml - name: Build Doxygen run: | mkdir docs doxygen Doxyfile - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs keep_files: true to .. code:: yaml - name: Build Sphinx run: | cd docs make html cd .. mkdir -p out mv docs/build/html/* out/ - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./out keep_files: true This does 3 things: * It switches to building the sphinx pages via ``make html`` * It creates a top-level directory called ``out/`` and puts all of the web site there * It instructs the "Deploy" process to copy ``out`` to ``gh-pages`` now .. tip:: Commit and push these changes and in a minute or two, the project webpage should be regenerated to reflect the Sphinx layout. Using Doxygen with Sphinx ========================= Now we'll try to combine Doxygen and Sphinx. .. tip:: The Sphinx *breathe* extension allows us to incorporate Doxygen documentation into Sphinx sites. 1. Move ``Doxyfile`` into ``docs/`` and change the following: * change ``OUTPUT_DIRECTORY`` to ``doxy_files`` * change ``INPUT`` to ``../`` * Turn off HTML and turn on XML---Breathe works off of the XML output. 2. Update our ``conf.py`` to include Breathe and also run Doxygen for us. Here's the updated ``conf.py``: .. code:: python # Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) import subprocess # run doyxgen subprocess.call("cd ..; doxygen", shell=True) # -- Project information ----------------------------------------------------- project = 'C++ Array' copyright = '2022, PHY 504' author = 'PHY 504' # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = ["sphinx.ext.autodoc", "breathe"] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] breathe_projects = { "cxx_array": "../doxy_files/xml/" } breathe_default_project = "cxx_array" 3. Create a ``doxygen_files.rst`` in ``source/`` with the following: .. code:: ReST Doxygen Files ============= .. doxygenindex:: :project: cxx_array 4. Update ``index.rst`` by adding the following: .. code:: ReST .. toctree:: :maxdepth: 1 :caption: API doxygen_files We don't need to do any changes to our GitHub workflow. We should be able to just add these new files / changes, commit, and push, and the website will be updated.