mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
04aee009aa
[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
249 lines
9.3 KiB
CMake
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})")
|