[llvm] [docs] Parallelize Sphinx builds by default (PR #217161)
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 19 10:27:04 PDT 2026
https://github.com/rnk updated https://github.com/llvm/llvm-project/pull/217161
>From 806ddda05499f7a42dbc26d1dfaa50e1dd2f7489 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Tue, 18 Aug 2026 22:34:12 +0000
Subject: [PATCH 1/3] [docs] Parallelize Sphinx builds by default
Sphinx supports building documents in parallel with -j. Default LLVM_PARALLEL_SPHINX_JOBS to half the logical cores, rounded up, using CMake's native host system information query, and pass it to sphinx-build. If LLVM_PARALLEL_SPHINX_JOBS is explicitly set empty, omit the -j flag.
3-run hyperfine comparison for clean docs-llvm-html builds, removing the html output and doctree cache before each timing run:
before (no sphinx -j): 97.897 s +/- 1.231 s
after (-j 8): 52.334 s +/- 15.348 s
speedup: 1.87x +/- 0.55x
Validation:
- cmake -S llvm -B build-docs-preview-all
- ninja -C build-docs-preview-all docs-llvm-html
- hyperfine --runs 3 comparing docs-llvm-html before/after
- git diff --check
- scanned touched file for internal-only markers
---
llvm/cmake/modules/AddSphinxTarget.cmake | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/llvm/cmake/modules/AddSphinxTarget.cmake b/llvm/cmake/modules/AddSphinxTarget.cmake
index 02a869b7941a9..c34f52d3a7b7b 100644
--- a/llvm/cmake/modules/AddSphinxTarget.cmake
+++ b/llvm/cmake/modules/AddSphinxTarget.cmake
@@ -136,6 +136,18 @@ function (add_sphinx_target builder project)
set(ARG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
+ if (NOT DEFINED LLVM_PARALLEL_SPHINX_JOBS)
+ cmake_host_system_information(RESULT number_of_logical_cores
+ QUERY NUMBER_OF_LOGICAL_CORES)
+ math(EXPR LLVM_PARALLEL_SPHINX_JOBS
+ "(${number_of_logical_cores} + 1) / 2")
+ set(LLVM_PARALLEL_SPHINX_JOBS "${LLVM_PARALLEL_SPHINX_JOBS}"
+ CACHE STRING "Define the number of parallel Sphinx jobs.")
+ endif()
+ if (LLVM_PARALLEL_SPHINX_JOBS)
+ set(sphinx_jobs_flag -j ${LLVM_PARALLEL_SPHINX_JOBS})
+ endif()
+
if ("${LLVM_VERSION_SUFFIX}" STREQUAL "git")
set(PreReleaseTag "-tPreRelease")
endif()
@@ -146,6 +158,7 @@ function (add_sphinx_target builder project)
${SPHINX_EXECUTABLE}
-b ${builder}
-d "${SPHINX_DOC_TREE_DIR}"
+ ${sphinx_jobs_flag}
-q # Quiet: no output other than errors and warnings.
-t builder-${builder} # tag for builder
-D version=${LLVM_VERSION_MAJOR}
>From f3e735a1ac026587b40d8f5d5927e41ccd63898d Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Wed, 19 Aug 2026 16:41:06 +0000
Subject: [PATCH 2/3] Rename the option, document it, and make the old option
control the job pool depth for consistency with existing options
---
llvm/cmake/modules/AddSphinxTarget.cmake | 34 +++++++++++++++++++-----
llvm/docs/CMake.md | 16 ++++++++---
2 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/llvm/cmake/modules/AddSphinxTarget.cmake b/llvm/cmake/modules/AddSphinxTarget.cmake
index c34f52d3a7b7b..d7da4f87c1a05 100644
--- a/llvm/cmake/modules/AddSphinxTarget.cmake
+++ b/llvm/cmake/modules/AddSphinxTarget.cmake
@@ -4,6 +4,23 @@ include(GNUInstallDirs)
if (LLVM_ENABLE_SPHINX)
message(STATUS "Sphinx enabled.")
find_package(Sphinx REQUIRED)
+
+ # Sphinx has internal parallelism, so give it a custom job pool. Sphinx tends
+ # not to use all available CPU, so this is not enabled by default.
+ set(LLVM_PARALLEL_SPHINX_JOBS "" CACHE STRING
+ "Define the maximum number of concurrent sphinx-build invocations (Ninja only).")
+ if (LLVM_PARALLEL_SPHINX_JOBS)
+ if (CMAKE_GENERATOR MATCHES "Ninja")
+ get_property(_sphinx_job_pools GLOBAL PROPERTY JOB_POOLS)
+ if (NOT "sphinx_job_pool=${LLVM_PARALLEL_SPHINX_JOBS}" IN_LIST _sphinx_job_pools)
+ set_property(GLOBAL APPEND PROPERTY JOB_POOLS sphinx_job_pool=${LLVM_PARALLEL_SPHINX_JOBS})
+ endif()
+ set(sphinx_job_pool JOB_POOL sphinx_job_pool)
+ else()
+ message(WARNING "Job pooling is only available with Ninja generators.")
+ endif()
+ endif()
+
if (LLVM_BUILD_DOCS AND NOT TARGET sphinx)
add_custom_target(sphinx ALL)
set_target_properties(sphinx PROPERTIES FOLDER "LLVM/Docs")
@@ -136,16 +153,20 @@ function (add_sphinx_target builder project)
set(ARG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
- if (NOT DEFINED LLVM_PARALLEL_SPHINX_JOBS)
+ # Give Sphinx some internal job parallelism, since it tends to be on the
+ # critical path at the end of the build. This can speed up doc builds by
+ # ~80%. Sphinx rarely consumes all cores available, so it's safe to
+ # overallocate a bit.
+ if (NOT DEFINED LLVM_SPHINX_BUILD_JOBS)
cmake_host_system_information(RESULT number_of_logical_cores
QUERY NUMBER_OF_LOGICAL_CORES)
- math(EXPR LLVM_PARALLEL_SPHINX_JOBS
+ math(EXPR LLVM_SPHINX_BUILD_JOBS
"(${number_of_logical_cores} + 1) / 2")
- set(LLVM_PARALLEL_SPHINX_JOBS "${LLVM_PARALLEL_SPHINX_JOBS}"
- CACHE STRING "Define the number of parallel Sphinx jobs.")
endif()
- if (LLVM_PARALLEL_SPHINX_JOBS)
- set(sphinx_jobs_flag -j ${LLVM_PARALLEL_SPHINX_JOBS})
+ set(LLVM_SPHINX_BUILD_JOBS "${LLVM_SPHINX_BUILD_JOBS}"
+ CACHE STRING "Define the number of parallel jobs for each Sphinx build.")
+ if (LLVM_SPHINX_BUILD_JOBS)
+ set(sphinx_jobs_flag -j ${LLVM_SPHINX_BUILD_JOBS})
endif()
if ("${LLVM_VERSION_SUFFIX}" STREQUAL "git")
@@ -167,6 +188,7 @@ function (add_sphinx_target builder project)
${SPHINX_WARNINGS_AS_ERRORS_FLAG} # Treat warnings as errors if requested
"${ARG_SOURCE_DIR}" # Source
"${SPHINX_BUILD_DIR}" # Output
+ ${sphinx_job_pool}
COMMENT
"Generating ${builder} Sphinx documentation for ${project} into \"${SPHINX_BUILD_DIR}\"")
get_subproject_title(subproject_title)
diff --git a/llvm/docs/CMake.md b/llvm/docs/CMake.md
index c64b419cd06ba..dac9b0815dfea 100644
--- a/llvm/docs/CMake.md
+++ b/llvm/docs/CMake.md
@@ -910,11 +910,11 @@ sub-projects. Nearly all of these variable names begin with `LLVM_`.
use during the build. Enabling this option can significantly speed up build
times, especially when building LLVM in Debug configurations.
-**LLVM_PARALLEL\_{COMPILE,LINK,TABLEGEN}\_JOBS**:STRING
+**LLVM_PARALLEL\_{COMPILE,LINK,TABLEGEN,SPHINX}\_JOBS**:STRING
-: Limit the maximum number of concurrent compilation, link or tablegen jobs
- respectively. The default total number of parallel jobs is determined by
- the number of logical CPUs.
+: Limit the maximum number of concurrent compilation, link, tablegen, or
+ `sphinx-build` invocations respectively. These limits are implemented with
+ Ninja job pools and only take effect when using a Ninja generator.
**LLVM_PROFDATA_FILE**:PATH
@@ -940,6 +940,14 @@ sub-projects. Nearly all of these variable names begin with `LLVM_`.
reverse order. This is useful for uncovering non-determinism caused by
iteration of unordered containers.
+**LLVM_SPHINX_BUILD_JOBS**:STRING
+
+: Controls `sphinx-build -j`, which defines the max internal Sphinx action
+ parallelism level. Defaults to half the number of logical cores, rounded
+ up. The default is high because Sphinx is often on the critical path, and
+ rarely uses all available cores. Set to an empty string to omit the Sphinx
+ `-j` option.
+
**LLVM_STATIC_LINK_CXX_STDLIB**:BOOL
: Statically link to the C++ standard library if possible. This uses the flag
>From 2903320acdfa6e09431237c165a62b186e7bc588 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Wed, 19 Aug 2026 17:25:54 +0000
Subject: [PATCH 3/3] Rename internal job option
---
llvm/cmake/modules/AddSphinxTarget.cmake | 10 +++++-----
llvm/docs/CMake.md | 11 +++++------
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/llvm/cmake/modules/AddSphinxTarget.cmake b/llvm/cmake/modules/AddSphinxTarget.cmake
index d7da4f87c1a05..6b3987cbbc7c0 100644
--- a/llvm/cmake/modules/AddSphinxTarget.cmake
+++ b/llvm/cmake/modules/AddSphinxTarget.cmake
@@ -157,16 +157,16 @@ function (add_sphinx_target builder project)
# critical path at the end of the build. This can speed up doc builds by
# ~80%. Sphinx rarely consumes all cores available, so it's safe to
# overallocate a bit.
- if (NOT DEFINED LLVM_SPHINX_BUILD_JOBS)
+ if (NOT DEFINED LLVM_SPHINX_THREADS)
cmake_host_system_information(RESULT number_of_logical_cores
QUERY NUMBER_OF_LOGICAL_CORES)
- math(EXPR LLVM_SPHINX_BUILD_JOBS
+ math(EXPR LLVM_SPHINX_THREADS
"(${number_of_logical_cores} + 1) / 2")
endif()
- set(LLVM_SPHINX_BUILD_JOBS "${LLVM_SPHINX_BUILD_JOBS}"
+ set(LLVM_SPHINX_THREADS "${LLVM_SPHINX_BUILD_JOBS}"
CACHE STRING "Define the number of parallel jobs for each Sphinx build.")
- if (LLVM_SPHINX_BUILD_JOBS)
- set(sphinx_jobs_flag -j ${LLVM_SPHINX_BUILD_JOBS})
+ if (LLVM_SPHINX_THREADS)
+ set(sphinx_jobs_flag -j ${LLVM_SPHINX_THREADS})
endif()
if ("${LLVM_VERSION_SUFFIX}" STREQUAL "git")
diff --git a/llvm/docs/CMake.md b/llvm/docs/CMake.md
index dac9b0815dfea..a87e20dd600a2 100644
--- a/llvm/docs/CMake.md
+++ b/llvm/docs/CMake.md
@@ -940,13 +940,12 @@ sub-projects. Nearly all of these variable names begin with `LLVM_`.
reverse order. This is useful for uncovering non-determinism caused by
iteration of unordered containers.
-**LLVM_SPHINX_BUILD_JOBS**:STRING
+**LLVM_SPHINX_THREADS**:STRING
-: Controls `sphinx-build -j`, which defines the max internal Sphinx action
- parallelism level. Defaults to half the number of logical cores, rounded
- up. The default is high because Sphinx is often on the critical path, and
- rarely uses all available cores. Set to an empty string to omit the Sphinx
- `-j` option.
+: Controls `sphinx-build -j`, which is the internal Sphinx worker count.
+ Defaults to half the number of logical cores, rounded up. The default is
+ high because Sphinx is often on the critical path, and rarely uses all
+ available cores. Set to an empty string to omit the Sphinx `-j` option.
**LLVM_STATIC_LINK_CXX_STDLIB**:BOOL
More information about the llvm-commits
mailing list