How the Omniverse Documentation System Works

Omniverse’s documentation system is built on the following technologies:

Technology

Purpose

reStructuredText

reStructuredText is an easy-to-read, what-you-see-is-what-you-get plaintext markup syntax. Defined in PEP 287.

Docutils

Python library for converting reStructuredText into a graph representation and outputting HTML.

Sphinx

Python build tool which utilizes Docutils to convert reStructuredText to HTML. Supports themes and extensions that make customizing Docutils’ output easier.

Doxygen

Markup and build tool for embedding and extracting API documetation in C++. Converts C++ documentation to XML.

Breathe

Sphinx extension that can convert Doxygen’s XML output into individual reStructuredText directives (e.g. enables directives to show the documentation for a given function, class, marco, etc).

Exhale

Sphinx extension that uses Doxygen’s XML output to create a coherent set of reStructuredText pages to document an entire API. Uses Breathe.

Markdown

Popular light-weight, human readable markup for creating structured text. Supported by Doxygen’s markup.

repo_man

Omniverse framework for defining shared repository tools.

repo_docs

repo_man tool to download, configure, and invoke the Omniverse documentation tool chain.

packman

NVIDIA packaging and dependency management system. The main way Omniverse shares and ships code between components.

sphinx-build

packman package which contains Omniverse specific forks of Docutils, Sphinx, Breathe, Exhale, and other Sphinx extensions.

The following document provides an overview on how these technologies are linked with the Omniverse documentation system.

The documentation system has three primary customers:

  • Repository owners

  • Developers documenting Omniverse

  • Users reading documentation

Let’s take a bottom-up approach to how the system works.

Repository Owners

Enabling the Omniverse documentation system in a new repository is easy. Assuming the repository is managing its dependencies via packman, the first step is to add a dependency on repo_docs by adding the following entry in the repository’s deps/repo-deps.packman.xml:

<dependency name="repo_docs" linkPath="../_repo/deps/repo_docs">
  <package name="repo_docs" version="0.1.0" />
</dependency>

Next, assuming the repository uses repo_man to manage the repository’s tool chain, the following entries can be added to the repository’s repo.toml:

[repo_docs]

enabled = true

# the name of you project.  should be a single word. used to name files.
short_name = "carbonite"

# a slightly more descriptive name for your project. user visible. keep it short.
long_name = "Carbonite SDK"

# first year in your projects copyright.
copyright_start = 2018

Finally, add an index.rst to the root of the repository.

That’s it. The repository owner doesn’t have to worry about CSS, logos, or output directories. The defaults generally do the right thing.

repo_docs has other configuration settings the repo owner can tweak to customize the output, but overall, the default output will have a look-and-feel that matches the overall Omniverse documentation.

Developers

Developers will generally author two types of documentation:

  • API documentation. This is usually embedded in .h and .py files.

  • Overview documentation. The is usually found in .rst files but also .md files.

Most overview documentation is stored in the repository’s docs/ directory. To extract a .h file’s documentation, the developer must add an entry to repo.toml. For example:

# list of files from which to extract documentation.  if a directory is specified,
# it will be recursively searched. defaults to an empty list.
doxygen_input = [
    "include/carb/Framework.h",
    "include/carb/Interface.h",
    "include/carb/PluginCoreUtils.h",
    "include/carb/PluginUtils.h",
    "include/carb/StartupUtils.h",
    "source/examples/example.doxygen/ExampleDoxygen.h",
]

A Python module’s docstrings can be extracted by adding its directory to repo.toml. For example:

# path to .py and .pyd files whose docstring should be extracted. defaults to an
# empty list
python_paths = [
    "${root}/_build/${platform_target}/${config}/bindings-python"
]

To build the docs, the developer simply types:

repo docs

The output will appear in _docs/index.html.

What Happens When You Type repo docs

repo docs invokes the repo script, which is a simple script that uses packman to bootstrap the repo tools. This downloads packman and any repo_man tools specified by the repository owner. One of these tools will be repo_docs. Once the repo_docs package is downloaded, its main entry point is invoked.

When repo_docs is invoked, repo_man provides it with the parsed contents of repo.toml. repo_docs uses the contents of repo.toml, plus any arguments provided to repo, to determine which actions it should perform. By default, repo_docs does the following:

  • Clean the output directory

  • Download (via packman) and run Doxygen (if enabled)

  • Download NVIDIA’s sphinx-build packman package. This contains Docutils, Sphinx and all of the Sphinx extensions needed to build Ominverse’s documentation.

  • Runs Sphinx. This will invoke both the Breathe and Exhale extensions if configured by the repository.

How Overview Documentation is Processed

Any .rst or .md document found in the repository is assumed to be input to Sphinx. Files can be excluded via repo.toml as follows:

sphinx_exclude_patterns = [
    "docs/rfcs/*"
    "tools/*",
]

How C++ Documentation is Processed

C++ documentation can be extracted by specifying the C++ source in repo.toml:

# list of files from which to extract documentation.  if a directory is specified,
# it will be recursively searched. defaults to an empty list.
doxygen_input = [
    "include/carb/Framework.h",
    "include/carb/Interface.h",
    "include/carb/PluginCoreUtils.h",
    "include/carb/PluginUtils.h",
    "include/carb/StartupUtils.h",
    "source/examples/example.doxygen/ExampleDoxygen.h",
]

The files specified above are processed with Doxygen. repo_docs instructs Doxygen to produce a series of XML files describing the API’s documentation.

The XML output is then given to Exhale. Exhale iterates over each class, file, namespace, function, marco, etc. and writes a series of unique .rst files. Exhale also produces an “overview” page from which most entities can be easily accessed.

repo_docs also provides Breathe with a pointer to Doxygen’s XML output. Breathe uses this to create a list of directives that can used throughout the documentation to inline a Doxygen entity’s docs. For example:

:cpp:struct:`carb::Framework`

The .rst files that Exhale outputs rely on the directives provided by Breathe.

It’s important to note that Omniverse has made several modification to Exhale to mold its output to Omniverse’s needs. For example, code exists to streamline the documentation of Omniverse Native Interfaces.

How Python Documentation is Processed

A Python module’s docstrings can be extracted by adding its directory to repo.toml. For example:

# path to .py and .pyd files whose docstring should be extracted. defaults to an
# empty list
python_paths = [
    "${root}/_build/${platform_target}/${config}/bindings-python"
]

reStrucutredText, Docutils, and Sphinx all come from the Python community, so setup is generally completed without drama.

How Styling Happens

Styling is controlled by repo_docs, which relies heavily on Sphinx’s theme system. The base theme used is sphinx_rtd_theme, though Omniverse has made extensive style changes via repo_docs media/omni-style.css.

Users

Users fall into two buckets:

  • Customers

  • Documentation reviewers

The customer experience is self-explanatory. Check out: https://docs.omniverse.nvidia.com/.

Documentation reviewers have a harder job. During code review, they must translate .rst, .md, .h, and .py into customer visible documentation. Here, the repository owner can be a great benefit.

When reviewing code via Omnivere’s CI/CD system, hooks can be added to:

  • Ensure the documentation is built

  • Publish the built documentation to a temporary website for review

The latter point is important, as it allows reviewers to see the “final” output.

Reach out to bnaji@nvidia.com for details.