Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 86 additions & 5 deletions cmake/FindSphinx.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,39 @@ if (Sphinx_FOUND AND NOT TARGET Sphinx::Build)
PROPERTIES
IMPORTED_LOCATION "${SPHINX_EXECUTABLE}")

# Helper function to register a Sphinx documentation target.
function(sphinx_add_docs NAME)
set(_BOOL_ARGS
ALL
SHOW_TRACEBACK
WRITE_ALL
FRESH_ENV
ISOLATED
)

set(_SINGLE_VALUE_ARGS
COMMENT
BUILDER
CONFIG_DIRECTORY
SOURCE_DIRECTORY
OUTPUT_DIRECTORY
WORKING_DIRECTORY
)

set(_MULTI_VALUE_ARGS
DEFINE
DEPENDS
LIBRARY_PATH_PREPEND
PYTHON_PATH_PREPEND
ENVIRONMENT
)

cmake_parse_arguments(
PARSE_ARGV 1 ""
"ALL;SHOW_TRACEBACK;WRITE_ALL;FRESH_ENV;ISOLATED"
"COMMENT;BUILDER;CONFIG_DIRECTORY;SOURCE_DIRECTORY;OUTPUT_DIRECTORY"
"DEFINE;DEPENDS")
"${_BOOL_ARGS}"
"${_SINGLE_VALUE_ARGS}"
"${_MULTI_VALUE_ARGS}"
)

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

# Set platform-specific library path environment variable.
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
set(LIBRARY_ENV_NAME PATH)
elseif (CMAKE_SYSTEM_NAME STREQUAL Darwin)
set(LIBRARY_ENV_NAME DYLD_LIBRARY_PATH)
else()
set(LIBRARY_ENV_NAME LD_LIBRARY_PATH)
endif()

# Convert paths to CMake-friendly format.
if(DEFINED ENV{${LIBRARY_ENV_NAME}})
cmake_path(CONVERT "$ENV{${LIBRARY_ENV_NAME}}" TO_CMAKE_PATH_LIST LIBRARY_PATH)
else()
set(LIBRARY_PATH "")
endif()
if(DEFINED ENV{PYTHONPATH})
cmake_path(CONVERT "$ENV{PYTHONPATH}" TO_CMAKE_PATH_LIST PYTHON_PATH)
else()
set(PYTHON_PATH "")
endif()

# Prepend specified paths to the library and Python paths.
if (_LIBRARY_PATH_PREPEND)
list(PREPEND LIBRARY_PATH ${_LIBRARY_PATH_PREPEND})
endif()

if (_PYTHON_PATH_PREPEND)
list(PREPEND PYTHON_PATH ${_PYTHON_PATH_PREPEND})
endif()

# Build environment arguments for cmake -E env.
set(_env_args "")

if (LIBRARY_PATH)
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
list(JOIN LIBRARY_PATH "\\;" _LIBRARY_PATH_STRING)
else()
list(JOIN LIBRARY_PATH ":" _LIBRARY_PATH_STRING)
endif()
list(APPEND _env_args "${LIBRARY_ENV_NAME}=${_LIBRARY_PATH_STRING}")
endif()

if (PYTHON_PATH)
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
list(JOIN PYTHON_PATH "\\;" _PYTHON_PATH_STRING)
else()
list(JOIN PYTHON_PATH ":" _PYTHON_PATH_STRING)
endif()
list(APPEND _env_args "PYTHONPATH=${_PYTHON_PATH_STRING}")
endif()

foreach(_env ${_ENVIRONMENT})
list(APPEND _env_args "${_env}")
endforeach()

