🔝 Retour au Sommaire
Chapitre 46 : Organisation et Standards · Section 46.4 : Documentation — Doxygen et commentaires
Niveau : Expert · Prérequis : Section 46.4.1 (syntaxe Doxygen), chapitre 26 (CMake), chapitre 38 (CI/CD)
Doxygen est disponible dans les dépôts officiels d'Ubuntu. L'installation inclut Doxygen lui-même et Graphviz, utilisé pour générer les diagrammes de classes et les graphes de dépendances :
sudo apt update
sudo apt install doxygen graphviz Vérification de l'installation :
doxygen --version
dot -V # Graphviz Pour obtenir une version plus récente que celle des dépôts (utile pour le support des fonctionnalités C++ les plus récentes), Doxygen peut être compilé depuis les sources ou installé via snap :
sudo snap install doxygenLe Doxyfile est le fichier de configuration de Doxygen. Il contient plusieurs centaines d'options, mais une vingtaine suffisent pour un projet typique. Le reste conserve ses valeurs par défaut.
Doxygen génère un fichier de configuration commenté avec toutes les options :
cd docs/
doxygen -g Doxyfile Le fichier produit fait environ 2500 lignes avec les commentaires. En production, on ne conserve que les options modifiées par rapport aux valeurs par défaut, ce qui réduit le fichier à quelques dizaines de lignes lisibles.
Voici un Doxyfile complet pour un projet professionnel, avec chaque option commentée :
# -----------------------------------------------------------------
# Projet
# -----------------------------------------------------------------
PROJECT_NAME = "MonProjet"
PROJECT_NUMBER = 1.2.0
PROJECT_BRIEF = "Framework de traitement de données en temps réel"
PROJECT_LOGO = docs/logo.png
# -----------------------------------------------------------------
# Entrées
# -----------------------------------------------------------------
# Répertoires à scanner pour le code source et la documentation.
INPUT = include/ \
src/ \
docs/
# Scan récursif des sous-répertoires.
RECURSIVE = YES
# Patterns de fichiers à traiter.
FILE_PATTERNS = *.h *.hpp *.cpp *.md
# Fichiers et répertoires à exclure.
EXCLUDE = build/ \
third_party/
# -----------------------------------------------------------------
# Extraction
# -----------------------------------------------------------------
# Extraire la documentation de tous les membres, même non documentés.
# Utile en développement pour voir les trous dans la documentation.
# À désactiver pour la documentation publique (ne montrer que ce
# qui est explicitement documenté).
EXTRACT_ALL = NO
# Extraire les membres privés (désactivé pour l'API publique).
EXTRACT_PRIVATE = NO
# Extraire les membres statiques.
EXTRACT_STATIC = YES
# -----------------------------------------------------------------
# Comportement des commentaires
# -----------------------------------------------------------------
# La première phrase d'un commentaire sert automatiquement de brief.
JAVADOC_AUTOBRIEF = YES
# Trier les membres par ordre alphabétique dans la documentation.
SORT_MEMBER_DOCS = YES
# -----------------------------------------------------------------
# Sortie
# -----------------------------------------------------------------
# Répertoire de sortie pour la documentation générée.
OUTPUT_DIRECTORY = build/docs
# Générer la sortie HTML (documentation navigable).
GENERATE_HTML = YES
HTML_OUTPUT = html
# Ne pas générer de LaTeX par défaut (activer pour le PDF).
GENERATE_LATEX = NO
# Générer la sortie XML (consommée par Breathe/Sphinx si utilisé).
GENERATE_XML = NO
# -----------------------------------------------------------------
# Apparence HTML
# -----------------------------------------------------------------
# Activer la recherche côté client (JavaScript).
SEARCHENGINE = YES
# Activer la navigation arborescente dans le panneau latéral.
GENERATE_TREEVIEW = YES
# Désactiver le timestamp dans le footer (reproductibilité des builds).
HTML_TIMESTAMP = NO
# Feuille de style personnalisée (optionnel).
# HTML_EXTRA_STYLESHEET = docs/custom.css
# -----------------------------------------------------------------
# Diagrammes (Graphviz)
# -----------------------------------------------------------------
# Activer les diagrammes générés par dot (Graphviz).
HAVE_DOT = YES
# Diagrammes de classes avec héritage.
CLASS_DIAGRAMS = YES
CLASS_GRAPH = YES
# Graphes de collaboration (quelles classes utilisent quelles autres).
COLLABORATION_GRAPH = YES
# Graphes d'inclusion de headers.
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
# Graphes d'appels de fonctions (coûteux sur de gros projets).
CALL_GRAPH = NO
CALLER_GRAPH = NO
# Format de sortie des graphes.
DOT_IMAGE_FORMAT = svg
INTERACTIVE_SVG = YES
# Limiter la profondeur des graphes pour éviter l'explosion.
MAX_DOT_GRAPH_DEPTH = 3
# -----------------------------------------------------------------
# Warnings
# -----------------------------------------------------------------
# Afficher les warnings pour les paramètres non documentés.
WARN_IF_UNDOCUMENTED = YES
# Afficher les warnings pour les commandes Doxygen mal formées.
WARN_IF_DOC_ERROR = YES
# Traiter les warnings comme des erreurs (utile en CI).
# WARN_AS_ERROR = FAIL_ON_WARNINGS
# Fichier de log pour les warnings.
WARN_LOGFILE = build/docs/doxygen_warnings.log
# -----------------------------------------------------------------
# Préprocesseur
# -----------------------------------------------------------------
# Activer le préprocesseur (nécessaire pour les macros).
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
# Macros à prédéfinir pour la documentation.
# Utile pour documenter du code derrière des macros de plateforme.
PREDEFINED = __linux__ \
MONPROJET_EXPORT=Parmi les centaines d'options, quelques-unes méritent une attention particulière car elles changent fondamentalement le résultat produit.
EXTRACT_ALL : quand cette option est à YES, Doxygen documente tous les symboles publics, même ceux sans commentaire Doxygen. C'est utile en phase de développement pour visualiser l'ensemble de l'API et identifier les trous de documentation. Pour la documentation publique d'une bibliothèque, NO est préférable : seuls les symboles explicitement documentés apparaissent, ce qui évite de publier une référence incomplète.
JAVADOC_AUTOBRIEF : à YES, la première phrase de chaque commentaire (jusqu'au premier point) est automatiquement utilisée comme brief. Cela rend l'écriture de commentaires plus naturelle en évitant le @brief explicite sur chaque élément.
WARN_AS_ERROR : la valeur FAIL_ON_WARNINGS fait échouer Doxygen dès qu'un warning est détecté (paramètre non documenté, lien cassé, commande invalide). C'est l'option clé pour l'intégration CI — elle transforme la documentation en un test qui échoue quand la qualité se dégrade.
HAVE_DOT : active la génération de diagrammes via Graphviz. Sans cette option, Doxygen ne produit que des diagrammes textuels basiques. Avec Graphviz, les diagrammes de classes, les graphes d'inclusion et les graphes de collaboration deviennent des SVG interactifs navigables.
La génération de documentation s'exécute en une commande :
doxygen docs/DoxyfileDoxygen affiche sa progression et les éventuels warnings sur la sortie standard. La documentation HTML est générée dans le répertoire spécifié par OUTPUT_DIRECTORY/HTML_OUTPUT — dans notre configuration, build/docs/html/.
Pour visualiser le résultat localement :
# Ouvrir dans le navigateur par défaut
xdg-open build/docs/html/index.html
# Ou servir via un serveur HTTP local
python3 -m http.server 8000 -d build/docs/htmlL'intégration de Doxygen dans CMake permet de générer la documentation via le build system standard du projet, avec une cible dédiée docs.
# docs/CMakeLists.txt
find_package(Doxygen REQUIRED)
if(DOXYGEN_FOUND)
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
add_custom_target(docs
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_IN}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Génération de la documentation Doxygen..."
VERBATIM
)
endif()La documentation est ensuite générée via :
cmake --build build --target docsCMake fournit un module FindDoxygen avec une fonction dédiée, doxygen_add_docs(), qui simplifie l'intégration et permet de surcharger les options du Doxyfile directement depuis CMake :
# docs/CMakeLists.txt
find_package(Doxygen REQUIRED
OPTIONAL_COMPONENTS dot) # Graphviz optionnel
if(DOXYGEN_FOUND)
# Surcharge d'options Doxygen depuis CMake.
# Chaque variable DOXYGEN_XXX correspond à l'option XXX du Doxyfile.
set(DOXYGEN_PROJECT_NAME "${PROJECT_NAME}")
set(DOXYGEN_PROJECT_NUMBER "${PROJECT_VERSION}")
set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doxygen")
set(DOXYGEN_GENERATE_HTML YES)
set(DOXYGEN_GENERATE_LATEX NO)
set(DOXYGEN_GENERATE_TREEVIEW YES)
set(DOXYGEN_JAVADOC_AUTOBRIEF YES)
set(DOXYGEN_EXTRACT_ALL NO)
set(DOXYGEN_WARN_IF_UNDOCUMENTED YES)
set(DOXYGEN_RECURSIVE YES)
# Graphviz
if(DOXYGEN_DOT_FOUND)
set(DOXYGEN_HAVE_DOT YES)
set(DOXYGEN_DOT_IMAGE_FORMAT svg)
set(DOXYGEN_INTERACTIVE_SVG YES)
set(DOXYGEN_CLASS_GRAPH YES)
set(DOXYGEN_COLLABORATION_GRAPH YES)
set(DOXYGEN_INCLUDE_GRAPH YES)
endif()
# Exclusions
set(DOXYGEN_EXCLUDE_PATTERNS
"*/build/*"
"*/third_party/*"
)
# Création de la cible.
# Les arguments sont les répertoires et fichiers à scanner.
doxygen_add_docs(docs
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/docs
COMMENT "Génération de la documentation Doxygen..."
)
endif()L'avantage de cette approche : les valeurs dynamiques du projet (nom, version, chemins) sont injectées automatiquement depuis CMake, sans dupliquer l'information dans le Doxyfile. Un Doxyfile séparé reste nécessaire uniquement si vous avez besoin d'options que doxygen_add_docs() ne couvre pas — dans ce cas, le fichier est passé en option et les variables CMake le complètent.
Pour que la documentation affiche toujours la version courante sans modification manuelle :
# Si vous utilisez un Doxyfile, générez-le avec configure_file
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
@ONLY
)Le fichier Doxyfile.in utilise des substitutions CMake :
# docs/Doxyfile.in
PROJECT_NAME = "@PROJECT_NAME@"
PROJECT_NUMBER = "@PROJECT_VERSION@"
INPUT = @CMAKE_SOURCE_DIR@/include \
@CMAKE_SOURCE_DIR@/src \
@CMAKE_SOURCE_DIR@/docs
OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/doxygenChaque @VARIABLE@ est remplacé par la valeur correspondante de CMake au moment de la configuration. Le Doxyfile généré dans le répertoire de build contient les chemins absolus corrects.
La documentation doit être générée et vérifiée automatiquement à chaque commit. Deux jobs CI distincts couvrent deux objectifs différents : la vérification de qualité et le déploiement.
Ce job s'exécute sur chaque merge request. Il vérifie que la documentation est complète et syntaxiquement correcte :
# .gitlab-ci.yml (extrait)
docs-check:
stage: test
image: ubuntu:24.04
before_script:
- apt-get update && apt-get install -y doxygen graphviz cmake ninja-build g++
script:
- cmake -B build -G Ninja -DBUILD_DOCS=ON
- cmake --build build --target docs
# Vérifier qu'aucun warning n'a été émis
- |
if [ -s build/docs/doxygen_warnings.log ]; then
echo "⚠️ Warnings Doxygen détectés :"
cat build/docs/doxygen_warnings.log
exit 1
fi
artifacts:
when: on_failure
paths:
- build/docs/doxygen_warnings.log
expire_in: 7 daysL'alternative, plus directe, est d'utiliser WARN_AS_ERROR = FAIL_ON_WARNINGS dans le Doxyfile. Doxygen retournera alors un code d'erreur non nul dès qu'un warning est émis, faisant échouer le job CI sans script de vérification supplémentaire.
# .github/workflows/docs.yml
name: Documentation
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
docs-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y doxygen graphviz
- name: Configure
run: cmake -B build -DBUILD_DOCS=ON
- name: Generate documentation
run: cmake --build build --target docs
- name: Check for warnings
run: |
if [ -s build/docs/doxygen_warnings.log ]; then
echo "::error::Doxygen warnings detected"
cat build/docs/doxygen_warnings.log
exit 1
fi
# Déploiement sur GitHub Pages (uniquement sur main)
- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build/docs/doxygen/htmlCe workflow combine vérification (sur chaque PR) et déploiement (sur main uniquement). La documentation est toujours accessible à jour sur GitHub Pages après chaque merge.
GitLab Pages utilise une convention : tout ce qui est dans le répertoire public/ de l'artefact du job pages est servi en tant que site statique.
# .gitlab-ci.yml (extrait)
pages:
stage: deploy
image: ubuntu:24.04
before_script:
- apt-get update && apt-get install -y doxygen graphviz cmake ninja-build g++
script:
- cmake -B build -G Ninja -DBUILD_DOCS=ON
- cmake --build build --target docs
- mv build/docs/doxygen/html public
artifacts:
paths:
- public
only:
- mainAprès exécution, la documentation est accessible à l'URL https://<group>.gitlab.io/<project>/.
Le thème par défaut de Doxygen est fonctionnel mais daté. Plusieurs options permettent de moderniser l'apparence.
La méthode la plus simple consiste à ajouter une feuille CSS qui surcharge le thème par défaut :
# Doxyfile
HTML_EXTRA_STYLESHEET = docs/custom.css/* docs/custom.css */
/* Typographie modernisée */
body, td, th {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, Helvetica, Arial, sans-serif;
font-size: 15px;
line-height: 1.6;
}
/* Blocs de code */
pre.fragment, div.fragment {
font-family: "JetBrains Mono", "Fira Code", "Consolas", monospace;
font-size: 13px;
border-radius: 6px;
border: 1px solid #e0e0e0;
background-color: #f8f9fa;
padding: 12px 16px;
}
/* Navigation latérale */
#side-nav {
background-color: #f5f5f5;
}
/* Liens */
a {
color: #0366d6;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}Le projet open source Doxygen Awesome (doxygen-awesome-css) fournit un thème moderne complet, avec mode sombre, navigation améliorée et design responsive. Son intégration est simple :
# Ajout comme sous-module Git
git submodule add https://github.com/jothepro/doxygen-awesome-css.git \
docs/doxygen-awesome-css# Doxyfile
HTML_EXTRA_STYLESHEET = docs/doxygen-awesome-css/doxygen-awesome.css \
docs/doxygen-awesome-css/doxygen-awesome-sidebar-only.css
# Options recommandées par le thème
GENERATE_TREEVIEW = YES
DISABLE_INDEX = NO
FULL_SIDEBAR = NO
HTML_COLORSTYLE = LIGHT Le résultat est une documentation visuellement comparable aux sites de documentation modernes (à la Read the Docs ou Docusaurus), sans quitter l'écosystème Doxygen.
Doxygen permet de surcharger le HTML d'en-tête et de pied de page pour ajouter un logo, des liens de navigation, ou un analytics tracker :
# Générer les templates par défaut
doxygen -w html header.html footer.html stylesheet.css DoxyfileCela produit trois fichiers dans le répertoire courant. Vous pouvez ensuite les modifier et les référencer dans le Doxyfile :
HTML_HEADER = docs/header.html
HTML_FOOTER = docs/footer.html Pour produire une documentation PDF (souvent requise dans les contextes réglementaires : automobile, aéronautique, défense), Doxygen peut générer du LaTeX compilable en PDF :
# Doxyfile
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
USE_PDFLATEX = YES
PDF_HYPERLINKS = YES La compilation LaTeX nécessite une installation TeX :
sudo apt install texlive-latex-base texlive-latex-extra \
texlive-fonts-recommended latexmkAprès la génération Doxygen, le PDF est produit par :
cd build/docs/latex
make # Appelle pdflatex automatiquement Le fichier refman.pdf est le document de référence complet. Pour les gros projets, la compilation LaTeX peut prendre plusieurs minutes — c'est typiquement un job CI nocturne plutôt qu'un build à chaque commit.
Pour les projets qui ont besoin d'une documentation narrative riche (tutoriels, guides, architecture) mêlée à la référence d'API, la combinaison Sphinx + Breathe offre le meilleur des deux mondes : Doxygen extrait la documentation du code C++, Breathe la rend accessible à Sphinx, et Sphinx produit un site navigable avec un thème moderne.
Code C++ ──Doxygen──► XML ──Breathe──► Sphinx ──► HTML/PDF
▲
Fichiers .rst/.md
(documentation narrative)
pip install sphinx breathe sphinx-rtd-theme# docs/conf.py
project = 'MonProjet'
version = '1.2.0'
extensions = [
'breathe',
'sphinx.ext.autodoc',
]
# Configuration Breathe
breathe_projects = {
"MonProjet": "../build/docs/doxygen/xml"
}
breathe_default_project = "MonProjet"
# Thème
html_theme = 'sphinx_rtd_theme'Le Doxyfile doit activer la sortie XML, consommée par Breathe :
GENERATE_XML = YES
XML_OUTPUT = xml
GENERATE_HTML = NO # Sphinx génère le HTML à la place API Reference
=============
Engine
------
.. doxygenclass:: monprojet::core::Engine
:members:
:undoc-members:
ConnectionPool
--------------
.. doxygenclass:: monprojet::network::ConnectionPool
:members:Sphinx génère une page qui inclut la documentation Doxygen extraite des commentaires C++, intégrée dans le design et la navigation du site Sphinx.
Cette combinaison est justifiée quand le projet a une documentation narrative conséquente (guides, tutoriels, changelogs, migration guides) qui coexiste avec la référence d'API. Pour un projet dont la documentation se résume à la référence d'API, Doxygen seul avec un thème comme Doxygen Awesome est plus simple et suffisant.
Si des classes ou fonctions que vous avez documentées n'apparaissent pas dans la documentation générée, les causes les plus fréquentes sont :
- Le répertoire contenant les fichiers n'est pas listé dans
INPUT. - Le pattern du fichier n'est pas dans
FILE_PATTERNS(par exemple,.hppmanquant). EXTRACT_ALL = NOet le commentaire Doxygen est syntaxiquement invalide (le/**ou///est absent ou malformé).- Le fichier est dans un répertoire listé dans
EXCLUDEouEXCLUDE_PATTERNS.
La commande doxygen -d Preprocessor active le mode debug du préprocesseur, utile pour diagnostiquer les problèmes liés aux macros et aux #ifdef.
Si les diagrammes de classes ne sont pas générés, vérifiez que HAVE_DOT = YES et que dot (Graphviz) est installé et dans le PATH. Doxygen ne signale pas toujours clairement l'absence de Graphviz — les diagrammes sont silencieusement omis.
Les commandes @ref et @see qui pointent vers un symbole inexistant génèrent un warning. Avec WARN_AS_ERROR = FAIL_ON_WARNINGS, ces liens cassés font échouer le build. C'est le comportement souhaité : un lien cassé dans la documentation est un bug, au même titre qu'un test en échec.
Sur un projet existant qui n'a jamais été documenté avec Doxygen, activer WARN_IF_UNDOCUMENTED peut produire des milliers de warnings. La stratégie recommandée est d'y aller progressivement : commencez avec EXTRACT_ALL = NO et WARN_IF_UNDOCUMENTED = NO, documentez l'API publique module par module, puis activez les warnings et WARN_AS_ERROR une fois que le backlog est résorbé.
La génération de documentation avec Doxygen s'organise en trois couches. La première est la configuration via le Doxyfile, où les options clés sont EXTRACT_ALL, JAVADOC_AUTOBRIEF, WARN_AS_ERROR, et l'activation de Graphviz pour les diagrammes. La deuxième est l'intégration CMake, soit avec un add_custom_target simple, soit avec doxygen_add_docs() qui synchronise automatiquement les métadonnées du projet. La troisième est le déploiement CI/CD : un job de vérification sur chaque merge request (warnings comme erreurs) et un job de déploiement sur la branche principale (GitHub Pages, GitLab Pages). Le thème par défaut peut être modernisé via une feuille CSS personnalisée ou le thème Doxygen Awesome. Pour les projets à forte composante narrative, Sphinx + Breathe offre un pipeline complet qui combine référence d'API extraite du code et documentation éditoriale.