1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 07:13:02 +04:00
Files
omrope79 04aee009aa Merge pull request #29220 from omrope79:doc_optimizations_v4
[FOLLOW UP] : Documentation optimizations for the new Sphinx structure #29220

### Pull Request Readiness Checklist

This PR serves as a follow-up to the new documentation system introduced in [#29206](https://github.com/opencv/opencv/pull/29206)
Co-authored by: @abhishek-gola @kirtijindal14 @Akansha-977 @Prasadayus @varun-jaiswal17

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
2026-06-05 14:18:27 +03:00

249 lines
9.3 KiB
CMake

if(NOT BUILD_DOCS)
return()
endif()
# Prefer the sphinx-build that lives in the conda env where myst-parser /
# pydata-sphinx-theme / breathe / exhale are installed. Override on the
# CMake command line: -DSPHINX_BUILD=/path/to/sphinx-build
find_program(SPHINX_BUILD
NAMES sphinx-build
DOC "Path to sphinx-build tool")
if(NOT SPHINX_BUILD)
message(STATUS "docs_sphinx: sphinx-build not found; `sphinx` target disabled")
return()
endif()
find_program(DOT_EXECUTABLE NAMES dot
DOC "Path to graphviz `dot` (required for API collaboration diagrams)")
if(NOT DOT_EXECUTABLE)
message(WARNING
"docs_sphinx: graphviz `dot` not found — API class-page collaboration "
"diagrams will be skipped. Install graphviz (e.g. `sudo apt-get install "
"graphviz`) and re-run cmake so the Doxygen HTML build enables HAVE_DOT.")
else()
message(STATUS
"docs_sphinx: graphviz dot found (${DOT_EXECUTABLE}) — "
"collaboration diagrams enabled")
endif()
set(_SPHINX_CONFDIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(_SPHINX_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/html")
set(_SPHINX_INPUT_ROOT "${CMAKE_CURRENT_BINARY_DIR}/docs_sphinx_input")
set(_SPHINX_INPUT_TUTORIALS "${_SPHINX_INPUT_ROOT}/tutorials")
set(_SPHINX_INPUT_CONTRIB "${_SPHINX_INPUT_ROOT}/tutorials_contrib")
file(REMOVE_RECURSE "${_SPHINX_INPUT_ROOT}")
file(MAKE_DIRECTORY "${_SPHINX_INPUT_TUTORIALS}")
# Main tree: symlink the master file + each main module subtree.
file(CREATE_LINK
"${CMAKE_SOURCE_DIR}/doc/tutorials/tutorials.markdown"
"${_SPHINX_INPUT_TUTORIALS}/tutorials.markdown"
SYMBOLIC COPY_ON_ERROR)
file(CREATE_LINK
"${CMAKE_SOURCE_DIR}/doc/faq.markdown"
"${_SPHINX_INPUT_ROOT}/faq.markdown"
SYMBOLIC COPY_ON_ERROR)
file(CREATE_LINK
"${CMAKE_SOURCE_DIR}/modules/core/doc/intro.markdown"
"${_SPHINX_INPUT_ROOT}/intro.markdown"
SYMBOLIC COPY_ON_ERROR)
file(GLOB _main_tutorial_children
RELATIVE "${CMAKE_SOURCE_DIR}/doc/tutorials"
"${CMAKE_SOURCE_DIR}/doc/tutorials/*")
foreach(_d ${_main_tutorial_children})
if(IS_DIRECTORY "${CMAKE_SOURCE_DIR}/doc/tutorials/${_d}")
file(CREATE_LINK
"${CMAKE_SOURCE_DIR}/doc/tutorials/${_d}"
"${_SPHINX_INPUT_TUTORIALS}/${_d}"
SYMBOLIC COPY_ON_ERROR)
endif()
endforeach()
# js_tutorials, py_tutorials, images/ sit directly under opencv/doc/.
foreach(_root js_tutorials py_tutorials images)
if(EXISTS "${CMAKE_SOURCE_DIR}/doc/${_root}")
file(CREATE_LINK
"${CMAKE_SOURCE_DIR}/doc/${_root}"
"${_SPHINX_INPUT_ROOT}/${_root}"
SYMBOLIC COPY_ON_ERROR)
endif()
endforeach()
if(OPENCV_EXTRA_MODULES_PATH AND EXISTS "${OPENCV_EXTRA_MODULES_PATH}")
file(MAKE_DIRECTORY "${_SPHINX_INPUT_CONTRIB}")
set(_contrib_root_md "${_SPHINX_INPUT_CONTRIB}/contrib_root.markdown")
file(WRITE "${_contrib_root_md}"
"Tutorials for contrib modules {#tutorial_contrib_root}\n"
"=============================\n\n")
file(GLOB _contrib_subdirs RELATIVE "${OPENCV_EXTRA_MODULES_PATH}"
"${OPENCV_EXTRA_MODULES_PATH}/*")
foreach(_m ${_contrib_subdirs})
set(_tut_dir "${OPENCV_EXTRA_MODULES_PATH}/${_m}/tutorials")
if(IS_DIRECTORY "${_tut_dir}")
file(CREATE_LINK "${_tut_dir}" "${_SPHINX_INPUT_CONTRIB}/${_m}"
SYMBOLIC COPY_ON_ERROR)
file(GLOB _tocs RELATIVE "${_tut_dir}" "${_tut_dir}/*.markdown")
foreach(_t ${_tocs})
file(STRINGS "${_tut_dir}/${_t}" _id LIMIT_COUNT 1 REGEX ".*\\{#[^}]+\\}")
string(REGEX REPLACE ".*\\{#([^}]+)\\}.*" "\\1" _id "${_id}")
if(_id)
file(APPEND "${_contrib_root_md}" "- @subpage ${_id}\n")
endif()
endforeach()
endif()
endforeach()
endif()
set(_LEGACY_DOXYFILE "${CMAKE_BINARY_DIR}/doc/Doxyfile")
set(_DOXYGEN_XML_DIR "${CMAKE_BINARY_DIR}/doc/doxygen/xml")
if(NOT DEFINED SPHINX_API_MODULES)
# Any module whose include tree declares an @defgroup, keyed on dir name; matlab excluded.
set(SPHINX_API_MODULES "")
set(_api_module_roots "${CMAKE_SOURCE_DIR}/modules")
if(OPENCV_EXTRA_MODULES_PATH AND EXISTS "${OPENCV_EXTRA_MODULES_PATH}")
list(APPEND _api_module_roots "${OPENCV_EXTRA_MODULES_PATH}")
endif()
foreach(_root ${_api_module_roots})
file(GLOB _api_module_dirs RELATIVE "${_root}" "${_root}/*")
foreach(_m ${_api_module_dirs})
if(IS_DIRECTORY "${_root}/${_m}/include/opencv2" AND NOT _m STREQUAL "matlab")
file(GLOB_RECURSE _api_hdrs "${_root}/${_m}/include/opencv2/*.hpp")
foreach(_hdr ${_api_hdrs})
file(READ "${_hdr}" _hdr_contents)
if(_hdr_contents MATCHES "@defgroup")
list(APPEND SPHINX_API_MODULES "${_m}")
break()
endif()
endforeach()
endif()
endforeach()
endforeach()
list(REMOVE_DUPLICATES SPHINX_API_MODULES)
list(SORT SPHINX_API_MODULES)
message(STATUS "docs_sphinx: discovered API modules: ${SPHINX_API_MODULES}")
endif()
set(_doxy_input "")
foreach(_m ${SPHINX_API_MODULES})
foreach(_base "${CMAKE_SOURCE_DIR}/modules" "${OPENCV_EXTRA_MODULES_PATH}")
if(EXISTS "${_base}/${_m}/include")
string(APPEND _doxy_input " ${_base}/${_m}/include")
break()
endif()
endforeach()
endforeach()
if(EXISTS "${_LEGACY_DOXYFILE}")
set(_SPHINX_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-xml")
file(WRITE "${_SPHINX_DOXYFILE}"
"@INCLUDE = ${_LEGACY_DOXYFILE}\n"
"GENERATE_HTML = NO\n"
"GENERATE_LATEX = NO\n"
"GENERATE_XML = YES\n"
"XML_OUTPUT = xml\n"
"XML_PROGRAMLISTING = NO\n"
"CREATE_SUBDIRS = NO\n"
"CLASS_GRAPH = NO\n"
"COLLABORATION_GRAPH = NO\n"
"GROUP_GRAPHS = NO\n"
"INCLUDE_GRAPH = NO\n"
"INCLUDED_BY_GRAPH = NO\n"
"DIRECTORY_GRAPH = NO\n"
"INPUT =${_doxy_input}\n"
"RECURSIVE = YES\n"
"EXCLUDE_SYMBOLS = cv::DataType<*> int void CV__* T __CV* cv::gapi::detail*\n"
"MACRO_EXPANSION = YES\n"
"EXPAND_ONLY_PREDEF = YES\n"
"PREDEFINED += __device__= __host__= __forceinline__= __global__= __constant__= __shared__= __restrict__=\n"
)
find_program(DOXYGEN_EXE NAMES doxygen)
if(DOXYGEN_EXE)
# Stamp-based: Doxygen only re-runs when Doxyfile changes, not on every build.
set(_SPHINX_XML_STAMP "${_DOXYGEN_XML_DIR}/.sphinx_xml.stamp")
add_custom_command(
OUTPUT "${_SPHINX_XML_STAMP}"
COMMAND ${CMAKE_COMMAND} -E make_directory ${_DOXYGEN_XML_DIR}
COMMAND ${DOXYGEN_EXE} ${_SPHINX_DOXYFILE}
COMMAND ${CMAKE_COMMAND} -E touch "${_SPHINX_XML_STAMP}"
DEPENDS "${_SPHINX_DOXYFILE}"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/doc
COMMENT "Doxygen XML (for Sphinx breathe) -> ${_DOXYGEN_XML_DIR}"
VERBATIM)
add_custom_target(sphinx-xml DEPENDS "${_SPHINX_XML_STAMP}")
message(STATUS "docs_sphinx: sphinx-xml target enabled (doxygen: ${DOXYGEN_EXE})")
else()
message(STATUS "docs_sphinx: doxygen not found; `sphinx-xml` disabled")
endif()
else()
message(STATUS "docs_sphinx: legacy Doxyfile not present at ${_LEGACY_DOXYFILE}; "
"`sphinx-xml` disabled (re-run cmake after doc/ subdir configures)")
endif()
set(_SPHINX_ENV
"OPENCV_SPHINX_INPUT_ROOT=${_SPHINX_INPUT_ROOT}"
"OPENCV_CONTRIB_ROOT=${OPENCV_EXTRA_MODULES_PATH}"
"OPENCV_DOXYGEN_XML_DIR=${_DOXYGEN_XML_DIR}"
)
if(OPENCV_PYTHON_SIGNATURES_FILE)
list(APPEND _SPHINX_ENV "OPENCV_PYTHON_SIGNATURES_FILE=${OPENCV_PYTHON_SIGNATURES_FILE}")
endif()
if(NOT SPHINX_JOBS)
set(SPHINX_JOBS "auto")
endif()
set(_SPHINX_WARNINGS "${CMAKE_CURRENT_BINARY_DIR}/sphinx-warnings.log")
# opencv.js (JS Try-it): download once into the build dir, bundled into html output.
set(_OPENCV_JS "${CMAKE_CURRENT_BINARY_DIR}/opencv.js")
if(NOT EXISTS "${_OPENCV_JS}")
message(STATUS "docs_sphinx: downloading opencv.js (one-time)")
file(DOWNLOAD "https://docs.opencv.org/5.x/opencv.js" "${_OPENCV_JS}"
SHOW_PROGRESS STATUS _DL_STATUS)
list(GET _DL_STATUS 0 _DL_OK)
if(NOT _DL_OK EQUAL 0)
message(WARNING "docs_sphinx: opencv.js download failed — Try-it won't run")
file(REMOVE "${_OPENCV_JS}")
set(_OPENCV_JS "")
endif()
endif()
if(_OPENCV_JS)
list(APPEND _SPHINX_ENV "OPENCV_JS_PATH=${_OPENCV_JS}")
endif()
add_custom_target(sphinx
COMMAND ${CMAKE_COMMAND} -E make_directory ${_SPHINX_OUTDIR}
COMMAND ${CMAKE_COMMAND} -E env ${_SPHINX_ENV}
${SPHINX_BUILD} -j ${SPHINX_JOBS} --keep-going
-c ${_SPHINX_CONFDIR}
${_SPHINX_INPUT_ROOT}
${_SPHINX_OUTDIR}
WORKING_DIRECTORY ${_SPHINX_CONFDIR}
COMMENT "Building Sphinx HTML site -> ${_SPHINX_OUTDIR} (jobs=${SPHINX_JOBS})"
VERBATIM)
# Ensure breathe sees current XML on every `sphinx` build.
if(TARGET sphinx-xml)
add_dependencies(sphinx sphinx-xml)
endif()
# Auto-generate Python binding signatures (needed for Python names in enum tables).
if(TARGET gen_opencv_python_source)
add_dependencies(sphinx gen_opencv_python_source)
endif()
option(SPHINX_BUILD_DIAGRAMS
"Rebuild the Doxygen HTML (collaboration diagrams) as part of the sphinx target" ON)
if(SPHINX_BUILD_DIAGRAMS AND TARGET doxygen)
add_dependencies(sphinx doxygen)
endif()
# Clean rebuild: `cmake --build <build> --target sphinx-clean`
add_custom_target(sphinx-clean
COMMAND ${CMAKE_COMMAND} -E rm -rf ${_SPHINX_OUTDIR}
COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_CURRENT_BINARY_DIR}/.doctrees
COMMENT "Removing ${_SPHINX_OUTDIR} and .doctrees env cache"
VERBATIM)
message(STATUS "docs_sphinx: sphinx target enabled (sphinx-build: ${SPHINX_BUILD})")