Skip to content

Commit 7c43003

Browse files
committed
Add env support to Sphinx docs target
1 parent 6c5c251 commit 7c43003

15 files changed

Lines changed: 319 additions & 5 deletions

File tree

cmake/FindSphinx.cmake

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,39 @@ if (Sphinx_FOUND AND NOT TARGET Sphinx::Build)
5050
PROPERTIES
5151
IMPORTED_LOCATION "${SPHINX_EXECUTABLE}")
5252

53+
# Helper function to register a Sphinx documentation target.
5354
function(sphinx_add_docs NAME)
55+
set(_BOOL_ARGS
56+
ALL
57+
SHOW_TRACEBACK
58+
WRITE_ALL
59+
FRESH_ENV
60+
ISOLATED
61+
)
62+
63+
set(_SINGLE_VALUE_ARGS
64+
COMMENT
65+
BUILDER
66+
CONFIG_DIRECTORY
67+
SOURCE_DIRECTORY
68+
OUTPUT_DIRECTORY
69+
WORKING_DIRECTORY
70+
)
71+
72+
set(_MULTI_VALUE_ARGS
73+
DEFINE
74+
DEPENDS
75+
LIBRARY_PATH_PREPEND
76+
PYTHON_PATH_PREPEND
77+
ENVIRONMENT
78+
)
79+
5480
cmake_parse_arguments(
5581
PARSE_ARGV 1 ""
56-
"ALL;SHOW_TRACEBACK;WRITE_ALL;FRESH_ENV;ISOLATED"
57-
"COMMENT;BUILDER;CONFIG_DIRECTORY;SOURCE_DIRECTORY;OUTPUT_DIRECTORY"
58-
"DEFINE;DEPENDS")
82+
"${_BOOL_ARGS}"
83+
"${_SINGLE_VALUE_ARGS}"
84+
"${_MULTI_VALUE_ARGS}"
85+
)
5986

6087
# Ensure that target should be added to the default build target,
6188
# if required.
@@ -65,6 +92,61 @@ if (Sphinx_FOUND AND NOT TARGET Sphinx::Build)
6592
set(_ALL "")
6693
endif()
6794

95+
# Set platform-specific library path environment variable.
96+
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
97+
set(LIBRARY_ENV_NAME PATH)
98+
elseif (CMAKE_SYSTEM_NAME STREQUAL Darwin)
99+
set(LIBRARY_ENV_NAME DYLD_LIBRARY_PATH)
100+
else()
101+
set(LIBRARY_ENV_NAME LD_LIBRARY_PATH)
102+
endif()
103+
104+
# Convert paths to CMake-friendly format.
105+
if(DEFINED ENV{${LIBRARY_ENV_NAME}})
106+
cmake_path(CONVERT "$ENV{${LIBRARY_ENV_NAME}}" TO_CMAKE_PATH_LIST LIBRARY_PATH)
107+
else()
108+
set(LIBRARY_PATH "")
109+
endif()
110+
if(DEFINED ENV{PYTHONPATH})
111+
cmake_path(CONVERT "$ENV{PYTHONPATH}" TO_CMAKE_PATH_LIST PYTHON_PATH)
112+
else()
113+
set(PYTHON_PATH "")
114+
endif()
115+
116+
# Prepend specified paths to the library and Python paths.
117+
if (_LIBRARY_PATH_PREPEND)
118+
list(PREPEND LIBRARY_PATH ${_LIBRARY_PATH_PREPEND})
119+
endif()
120+
121+
if (_PYTHON_PATH_PREPEND)
122+
list(PREPEND PYTHON_PATH ${_PYTHON_PATH_PREPEND})
123+
endif()
124+
125+
# Build environment arguments for cmake -E env.
126+
set(_env_args "")
127+
128+
if (LIBRARY_PATH)
129+
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
130+
list(JOIN LIBRARY_PATH "\\;" _LIBRARY_PATH_STRING)
131+
else()
132+
list(JOIN LIBRARY_PATH ":" _LIBRARY_PATH_STRING)
133+
endif()
134+
list(APPEND _env_args "${LIBRARY_ENV_NAME}=${_LIBRARY_PATH_STRING}")
135+
endif()
136+
137+
if (PYTHON_PATH)
138+
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
139+
list(JOIN PYTHON_PATH "\\;" _PYTHON_PATH_STRING)
140+
else()
141+
list(JOIN PYTHON_PATH ":" _PYTHON_PATH_STRING)
142+
endif()
143+
list(APPEND _env_args "PYTHONPATH=${_PYTHON_PATH_STRING}")
144+
endif()
145+
146+
foreach(_env ${_ENVIRONMENT})
147+
list(APPEND _env_args "${_env}")
148+
endforeach()
149+
68150
# Default working directory to current source path if none is provided.
69151
if (NOT _WORKING_DIRECTORY)
70152
set(_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
@@ -128,7 +210,6 @@ if (Sphinx_FOUND AND NOT TARGET Sphinx::Build)
128210
COMMENT ${_COMMENT}
129211
DEPENDS ${_DEPENDS}
130212
COMMAND ${CMAKE_COMMAND} -E make_directory ${_OUTPUT_DIRECTORY}
131-
COMMAND Sphinx::Build ${_args}
132-
COMMAND_EXPAND_LISTS)
213+
COMMAND ${CMAKE_COMMAND} -E env ${_env_args} "${SPHINX_EXECUTABLE}" ${_args})
133214
endfunction()
134215
endif()

