This directory contains the source for PyTorch's C++ API documentation, built with Sphinx, Breathe, and Doxygen.
The documentation pipeline has three stages:
C++ headers ──→ Doxygen ──→ XML ──→ Breathe ──→ Sphinx ──→ HTML
↑ ↑
Doxyfile Markdown files with
(which headers) Breathe directives (MyST)
- Doxygen reads C++ headers listed in
source/DoxyfileINPUTand produces XML inbuild/xml/. - Breathe is a Sphinx extension that reads Doxygen XML and makes it available
via directives like
```{doxygenclass} ClassName(MyST Markdown syntax). - Sphinx builds the final HTML from
.mdfiles insource/, using Breathe directives to pull in C++ API documentation. Themyst_parserextension enables Markdown support.
Only headers listed in the Doxyfile's INPUT are processed. Source files must
explicitly reference each symbol — nothing is auto-generated.
make html # Build Doxygen XML + Sphinx HTML
make doxygen # Build Doxygen XML only
make clean # Clean build artifactsThe output is in build/html/.
-
Ensure the header is in the Doxyfile — check that
source/DoxyfileINPUTincludes the header file or its parent directory. If not, add it:INPUT = ... \ ../../../path/to/your/header.h -
Add a Breathe directive to the appropriate
.mdfile undersource/api/. See Which directive to use below. -
Run
make htmland check the output inbuild/html/. -
Run
python check_coverage.pyto verify your API shows as documented.
Use Breathe directives to pull documentation from Doxygen XML. These render the full C++ signature, doc comments, parameters, and members automatically.
All source files use MyST Markdown syntax (fenced directives with backticks).
Classes and structs — use doxygenclass or doxygenstruct:
```{doxygenclass} torch::nn::Linear
:members:
:undoc-members:
```:members:shows all public member functions and variables:undoc-members:includes members without doc comments- Omit both flags to show only the class description (useful when
:members:causes rendering issues)
Free functions — use doxygenfunction:
```{doxygenfunction} torch::autograd::grad
```For overloaded functions, Breathe will document all overloads.
Macros — use doxygendefine:
```{doxygendefine} TORCH_LIBRARY
```Typedefs — use doxygentypedef:
```{doxygentypedef} torch::DeviceType
```Some symbols can't be documented with Breathe directives:
-
TORCH_MODULE holder classes (e.g.,
Conv2d,Linear): TheTORCH_MODULE()macro generates these, but Doxygen can't index them. Document the*Implclass instead (e.g.,Conv2dImpl) — it contains all the actual methods. -
Functions with broken
\rst/\endrstblocks: Some doc comments use Doxygen's\rstalias to embed RST. When a comment has multiple such blocks, Doxygen generates malformed XML and Breathe renders raw text. In these cases, either:- Fix the header to use native Doxygen (
@code{.cpp}/@endcode,@note,@warning) instead of\rst/\endrst - Use a hand-written Sphinx C++ domain directive as a fallback
- Fix the header to use native Doxygen (
-
Functions with mismatched
\paramnames: If a header's\paramnames don't match the actual parameter names, Doxygen may fail to index the function. Use a hand-writtencpp:functiondirective instead.
Hand-written Sphinx C++ domain directives (fallback):
```{cpp:function} void torch::autograd::backward(const variable_list& tensors, const variable_list& grad_tensors = {}, std::optional<bool> retain_graph = std::nullopt, bool create_graph = false, const variable_list& inputs = {})
Computes gradients of given tensors with respect to graph leaves.
:param tensors: Tensors of which the derivative will be computed.
:param grad_tensors: The "vector" in the Jacobian-vector product.
```These don't pull from Doxygen — you write the signature and docs manually.
{eval-rst} escape hatch — if a MyST directive doesn't render correctly,
you can embed raw RST:
```{eval-rst}
.. doxygenclass:: X::A
:members:
:protected-members:
:private-members:
```Each .md file under source/api/ documents one topic area using MyST Markdown.
The typical pattern:
# Page Title
Brief description of this API area.
## Section Name
Optional prose explaining usage, with a code example:
```cpp
#include <torch/torch.h>
auto x = torch::randn({2, 3});
```
```{doxygenclass} torch::nn::SomeClass
:members:
:undoc-members:
```
```{doxygenstruct} torch::nn::SomeClassOptions
:members:
:undoc-members:
```Nesting directives: When a directive contains other directives or code blocks, the outer fence must use more backticks than the inner ones:
````{cpp:class} at::Tensor
The primary tensor class.
```{cpp:function} int64_t dim() const
Returns the number of dimensions.
```
````Doxygen extracts documentation from comments in headers. Use /// style:
/// Applies a linear transformation to the incoming data: :math:`y = xA^T + b`.
///
/// @code{.cpp}
/// auto linear = torch::nn::Linear(torch::nn::LinearOptions(10, 5));
/// auto output = linear->forward(input);
/// @endcode
///
/// @note The weight matrix is transposed compared to the Python API.
class LinearImpl : public Cloneable<LinearImpl> {Preferred Doxygen commands:
@code{.cpp}/@endcodefor code examples@notefor important notes@warningfor warnings@param namefor parameter descriptions@returnfor return value descriptions
Avoid \rst / \endrst blocks — they cause rendering issues when a single
doc comment contains multiple blocks. Use native Doxygen commands instead.
make coverage # Build docs + run coverage check
make coverage-only # Run coverage check without rebuildingcheck_coverage.py auto-discovers public APIs from Doxygen XML (build/xml/index.xml)
and checks which ones have Breathe or Sphinx directives in the source files.
Reports are written to cpp_coverage.txt and cpp_html_issues.txt.
The script parses build/xml/index.xml to find all classes, structs, functions,
and macros that Doxygen indexed. It then:
- Filters out internal symbols using
EXCLUDED_PATTERNSandEXCLUDED_SYMBOLS - Re-includes any symbols in
INCLUDED_SYMBOLS(overrides exclusions) - Scans
.mdfiles for Breathe (doxygenclass,doxygenfunction, etc.) and Sphinx C++ domain (cpp:class,cpp:function, etc.) directives - Reports the gap
Not everything in Doxygen XML is public API. The script has three exclusion mechanisms:
EXCLUDED_PATTERNS — regex patterns for broad categories:
EXCLUDED_PATTERNS = [
r".*::detail::.*", # Internal namespaces
r"torch::jit::.*", # Deprecated
r".*::_\w+", # Underscore-prefixed internals
]EXCLUDED_SYMBOLS — exact match for specific symbols:
EXCLUDED_SYMBOLS = {
"torch::autograd::deleteNode",
"at::native::dataSize",
}Doxyfile EXCLUDE — prevents Doxygen from indexing files entirely:
EXCLUDE = ../../../torch/csrc/api/include/torch/detail
Some APIs live in internal-looking namespaces but are widely used by external
developers. To track these for documentation coverage, add them to
INCLUDED_SYMBOLS in check_coverage.py:
INCLUDED_SYMBOLS: set[str] = {
"c10::IValue", # Used for custom op registration
}INCLUDED_SYMBOLS takes priority over all exclusions.
The script also checks built HTML for:
- Unresolved Breathe directives ("Cannot find class/struct/function")
- Raw directive text in output (build failures)
- Sphinx "problematic" nodes (broken references)
- Near-empty API pages
python check_coverage.py --coverxygenThis runs coverxygen on the Doxygen XML to measure what percentage of C++ symbols have doc comments in the source code. This is complementary to file coverage — it tells you which headers need more doc comments, not which symbols need Sphinx directives.
-
\rst/\endrstrendering — Some C++ headers use Doxygen's\rstalias to embed RST in doc comments. When a single doc comment has multiple\rst/\endrstblocks, Doxygen generates malformed XML and Breathe renders them as raw text. Avoid using:members:on classes with this issue. Use hand-written examples in the source files instead, or convert the headers to native Doxygen commands. -
TORCH_MODULE holder classes — Doxygen can't index classes generated by the
TORCH_MODULE()macro. Use the*Implclass name in directives instead. -
"Subclassed by" plain text — Without per-class pages (exhale), Breathe renders "Subclassed by" lists as plain text instead of links. A
conf.pyhook (remove_subclassed_by) strips these automatically.
