Using Intersphinx

The Sphinx intersphinx extension is exceptionally convenient, and typically works out-of-the-box for most projects you would want to link to. This is not limited to linking to documents just within your domain, and if you really want to go the extra mile (and create your own mapping), it doesn’t even have to be restricted to linking to documentation that was generated with Sphinx.

Setup your conf.py

First, how you link to things depends on what your domain is. In the Exhale Quickstart Guide, I encouraged you to add these lines to your conf.py:

# Tell sphinx what the primary language being documented is.
primary_domain = 'cpp'

# Tell sphinx what the pygments highlight language should be.
highlight_language = 'cpp'

This will come up in the next section, but is added to conf.py so it is included here.

For this ExhaleCompanion project, I want to link to two Sphinx generated projects. In the conf.py, this means that I have:

# In addition to `breathe` and `exhale`, use the `intersphinx` extension
extensions = [
    'sphinx.ext.intersphinx',
    'breathe',
    'exhale'
]

# Specify the baseurls for the projects I want to link to
intersphinx_mapping = {
    'exhale':  ('https://exhale.readthedocs.io/en/latest/', None),
    'nanogui': ('http://nanogui.readthedocs.io/en/latest/', None)
}

Linking to Other Sites Using Intersphinx

This is where understanding your primary domain becomes particularly relevant. Since the primary_domain for this project is cpp, I can link to things like :cpp:function: as just :function:. But if I want to link to Python or C domains I need to specify that explicitly. Inlined from the Cross Referencing Syntax docs, there is some syntax you will likely need to wield:

  • You may supply an explicit title and reference target: :role:`title <target>` will refer to target, but the link text will be title.

  • If you prefix the content with !, no reference/hyperlink will be created.

  • If you prefix the content with ~, the link text will only be the last component of the target. For example, :py:meth:`~Queue.Queue.get` will refer to Queue.Queue.get but only display get as the link text.

Linking to Python Docs from a cpp Project

Since I’ve setup intersphinx to point back to the main Exhale site, I’ll just link to some from there.

Linking to a Python Class
:py:class:`exhale.graph.ExhaleRoot`

Links to exhale.graph.ExhaleRoot

:py:class:`graph.ExhaleRoot <exhale.graph.ExhaleRoot>`

Links to graph.ExhaleRoot

:py:class:`~exhale.graph.ExhaleRoot`

Links to ExhaleRoot

Linking to a Python Function
:py:func:`exhale.deploy.explode`

Links to exhale.deploy.explode()

:py:func:`deploy.explode <exhale.deploy.explode>`

Links to deploy.explode

:py:func:`~exhale.deploy.explode`

Links to explode()

Linking to Another C++ Project

This is where understanding how to manipulate the link titles becomes relevant. I’ll use the NanoGUI docs since I stole the NAMESPACE_BEGIN macro from there.

Linking to a C++ Class

Using a single : does not appear to work, but using the namespace::ClassName seems to include a leading :. I think this is a bug, but solving it would likely be treacherous so instead just control the title yourself.

:class:`nanogui::Screen`

Links to :Screen

:class:`nanogui::Screen <nanogui::Screen>`

Links to nanogui::Screen

:class:`~nanogui::Screen`

Links to Screen

Linking to C Domains

Even if the other project is primarily C++, things like macros are in the :c: Sphinx domain. I choose the NAMESPACE_BEGIN example to show you how to qualify where Sphinx should link — both this project and NanoGUI have links to it, so when I just do :c:macro:`NAMESPACE_BEGIN` the link (NAMESPACE_BEGIN) goes to this project. Using nanogui:NAMESPACE_BEGIN (since 'nanogui' was a key in our intersphinx_mapping)

:c:macro:`nanogui:NAMESPACE_BEGIN`

Links to NAMESPACE_BEGIN

:c:macro:`NanoGUI macro NAMESPACE_BEGIN <nanogui:NAMESPACE_BEGIN>`

Links to NanoGUI macro NAMESPACE_BEGIN

:c:macro:`~nanogui:NAMESPACE_BEGIN`

Links to NAMESPACE_BEGIN

Tip

These kinds of cross references are reStructuredText syntax! You must enable the \rst environment for Doxygen (see Doxygen ALIASES) and use this in the documentation. For example, in order to get the NAMESPACE_BEGIN link to work, the actual C++ code is as follows:

#if !defined(NAMESPACE_BEGIN) || defined(DOXYGEN_DOCUMENTATION_BUILD)
    /**
     * \rst
     * See :c:macro:`NanoGUI macro NAMESPACE_BEGIN <nanogui:NAMESPACE_BEGIN>`.
     * \endrst
     */
    #define NAMESPACE_BEGIN(name) namespace name {
#endif