doc/api_reference.rst

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ API Reference
2121
[OUTPUT_DIRECTORY dir]
2222
[DEFINE setting1=value1 setting2=value2...]
2323
[DEPENDS target1 target2...]
24+
[LIBRARY_PATH_PREPEND path1 path2...]
25+
[PYTHON_PATH_PREPEND path1 path2...]
26+
[ENVIRONMENT env1 env2...]
2427
[SHOW_TRACEBACK]
2528
[WRITE_ALL]
2629
[FRESH_ENV]
@@ -120,6 +123,50 @@ API Reference
120123
DEPENDS lib1 lib2
121124
)
122125

126+
* ``LIBRARY_PATH_PREPEND``
127+
128+
List of library paths to prepend to the corresponding environment
129+
variable (:envvar:`LD_LIBRARY_PATH` on Linux,
130+
:envvar:`DYLD_LIBRARY_PATH` on macOS, and :envvar:`PATH` on Windows)
131+
when building the documentation. Each path can be defined literally or
132+
as a CMake expression generator for convenience::
133+
134+
sphinx_add_docs(
135+
...
136+
LIBRARY_PATH_PREPEND
137+
$<TARGET_FILE_DIR:lib1>
138+
$<TARGET_FILE_DIR:lib2>
139+
/path/to/libs/
140+
)
141+
142+
* ``PYTHON_PATH_PREPEND``
143+
144+
List of Python paths to prepend to the :envvar:`PYTHONPATH` environment
145+
variable when building the documentation. Each path can be defined
146+
literally or as a CMake expression generator for convenience::
147+
148+
sphinx_add_docs(
149+
...
150+
PYTHON_PATH_PREPEND
151+
$<TARGET_FILE_DIR:lib1>
152+
$<TARGET_FILE_DIR:lib2>
153+
/path/to/python/
154+
)
155+
156+
* ``ENVIRONMENT``
157+
158+
List of custom environment variables with associated values to set when
159+
building the documentation::
160+
161+
sphinx_add_docs(
162+
...
163+
ENVIRONMENT
164+
"ENV_VAR1=VALUE1"
165+
"ENV_VAR2=VALUE2"
166+
"ENV_VAR3=VALUE3"
167+
)
168+
169+
123170
* ``SHOW_TRACEBACK``
124171

125172
Display the full traceback when an unhandled exception occurs.

doc/environment_variables.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.. _environment_variables:
2+
3+
*********************
4+
Environment variables
5+
*********************
6+
7+
Environment variables directly defined or referenced by this package.
8+
9+
.. envvar:: CMAKE_PREFIX_PATH
10+
11+
Environment variable (or :term:`CMake` option) used to locate directory
12+
to look for configurations.
13+
14+
.. seealso:: https://cmake.org/cmake/help/latest/envvar/CMAKE_PREFIX_PATH.html
15+
16+
.. envvar:: LD_LIBRARY_PATH
17+
18+
Environment variable used on Linux/UNIX System to locate shared libraries.
19+
20+
.. envvar:: DYLD_LIBRARY_PATH
21+
22+
Environment variable used on macOS System to locate shared libraries.
23+
24+
.. envvar:: PATH
25+
26+
Environment variable used to specifies the directories to be searched to
27+
find a command. On Windows system, this environment variable is also used
28+
to locate shared libraries.

doc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Generate documentation for :term:`Sphinx` with :term:`CMake`.
1414
integration
1515
tutorial
1616
api_reference
17+
environment_variables
1718
release/index
1819
Source Code @ GitHub <https://github.com/python-cmake/sphinx-cmake>
1920
glossary

doc/release/release_notes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
Release Notes
55
*************
66

7+
.. release:: Upcoming
8+
9+
.. change:: new
10+
11+
Added support for prepending library and Python paths, and for passing
12+
arbitrary environment variables to Sphinx builds.
13+
714
.. release:: 1.0.1
815
:date: 2025-08-14
916

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
if(WIN32)
2+
set(EXPECTED "/path1;/path2;/path3")
3+
else()
4+
set(EXPECTED "/path1:/path2:/path3")
5+
endif()
6+
configure_file(index.html index.html @ONLY)
7+
8+
# NOTE: configure_file() adds a trailing newline; Sphinx doesn’t.
9+
# Strip it so compare_files remains stable.
10+
file(READ ${CMAKE_CURRENT_BINARY_DIR}/index.html _content)
11+
string(REGEX REPLACE "\n$" "" _content "${_content}")
12+
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/index.html "${_content}")
13+
14+
sphinx_add_docs(doc8 ALL
15+
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
16+
LIBRARY_PATH_PREPEND "/path1" "/path2" "/path3"
17+
PYTHON_PATH_PREPEND "/path1" "/path2" "/path3")
18+
19+
add_test(NAME PrependPaths
20+
COMMAND ${CMAKE_COMMAND} -E compare_files
21+
${CMAKE_CURRENT_BINARY_DIR}/index.html
22+
${CMAKE_CURRENT_BINARY_DIR}/doc/index.html)

test/08-prepend-paths/conf.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import sys
2+
from pathlib import Path
3+
4+
root = Path(__file__).resolve().parent
5+
sys.path.insert(0, str((root / "../resources/_extensions").resolve()))
6+
7+
project = "foo"
8+
copyright = "2026, john-doe"
9+
extensions = ["sphinx_env"]
10+
templates_path = ["../resources/_templates"]
11+
html_permalinks = False

test/08-prepend-paths/index.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>foo</title>
6+
</head>
7+
<body>
8+
<header>
9+
<h1>foo</h1>
10+
</header>
11+
<main>
12+
<span>@EXPECTED@</span><span>@EXPECTED@</span>
13+
</main>
14+
<footer>
15+
<p>&copy2026, john-doe</p>
16+
</footer>
17+
</body>
18+
</html>

test/08-prepend-paths/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.. env:: LIBRARY_PATH 3
2+
.. env:: PYTHONPATH 3

test/09-environment/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
sphinx_add_docs(doc9 ALL
2+
ENVIRONMENT
3+
"KEY1=VALUE1"
4+
"KEY2=VALUE2"
5+
"KEY3=PATH1:PATH2:PATH3"
6+
"KEY4=PATH1\;PATH2\;PATH3"
7+
"KEY5=C:\\Path\\To\\Dir1\;C:\\Path\\To\\Dir2"
8+
"K3Y4=SPECIAL$VALUE!@#%^&*")
9+
10+
add_test(NAME Environment
11+
COMMAND ${CMAKE_COMMAND} -E compare_files
12+
${CMAKE_CURRENT_SOURCE_DIR}/index.html
13+
${CMAKE_CURRENT_BINARY_DIR}/doc/index.html)

0 commit comments

Comments
 (0)