[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