# Default working directory to current source path if none is provided.
if (NOT _WORKING_DIRECTORY)
set(_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
Expand Down Expand Up @@ -128,7 +210,6 @@ if (Sphinx_FOUND AND NOT TARGET Sphinx::Build)
COMMENT ${_COMMENT}
DEPENDS ${_DEPENDS}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_OUTPUT_DIRECTORY}
COMMAND Sphinx::Build ${_args}
COMMAND_EXPAND_LISTS)
COMMAND ${CMAKE_COMMAND} -E env ${_env_args} "${SPHINX_EXECUTABLE}" ${_args})
endfunction()
endif()
47 changes: 47 additions & 0 deletions doc/api_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ API Reference
[OUTPUT_DIRECTORY dir]
[DEFINE setting1=value1 setting2=value2...]
[DEPENDS target1 target2...]
[LIBRARY_PATH_PREPEND path1 path2...]
[PYTHON_PATH_PREPEND path1 path2...]
[ENVIRONMENT env1 env2...]
[SHOW_TRACEBACK]
[WRITE_ALL]
[FRESH_ENV]
Expand Down Expand Up @@ -120,6 +123,50 @@ API Reference
DEPENDS lib1 lib2
)

* ``LIBRARY_PATH_PREPEND``

List of library paths to prepend to the corresponding environment
variable (:envvar:`LD_LIBRARY_PATH` on Linux,
:envvar:`DYLD_LIBRARY_PATH` on macOS, and :envvar:`PATH` on Windows)
when building the documentation. Each path can be defined literally or
as a CMake expression generator for convenience::

sphinx_add_docs(
...
LIBRARY_PATH_PREPEND
$<TARGET_FILE_DIR:lib1>
$<TARGET_FILE_DIR:lib2>
/path/to/libs/
)

* ``PYTHON_PATH_PREPEND``

List of Python paths to prepend to the :envvar:`PYTHONPATH` environment
variable when building the documentation. Each path can be defined
literally or as a CMake expression generator for convenience::

sphinx_add_docs(
...
PYTHON_PATH_PREPEND
$<TARGET_FILE_DIR:lib1>
$<TARGET_FILE_DIR:lib2>
/path/to/python/
)

* ``ENVIRONMENT``

List of custom environment variables with associated values to set when
building the documentation::

sphinx_add_docs(
...
ENVIRONMENT
"ENV_VAR1=VALUE1"
"ENV_VAR2=VALUE2"
"ENV_VAR3=VALUE3"
)


* ``SHOW_TRACEBACK``

Display the full traceback when an unhandled exception occurs.
Expand Down
28 changes: 28 additions & 0 deletions doc/environment_variables.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.. _environment_variables:

*********************
Environment variables
*********************

Environment variables directly defined or referenced by this package.

.. envvar:: CMAKE_PREFIX_PATH

Environment variable (or :term:`CMake` option) used to locate directory
to look for configurations.

.. seealso:: https://cmake.org/cmake/help/latest/envvar/CMAKE_PREFIX_PATH.html

.. envvar:: LD_LIBRARY_PATH

Environment variable used on Linux/UNIX System to locate shared libraries.

.. envvar:: DYLD_LIBRARY_PATH

Environment variable used on macOS System to locate shared libraries.

.. envvar:: PATH

Environment variable used to specifies the directories to be searched to
find a command. On Windows system, this environment variable is also used
to locate shared libraries.
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Generate documentation for :term:`Sphinx` with :term:`CMake`.
integration
tutorial
api_reference
environment_variables
release/index
Source Code @ GitHub <https://github.com/python-cmake/sphinx-cmake>
glossary
7 changes: 7 additions & 0 deletions doc/release/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
Release Notes
*************

.. release:: Upcoming

.. change:: new

Added support for prepending library and Python paths, and for passing
arbitrary environment variables to Sphinx builds.

.. release:: 1.0.1
:date: 2025-08-14

Expand Down
103 changes: 87 additions & 16 deletions doc/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
Tutorial
********

Once :ref:`integrated in your project <integration>`, the ``Sphinx::Build``
target and the :func:`sphinx_add_docs` function are available for using.
Once :ref:`integrated into your project <integration>`, the ``Sphinx::Build``
target and the :func:`sphinx_add_docs` function are available for use.

.. _tutorial/target:

Expand All @@ -14,8 +14,9 @@ Using the target

Let's consider a project that includes a :file:`doc` folder containing
:term:`Sphinx` documentation. We need to add a :file:`CMakeLists.txt`
configuration file to add Python tests within the same directory. The
"sphinx-build" command can be easily implemented using a custom target:
configuration file to build the documentation as part of the project.

The ``sphinx-build`` command can be implemented directly using a custom target:

.. code-block:: cmake

Expand All @@ -26,29 +27,61 @@ configuration file to add Python tests within the same directory. The
)

Building the project will generate an HTML version of the documentation within
the build folder, making it ready for installation.
the build directory, making it ready for installation or deployment.

In some cases, the documentation build may depend on Python modules or shared
libraries produced by the project itself. These must be made available through
the build environment.

This can be achieved by explicitly defining environment variables on the target,
for example:

.. code-block:: cmake

set_target_properties(doc PROPERTIES
ENVIRONMENT
PYTHONPATH=$<TARGET_FILE_DIR:MyLibrary>:$ENV{PYTHONPATH}
)

Similarly, shared libraries required at runtime must be discoverable through the
platform-specific library search path.

.. code-block:: cmake

set_target_properties(doc PROPERTIES
APPEND ENVIRONMENT
LD_LIBRARY_PATH=$<TARGET_FILE_DIR:MyLibrary>:$ENV{LD_LIBRARY_PATH}
)

.. warning::

The environment variable used to locate shared libraries depends on the
platform. :envvar:`LD_LIBRARY_PATH` is used on Linux,
:envvar:`DYLD_LIBRARY_PATH` on macOS, and :envvar:`PATH` on Windows.

.. _tutorial/function:

Using the function
==================

A :func:`sphinx_add_docs` function is provided to create a target which will
generate the documentation. Therefore, the custom target added in the previous
section could be replaced by the following:
A :func:`sphinx_add_docs` function is provided to simplify the creation of a
documentation target. The configuration above can therefore be replaced by the
following:

.. code-block:: cmake

sphinx_add_docs(doc ALL)

By default, the :term:`builder` used is "html". Another builder can be defined
By default, the :term:`builder` used is ``html``. Another builder can be selected
as follows:

.. code-block:: cmake

sphinx_add_docs(doc ALL BUILDER latex)
sphinx_add_docs(doc ALL
BUILDER latex
)

You can define different source and output directories as follows:
Different source and output directories can be specified:

.. code-block:: cmake

Expand All @@ -57,26 +90,64 @@ You can define different source and output directories as follows:
OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/sphinx-doc
)

You can also define a separate directory to fetch the :file:`conf.py` file:
A separate directory can also be used to locate the :file:`conf.py` file:

.. code-block:: cmake

sphinx_add_docs(doc ALL
CONFIG_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/config
)

Defining configuration setting directly within the :term:`CMake` configuration
file to override the :file:`conf.py` file can be done as follows:
Configuration values can be overridden directly from the :term:`CMake`
configuration using the ``DEFINE`` option:

.. code-block:: cmake

sphinx_add_docs(doc ALL
DEFINE
version=${MAKE_PROJECT_VERSION}
version=${PROJECT_VERSION}
)

If necessary, you can also ignore the :file:`conf.py` file:
The :file:`conf.py` file can be ignored entirely if required:

.. code-block:: cmake

sphinx_add_docs(doc ALL ISOLATED)

When the documentation depends on project-built libraries or Python modules,
the build environment can be configured declaratively using dedicated options.

The ``LIBRARY_PATH_PREPEND`` option prepends directories to the platform-specific
library search path, selecting the appropriate environment variable
automatically:

.. code-block:: cmake

sphinx_add_docs(doc ALL
LIBRARY_PATH_PREPEND
$<TARGET_FILE_DIR:MyLibrary>
)

Python modules can similarly be made available by prepending directories to the
Python module search path:

.. code-block:: cmake

sphinx_add_docs(doc ALL
PYTHON_PATH_PREPEND
${CMAKE_CURRENT_SOURCE_DIR}/python
)

Custom environment variables can also be defined explicitly:

.. code-block:: cmake

sphinx_add_docs(doc ALL
ENVIRONMENT
"MY_PROJECT_DOCS_MODE=1"
"CUSTOM_FLAG=enabled"
)

These options allow the documentation build environment to be described
declaratively and consistently across platforms, without manually handling
platform-specific environment variables.
Loading
Loading