Parse Doxygen-documented C++ with libclang and generate MyST Markdown API docs for Sphinx
Project description
clangquill
Parse Doxygen-documented C++ with libclang and generate MyST Markdown API docs for Sphinx.
clangquill reads your C++ headers with libclang,
extracts classes, functions, namespaces, enums and their documentation comments
into a SQLite intermediate representation, and renders MyST
Markdown pages. Every symbol becomes a real
Sphinx C++ domain object ({cpp:class}, {cpp:function}, …) — so the generated
API appears in objects.inv and cross-references like any hand-written page,
with inter-symbol links resolved through {cpp:any}.
Features
- libclang-based parsing of real C++ (
c++20/c++23/c++26), including Doxygen comments andcompile_commands.jsonsupport. - First-class Sphinx integration — output is MyST Markdown backed by the Sphinx C++ domain, so symbols cross-reference and show up in the search index.
- Three front-ends for the same pipeline: a Sphinx extension, a
clangquillCLI, and a Python API. - Incremental builds — a persistent SQLite IR plus a hash cache skip re-parsing unchanged inputs, rewrite only pages whose content changed, and delete pages for symbols that disappeared.
- Customizable output via per-kind Jinja2 templates you can override one file at a time.
- Choosable page layout (
clangquill_group_by): one page persymbol, perfile, perclass, or a browsablenamespacehierarchy (see below). - Pluggable comment parsers (Doxygen by default).
Installation
clangquill is published on PyPI. Install it with uv:
uv pip install clangquill
(Plain pip install clangquill works too.)
The Linux wheels bundle a self-contained libclang 22 from the official LLVM release, so parsing works out of the box with no system LLVM required. That bundled libclang needs glibc ≥ 2.34 (manylinux_2_34); on older distributions, build from source against your own libclang instead.
Quick start
Sphinx extension
For the common case you do not need to drive the parser yourself: enable the bundled extension and it runs the whole pipeline — parse → SQLite → MyST — at build time, regenerating pages into your source tree before Sphinx reads them.
# conf.py
extensions = ["clangquill.sphinx_ext"] # pulls in myst_parser automatically
clangquill_input = ["../include/**/*.hpp"]
clangquill_output_dir = "api" # written under the Sphinx srcdir
clangquill_std = "c++20"
clangquill_include_dirs = ["../include"]
Then reference the generated toctree from your root document:
```{toctree}
api/index
```
Every knob is a clangquill_* config value mirroring a field of
clangquill.config.Config — including clangquill_compile_commands,
clangquill_template_dirs, clangquill_include_undocumented,
clangquill_comment_parser and clangquill_group_by. See the
configuration guide
for the full reference.
Command line
The same pipeline is available standalone, handy for previewing output or wiring clangquill into a non-Sphinx build:
$ clangquill build include/geo.hpp -o docs/api --std c++20 -I include
Parsed 7 symbol(s) from 1 file(s).
Wrote 1 page(s) to /path/to/docs/api.
Run clangquill build --help for the full set of options, which mirror the
clangquill_* config values.
Python API
Once a project has been parsed into the SQLite IR, the generator renders it into
MyST Markdown: one page per top-level symbol plus an index.md toctree.
from clangquill.generator import Generator
from clangquill.store import Store
with Store.open("api.sqlite") as store:
Generator(store).generate("docs/api")
Page layout
clangquill_group_by (CLI --group-by, API generate(group_by=...)) chooses how
symbols are partitioned into pages:
symbol(default) — one page per top-level symbol. A single root namespace collapses its whole subtree onto one page.file— one page per parsed source file.class— one page per documented class/namespace. Splits a colossal namespace into a page per member class, but the rootindexstill lists every page in one flat toctree.namespace— a browsable hierarchy. The rootindexlinks only the top-level namespaces; each namespace gets a navigational hub page whose toctree links its sub-namespaces, one page per class, one page per free-function name (overloads together), a single lumped operators page, and grouped types (enums/typedefs/aliases/concepts) and constants (variables/macros) pages. Best for large libraries where a flat index would be unreadable: you drill down all namespaces → everything in a namespace → individual class/function pages.
Incremental builds
Set clangquill_cache_dir (or the matching CLI/API option) to make rebuilds
incremental. clangquill keeps the SQLite IR and a small bookkeeping cache between
runs and:
- skips the parse when no input — or transitively
#included header — changed, reusing the cached IR instead of invoking libclang again; - rewrites only the pages whose content changed; and
- deletes pages whose symbols disappeared.
Without a cache directory the build is stateless: it re-parses into a throwaway database and rewrites every page each time.
Templates
Templates are the customization point. The Jinja environment looks up
{kind}.md.jinja (e.g. class.md.jinja, function.md.jinja) in your own
template directories before the bundled defaults, so dropping in a file of the
same name overrides just that kind:
Generator(store, template_dirs=["my_templates"]).generate("docs/api")
See the templates guide for the available templates and context variables.
Building from source
clangquill ships a compiled C++ core (clangquill._core) built with
scikit-build-core, CMake and
nanobind. A standard install builds it:
uv pip install .
uv run python -c "from clangquill import _core; print(_core.have_libclang())"
The core optionally links libclang; when libclang-dev (or an LLVM prefix
via LibClang_ROOT) is available at build time the extraction backend is
enabled. Pass -DCLANGQUILL_WITH_LIBCLANG=ON to require it.
Documentation
- Usage — generator, Sphinx extension, CLI and incremental builds
- Installation
- Configuration reference
- Templates
- Comment parsers
Contributing
Contributions are welcome — see CONTRIBUTING.md. In short:
uv sync --extra dev
uvx pre-commit install
uv run pytest # Python test suite
make cpp-test # C++ (Catch2) unit tests
License
clangquill is released under the BSD 2-Clause License — see LICENSE. The Linux wheels additionally bundle libclang, distributed under the Apache-2.0 WITH LLVM-exception license.
Credits
This package was created with Cookiecutter and the renefritze/python_cookiecutter project template.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clangquill-0.6.1.tar.gz.
File metadata
- Download URL: clangquill-0.6.1.tar.gz
- Upload date:
- Size: 1.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d084a384b4f6e1ecd180840ff94a800a21dda1e124be5b9cc6edfc81bf84b5c
|
|
| MD5 |
bf8c0d041411655b26a0d8ce32fbaf1b
|
|
| BLAKE2b-256 |
7994d4c8780081c2aaf53d4e8934eb69d093eadec4d0f23a8f4d0382ac1062b3
|
Provenance
The following attestation bundles were made for clangquill-0.6.1.tar.gz:
Publisher:
deploy.yml on renefritze/clangquill
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clangquill-0.6.1.tar.gz -
Subject digest:
4d084a384b4f6e1ecd180840ff94a800a21dda1e124be5b9cc6edfc81bf84b5c - Sigstore transparency entry: 1942065413
- Sigstore integration time:
-
Permalink:
renefritze/clangquill@ec2d4d0d899487eaa23c9e24bdfe5000e9f6ca23 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/renefritze
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy.yml@ec2d4d0d899487eaa23c9e24bdfe5000e9f6ca23 -
Trigger Event:
release
-
Statement type:
File details
Details for the file clangquill-0.6.1-cp313-cp313-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: clangquill-0.6.1-cp313-cp313-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 60.6 MB
- Tags: CPython 3.13, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a75ea1d6c4d197517847b73c0c5ec019c17db4aa81ae2285ca446d10f6d6b58
|
|
| MD5 |
c58d8befde06df5dea09ea90e43ae262
|
|
| BLAKE2b-256 |
938ee380d371ce1a7e25e0b397f0dbc62fd151a97fb450ca685124d164de7d29
|
Provenance
The following attestation bundles were made for clangquill-0.6.1-cp313-cp313-manylinux_2_34_x86_64.whl:
Publisher:
deploy.yml on renefritze/clangquill
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clangquill-0.6.1-cp313-cp313-manylinux_2_34_x86_64.whl -
Subject digest:
7a75ea1d6c4d197517847b73c0c5ec019c17db4aa81ae2285ca446d10f6d6b58 - Sigstore transparency entry: 1942065508
- Sigstore integration time:
-
Permalink:
renefritze/clangquill@ec2d4d0d899487eaa23c9e24bdfe5000e9f6ca23 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/renefritze
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy.yml@ec2d4d0d899487eaa23c9e24bdfe5000e9f6ca23 -
Trigger Event:
release
-
Statement type:
File details
Details for the file clangquill-0.6.1-cp313-cp313-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: clangquill-0.6.1-cp313-cp313-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 56.9 MB
- Tags: CPython 3.13, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31867555cc9c6a5394c7882249fa55ed8dbff020f41502853b3b64ab15d331d1
|
|
| MD5 |
8f7fcdda412ba1d1111989ef36067c83
|
|
| BLAKE2b-256 |
a1da4a1f6dbb78ab1a56c3802111ee0e7aa97a024755ecb6c5eee8ab96a3b215
|
Provenance
The following attestation bundles were made for clangquill-0.6.1-cp313-cp313-manylinux_2_34_aarch64.whl:
Publisher:
deploy.yml on renefritze/clangquill
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clangquill-0.6.1-cp313-cp313-manylinux_2_34_aarch64.whl -
Subject digest:
31867555cc9c6a5394c7882249fa55ed8dbff020f41502853b3b64ab15d331d1 - Sigstore transparency entry: 1942065581
- Sigstore integration time:
-
Permalink:
renefritze/clangquill@ec2d4d0d899487eaa23c9e24bdfe5000e9f6ca23 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/renefritze
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy.yml@ec2d4d0d899487eaa23c9e24bdfe5000e9f6ca23 -
Trigger Event:
release
-
Statement type: