Skip to content

[25592] Reduce Read the Docs build time and fix version branch resolution - #1306

Open
rsanchez15 wants to merge 3 commits into
masterfrom
feature/improve-docs-build
Open

[25592] Reduce Read the Docs build time and fix version branch resolution#1306
rsanchez15 wants to merge 3 commits into
masterfrom
feature/improve-docs-build

Conversation

@rsanchez15

@rsanchez15 rsanchez15 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Description

Read the Docs builds of latest / 3.x were taking around 37 minutes (2248 s, 2199 s, 2244 s on recent builds). The suspicion was that the breathe-generated C++ API Reference was to blame. It is a large cost, but not the main one: the build was paying for the same work four times over.

Read the Docs runs a separate sphinx-build per output format, and readthedocs.yaml requested formats: all. The build log of a latest build shows where the 37 minutes go:

Step Time
python -m sphinx -b html 735.9 s
python -m sphinx -b singlehtml (htmlzip) 491.2 s
python -m sphinx -b latex (pdf) 463.9 s
python -m sphinx -b epub 392.9 s
latexmk 72.1 s
apt + pip + git setup ~70 s

93% of the wall time is those four Sphinx invocations. Since each one imports docs/conf.py again, the preparation done there also ran four times: the log contains Read the Docs environment detected!, Cloning Fast DDS, Cloning Fast DDS Python Bindings and Configuring Doxyfile 4x each, plus Removing existing repository in ... 6 times — runs 2 to 4 deleted and re-cloned Fast DDS (149 MB of history, no --depth) and Fast DDS Python, and re-ran doxygen and SWIG.

PR builds only took ~13 min because Read the Docs skips additional formats for external versions.

This PR contains four changes:

1. Build only HTML, and generate the downloadable documentation from it (readthedocs.yaml)

formats: all -> formats: [htmlzip]. The latex and epub runs and latexmk are removed: -929 s (~15.5 min). The PDF and epub downloads disappear from the Read the Docs flyout menu. htmlzip is kept, as it is the format that provides the downloadable documentation for offline reading.

By default, htmlzip is not a copy of the HTML output: Read the Docs generates it with an extra sphinx-build -b singlehtml run, that is, by building the whole documentation a second time (491.2 s in the log above). Since html is built first and its output is already the complete documentation, build.jobs.build.htmlzip is overridden to compress that output instead:

build:
  jobs:
    build:
      htmlzip:
        - mkdir -p $READTHEDOCS_OUTPUT/htmlzip
        - python -m zipfile -c $READTHEDOCS_OUTPUT/htmlzip/fast-dds-docs.zip $READTHEDOCS_OUTPUT/html

491.2 s -> ~1 s, and the downloaded file becomes the whole documentation site, navigation and search included, instead of a single page. Only the htmlzip job is overridden; every other format keeps its default command.

2. Stop generating doxygen output that nothing consumes (code/doxygen-config.in)

Tag Before After Reason
XML_PROGRAMLISTING YES NO 11.5 MB of the 32.3 MB XML that breathe parses on every build were <programlisting> elements. None of the 492 directives used in the API Reference renders program listings. XML: 33 MB -> 22 MB.
GENERATE_HTML YES NO 51 MB of standalone doxygen HTML was written to @PROJECT_BINARY_DIR@/html/doxygen and never published: html_extra_path is commented out, CMakeLists.txt installs only doxygen/xml, and no .rst file links into doxygen/.
SEARCHENGINE YES NO Only applies to the HTML output disabled above.

The API Reference is unaffected: breathe consumes the XML output, which is still generated.

3. Clone Fast DDS cheaply, and prepare it once per build (docs/conf.py)

resolve_remote_ref() resolves the branch or tag with git ls-remote, without downloading anything, so falling back to master when the remote does not have the wanted ref costs nothing. clone_repo_at_ref() then clones it with --depth 1 --single-branch, which is all doxygen and SWIG need — 4.5 MB and 1.6 s instead of 149 MB of history.

The shutil.rmtree + re-clone on every import is replaced by a reuse check: the clone, doxygen and SWIG steps are skipped when the repositories are already checked out at the expected commit (repo_is_at_commit(), comparing HEAD against the commit resolved above) and doxygen/xml/index.xml and the SWIG wrapper are already in place. So the htmlzip run reuses everything the html run prepared instead of repeating it.

4. Build the API Reference from the right branch (docs/conf.py)

Unrelated bug found in the same logs: on the latest (3.6.x) build, get_git_branch() returns None for the latest pseudo-name, so the log reads Current documentation branch could not be determined followed by Checking out Fast DDS branch "origin/master". The 3.6.x API Reference was therefore generated from Fast DDS master headers, and the GitHub links pointed at master.

get_git_branch() now prefers Read the Docs' READTHEDOCS_GIT_IDENTIFIER (the ref actually checked out, e.g. 3.6.x) for the latest and stable pseudo-names. The value is validated against the remote by change 3, so an unexpected value still falls back to master exactly as before.

Result

Before After
Sphinx run (local, same command, fresh doctrees) 405.2 s 338.7 s (-16.4%)
Doxygen 4.6 s 2.7 s
Doxygen XML parsed by breathe 33 MB 22 MB
Fast DDS clone 149 MB of history 4.5 MB, 1.6 s
Repository clone + doxygen + SWIG per build 4 times once
Downloadable documentation (htmlzip) 491.2 s ~1 s
latest / 3.x build on Read the Docs ~37 min ~11 min
PR build on Read the Docs ~13 min ~11 min

The estimate for latest is the html run with 16.4% off (~615 s), about a second of compression, and the ~70 s of environment setup.

Verification

  • colcon build --packages-select fastdds-docs succeeds, build succeeded with no warnings.
  • The API Reference output is unchanged: all 350 fastdds/api_reference HTML pages are byte-identical before and after the doxygen changes (51,136,889 bytes either way), compared with the same command and a fresh doctrees directory.
  • resolve_remote_ref() was exercised against the real remotes for an existing branch (3.6.x), an existing tag (v3.6.1), a ref that only tail-matches an unrelated branch, and an absent ref: the first two are used with their commit, the last two fall back to master without failing.
  • repo_is_at_commit() returns True only for a clone at the expected commit, and False, with a printed reason, for a clone at a different commit, a missing directory, a directory that is not a repository, and an unresolved commit.
  • The htmlzip commands were run against a real HTML output: 1.1 s to compress 98 MB into a 15 MB archive that unzips into a browsable site with the 559 pages, the 350 API Reference pages, the static assets, searchindex.js and the images. The build log confirms Read the Docs builds the html format first, so its output is in place when the htmlzip job runs.
  • The Read the Docs block was executed with the clone, doxygen and SWIG steps stubbed out, covering its four paths: nothing cloned yet, everything present at the expected commit (reused), present at a different commit (re-cloned and regenerated), and present at the right commit but without the doxygen XML (regenerated).
  • get_git_branch() was exercised for a latest build tracking 3.6.x (now resolves to 3.6.x), a latest build with no READTHEDOCS_GIT_IDENTIFIER (still None, unchanged), and an external PR build (still None, so the PR number is never used as a ref).

Not included

Moving fastdds/api_reference into its own Read the Docs subproject. It is the biggest remaining lever — the API Reference is 65% of each Sphinx run (262 s of 405 s locally; excluding it drops the build to 143 s) — but it requires intersphinx to keep the ~1000 :cpp: aliases in docs/03-exports/aliases-api.include resolving from the prose, so it is left for a separate discussion.

Contributor Checklist

  • Commit messages follow the project guidelines.
  • N/A Code snippets related to the added documentation have been provided.
  • Documentation tests pass locally.
  • N/A The Pro version badge has been added if the documented feature is exclusive to Fast DDS Pro.
  • Applicable backports have been included in the description.

Reviewer Checklist

  • The PR has a milestone assigned.
  • The title and description correctly express the PR's purpose.
  • Check contributor checklist is correct.
  • CI passes without warnings or errors.

Signed-off-by: Raul Sanchez-Mateos <raul@eprosima.com>

@cferreiragonz cferreiragonz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I would just add one extra protection

Comment thread docs/conf.py
# Read the Docs runs a separate sphinx-build, which imports this file again, for every enabled output
# format. Cloning the repositories and running doxygen and SWIG once per format would repeat several
# minutes of work, so the preparation is skipped when a previous run of this build already completed it.
if (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also check here that the existing repo is checked out at the correct ref, not only that it exists.

@cferreiragonz cferreiragonz added this to the v3.6.3.0 milestone Aug 31, 2026
@cferreiragonz cferreiragonz changed the title Reduce Read the Docs build time and fix version branch resolution [25592] Reduce Read the Docs build time and fix version branch resolution Aug 31, 2026
…ected commit

Signed-off-by: Raul Sanchez-Mateos <raul@eprosima.com>
cferreiragonz
cferreiragonz previously approved these changes Sep 1, 2026

@cferreiragonz cferreiragonz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with green CI

@cferreiragonz
cferreiragonz requested review from richiprosima and removed request for richiprosima September 1, 2026 14:49
Signed-off-by: Raul Sanchez-Mateos <raul@eprosima.com>
@rsanchez15

Copy link
Copy Markdown
Contributor Author

See https://fast-dds.docs.eprosima.com/en/feature-improve-docs-build for a reference build.

@rsanchez15
rsanchez15 requested review from cferreiragonz and removed request for cferreiragonz September 2, 2026 06:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants