| # SPDX-License-Identifier: Apache-2.0 |
| |
| cmake_minimum_required(VERSION 3.28.0) |
| project(Zephyr-Kernel-Doc LANGUAGES) |
| |
| set(MIN_WEST_VERSION 1.0.0) |
| find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} .. COMPONENTS doc) |
| |
| file(TO_CMAKE_PATH "${ZEPHYR_BASE}" ZEPHYR_BASE) |
| message(STATUS "Zephyr base: ${ZEPHYR_BASE}") |
| |
| #------------------------------------------------------------------------------- |
| # Options |
| |
| set(SPHINXOPTS "-j auto -W --keep-going -T" CACHE STRING "Default Sphinx Options") |
| set(SPHINXOPTS_EXTRA "" CACHE STRING "Extra Sphinx Options (added to defaults)") |
| set(LATEXMKOPTS "-halt-on-error -no-shell-escape" CACHE STRING "Default latexmk options") |
| set(DT_TURBO_MODE OFF CACHE BOOL "Enable DT turbo mode") |
| set(HW_FEATURES_TURBO_MODE OFF CACHE BOOL "Enable HW features turbo mode") |
| set(HW_FEATURES_VENDOR_FILTER "" CACHE STRING "Vendor filter for HW features") |
| set(NO_EXTERNAL_DEPS OFF CACHE BOOL "Enable serving external CSS/JS libraries locally instead of fetching from the Internet.") |
| set(DOC_TAG "development" CACHE STRING "Documentation tag") |
| set(DTS_ROOTS "${ZEPHYR_BASE}" CACHE STRING "DT bindings root folders") |
| set(DOXYGEN_FORCE_SINGLE_THREAD OFF CACHE BOOL "Enable Doxygen single thread mode") |
| |
| separate_arguments(SPHINXOPTS) |
| separate_arguments(SPHINXOPTS_EXTRA) |
| separate_arguments(LATEXMKOPTS) |
| |
| #------------------------------------------------------------------------------- |
| # Dependencies |
| |
| find_package(Doxygen REQUIRED dot) |
| |
| find_program(SPHINXBUILD sphinx-build) |
| if(NOT SPHINXBUILD) |
| message(WARNING "The 'sphinx-build' command was not found; Sphinx-based targets will not be available.") |
| endif() |
| find_program(SPHINXAUTOBUILD sphinx-autobuild) |
| |
| find_package(LATEX COMPONENTS PDFLATEX) |
| find_program(LATEXMK latexmk) |
| if(NOT LATEX_PDFLATEX_FOUND OR NOT LATEXMK) |
| message(WARNING "LaTeX components not found. PDF build will not be available.") |
| endif() |
| |
| #------------------------------------------------------------------------------- |
| # Environment & Paths |
| |
| set(SPHINX_ENV |
| DOXYGEN_EXECUTABLE=${DOXYGEN_EXECUTABLE} |
| DOT_EXECUTABLE=${DOXYGEN_DOT_EXECUTABLE} |
| DOCS_HTML_DIR=${CMAKE_CURRENT_BINARY_DIR}/html |
| DOXY_REQ_INPUT=${CMAKE_CURRENT_BINARY_DIR}/requirements/dox |
| ) |
| |
| set(DOXYGEN_CUSTOM_LINES) |
| |
| if(DEFINED ENV{ZEPHYR_DOXYGEN_OVERLAY}) |
| if(EXISTS $ENV{ZEPHYR_DOXYGEN_OVERLAY}) |
| list(APPEND DOXYGEN_CUSTOM_LINES "@INCLUDE = $ENV{ZEPHYR_DOXYGEN_OVERLAY}") |
| else() |
| message(FATAL_ERROR "Zephyr Doxygen overlay $ENV{ZEPHYR_DOXYGEN_OVERLAY} does not exist!") |
| endif() |
| endif() |
| |
| if(DOXYGEN_FORCE_SINGLE_THREAD) |
| list(APPEND DOXYGEN_CUSTOM_LINES "NUM_PROC_THREADS = 1") |
| endif() |
| |
| list(JOIN DOXYGEN_CUSTOM_LINES "\n" INCLUDE_CUSTOM_FILE) |
| |
| set(DOCS_CFG_DIR ${CMAKE_CURRENT_LIST_DIR}) |
| set(DOCS_DOCTREE_DIR ${CMAKE_CURRENT_BINARY_DIR}/doctrees) |
| set(DOCS_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) |
| set(DOCS_SRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/src) |
| set(DOCS_HTML_DIR ${CMAKE_CURRENT_BINARY_DIR}/html) |
| set(DOCS_LINKCHECK_DIR ${CMAKE_CURRENT_BINARY_DIR}/linkcheck) |
| set(DOCS_LATEX_DIR ${CMAKE_CURRENT_BINARY_DIR}/latex) |
| |
| if(WIN32) |
| set(SEP $<SEMICOLON>) |
| else() |
| set(SEP :) |
| endif() |
| |
| #------------------------------------------------------------------------------- |
| # Requirements (reqmgmt module) |
| # |
| # When the 'reqmgmt' module (the StrictDoc requirements repository) is present |
| # in the workspace, its requirements are exported to JSON and converted into |
| # reStructuredText (for Sphinx) and Doxygen (for the API docs) by the |
| # 'requirements' target. When the module is absent, only a placeholder is |
| # generated so that the strict Sphinx and Doxygen builds still succeed. |
| |
| set(GEN_REQUIREMENTS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/_scripts/gen_requirements.py) |
| set(REQ_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/requirements) |
| set(REQ_DOX_DIR ${REQ_BUILD_DIR}/dox) |
| set(REQ_RST_DIR ${DOCS_SRC_DIR}/build/requirements) |
| |
| # Requirements .dox directory consumed by the Doxygen INPUT (see |
| # zephyr.doxyfile.in). Always points at REQ_DOX_DIR; the directory is populated |
| # (possibly empty) by the 'requirements' target before Doxygen runs. |
| set(DOXY_REQ_INPUT ${REQ_DOX_DIR}) |
| |
| set(REQMGMT_FOUND FALSE) |
| if(DEFINED ZEPHYR_REQMGMT_MODULE_DIR AND |
| EXISTS ${ZEPHYR_REQMGMT_MODULE_DIR}/strictdoc_config.py) |
| find_program(STRICTDOC strictdoc) |
| if(STRICTDOC) |
| set(REQMGMT_FOUND TRUE) |
| message(STATUS "Requirements management module: ${ZEPHYR_REQMGMT_MODULE_DIR}") |
| else() |
| message(WARNING "reqmgmt module found but 'strictdoc' is not installed; " |
| "requirements will not be included in the documentation.") |
| endif() |
| else() |
| message(STATUS "Requirements management module not found; " |
| "requirements will not be included in the documentation.") |
| endif() |
| |
| if(REQMGMT_FOUND) |
| add_custom_target( |
| requirements |
| COMMAND ${STRICTDOC} export ${ZEPHYR_REQMGMT_MODULE_DIR} |
| --formats json |
| --output-dir ${REQ_BUILD_DIR} |
| COMMAND ${PYTHON_EXECUTABLE} ${GEN_REQUIREMENTS_SCRIPT} |
| --json ${REQ_BUILD_DIR}/json/index.json |
| --rst-out ${REQ_RST_DIR} |
| --dox-out ${REQ_DOX_DIR} |
| --module-present 1 |
| COMMENT "Exporting and converting requirements from reqmgmt..." |
| ) |
| else() |
| add_custom_target( |
| requirements |
| COMMAND ${PYTHON_EXECUTABLE} ${GEN_REQUIREMENTS_SCRIPT} |
| --rst-out ${REQ_RST_DIR} |
| --dox-out ${REQ_DOX_DIR} |
| --module-present 0 |
| COMMENT "reqmgmt module not present; generating placeholder requirements..." |
| ) |
| endif() |
| |
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${GEN_REQUIREMENTS_SCRIPT}) |
| |
| #------------------------------------------------------------------------------- |
| # Functions |
| |
| # Create a custom doc target. |
| # |
| # This function has the same signature as `add_custom_target()` |
| # |
| # The function will create two targets for the doc build system. |
| # - Target 1 named: `<name>` |
| # - Target 2 named: `<name>-nodeps` |
| # |
| # Both targets will produce same result, but target 2 must have no dependencies. |
| # This is useful to, e.g. re-run the Sphinx build without dependencies such as |
| # devicetree generator. |
| # |
| function(add_doc_target name) |
| add_custom_target(${name} ${ARGN}) |
| add_custom_target(${name}-nodeps ${ARGN}) |
| endfunction() |
| |
| #------------------------------------------------------------------------------- |
| # Doxygen (standalone) |
| |
| set(DOXY_OUT ${CMAKE_CURRENT_BINARY_DIR}/doxygen) |
| set(DOXYFILE_IN ${CMAKE_CURRENT_LIST_DIR}/zephyr.doxyfile.in) |
| set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/zephyr.doxyfile) |
| set(ZEPHYR_VERSION "${Zephyr_VERSION}") |
| |
| configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) |
| |
| add_custom_target( |
| doxygen |
| COMMAND |
| ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} |
| COMMENT "Running Doxygen..." |
| ) |
| |
| add_dependencies(doxygen requirements) |
| |
| set_target_properties( |
| doxygen |
| PROPERTIES |
| ADDITIONAL_CLEAN_FILES "${DOXY_OUT}" |
| ) |
| |
| #------------------------------------------------------------------------------- |
| # Doxygen Coverage |
| |
| add_custom_target( |
| doxygen-coverage |
| COMMAND ${PYTHON_EXECUTABLE} -m coverxygen |
| --xml-dir ${CMAKE_CURRENT_BINARY_DIR}/doxygen/xml/ |
| --src-dir ${ZEPHYR_BASE}/include/ |
| --output ${CMAKE_CURRENT_BINARY_DIR}/doc-coverage.info |
| COMMAND lcov |
| --remove ${CMAKE_CURRENT_BINARY_DIR}/doc-coverage.info "*/deprecated" |
| > ${CMAKE_CURRENT_BINARY_DIR}/new.info |
| COMMAND genhtml |
| --no-function-coverage |
| --no-branch-coverage |
| ${CMAKE_CURRENT_BINARY_DIR}/new.info |
| -o ${CMAKE_CURRENT_BINARY_DIR}/coverage-report |
| DEPENDS doxygen |
| COMMENT "Generating Doxygen coverage info and HTML report..." |
| ) |
| |
| add_custom_target( |
| doxygen-coverage-json |
| COMMAND ${PYTHON_EXECUTABLE} -m coverxygen |
| --xml-dir ${CMAKE_CURRENT_BINARY_DIR}/doxygen/xml/ |
| --src-dir ${ZEPHYR_BASE}/include/ |
| --format json-v3 |
| --output ${CMAKE_CURRENT_BINARY_DIR}/doc-coverage.json |
| DEPENDS doxygen |
| COMMENT "Generating Doxygen coverage info in JSON format..." |
| ) |
| |
| #------------------------------------------------------------------------------- |
| # devicetree |
| |
| set(GEN_DEVICETREE_REST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/_scripts/gen_devicetree_rest.py) |
| |
| set(DTS_ARGS) |
| foreach(root ${DTS_ROOTS}) |
| list(APPEND DTS_ARGS --dts-root ${root}) |
| endforeach() |
| |
| if(DT_TURBO_MODE) |
| list(APPEND DTS_ARGS --turbo-mode) |
| endif() |
| |
| add_custom_target( |
| devicetree |
| COMMAND ${CMAKE_COMMAND} -E env |
| PYTHONPATH=${ZEPHYR_BASE}/scripts/dts/python-devicetree/src${SEP}$ENV{PYTHONPATH} |
| ZEPHYR_BASE=${ZEPHYR_BASE} |
| ${PYTHON_EXECUTABLE} ${GEN_DEVICETREE_REST_SCRIPT} |
| --vendor-prefixes ${ZEPHYR_BASE}/dts/bindings/vendor-prefixes.txt |
| ${DTS_ARGS} |
| ${DOCS_SRC_DIR}/build/dts/api |
| VERBATIM |
| USES_TERMINAL |
| COMMENT "Generating Devicetree bindings documentation..." |
| ) |
| |
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${GEN_DEVICETREE_REST_SCRIPT}) |
| |
| #------------------------------------------------------------------------------- |
| # html |
| |
| set(SPHINX_TAGS "${DOC_TAG}") |
| if(HW_FEATURES_TURBO_MODE) |
| list(APPEND SPHINX_TAGS "hw_features_turbo") |
| endif() |
| |
| if(NO_EXTERNAL_DEPS) |
| list(APPEND SPHINX_TAGS "no-external-deps") |
| endif() |
| |
| if(REQMGMT_FOUND) |
| list(APPEND SPHINX_TAGS "reqmgmt") |
| endif() |
| |
| set(SPHINX_TAGS_ARGS "") |
| foreach(tag ${SPHINX_TAGS}) |
| list(APPEND SPHINX_TAGS_ARGS "-t" "${tag}") |
| endforeach() |
| |
| if(HW_FEATURES_VENDOR_FILTER) |
| list(JOIN HW_FEATURES_VENDOR_FILTER "," vendor_filter) |
| list(APPEND SPHINXOPTS "-D" "zephyr_hw_features_vendor_filter=${vendor_filter}") |
| endif() |
| |
| if(SPHINXBUILD) |
| add_doc_target( |
| html |
| COMMAND ${CMAKE_COMMAND} -E env ${SPHINX_ENV} OUTPUT_DIR=${DOCS_HTML_DIR} |
| ${SPHINXBUILD} |
| -b html |
| -c ${DOCS_CFG_DIR} |
| -d ${DOCS_DOCTREE_DIR} |
| -w ${DOCS_BUILD_DIR}/html.log |
| ${SPHINX_TAGS_ARGS} |
| ${SPHINXOPTS} |
| ${SPHINXOPTS_EXTRA} |
| ${DOCS_SRC_DIR} |
| ${DOCS_HTML_DIR} |
| USES_TERMINAL |
| COMMENT "Running Sphinx HTML build..." |
| ) |
| |
| set_target_properties( |
| html html-nodeps |
| PROPERTIES |
| ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_HTML_DIR};${DOCS_DOCTREE_DIR}" |
| ) |
| |
| add_dependencies(html devicetree requirements) |
| endif() |
| |
| #------------------------------------------------------------------------------- |
| # html-live |
| |
| if(SPHINXBUILD) |
| add_doc_target( |
| html-live |
| COMMAND ${CMAKE_COMMAND} -E env ${SPHINX_ENV} OUTPUT_DIR=${DOCS_HTML_DIR} |
| ${SPHINXAUTOBUILD} |
| --watch ${DOCS_CFG_DIR} |
| --ignore ${DOCS_BUILD_DIR} |
| -b html |
| -c ${DOCS_CFG_DIR} |
| -d ${DOCS_DOCTREE_DIR} |
| -w ${DOCS_BUILD_DIR}/html.log |
| ${SPHINX_TAGS_ARGS} |
| ${SPHINXOPTS} |
| ${SPHINXOPTS_EXTRA} |
| ${DOCS_SRC_DIR} |
| ${DOCS_HTML_DIR} |
| USES_TERMINAL |
| COMMENT "Running Sphinx HTML autobuild..." |
| ) |
| |
| set_target_properties( |
| html-live html-live-nodeps |
| PROPERTIES |
| ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_HTML_DIR};${DOCS_DOCTREE_DIR}" |
| ) |
| |
| add_dependencies(html-live devicetree requirements) |
| endif() |
| #------------------------------------------------------------------------------- |
| # pdf |
| |
| if(SPHINXBUILD) |
| add_doc_target( |
| latex |
| COMMAND ${CMAKE_COMMAND} -E env ${SPHINX_ENV} OUTPUT_DIR=${DOCS_LATEX_DIR} |
| ${SPHINXBUILD} |
| -b latex |
| -c ${DOCS_CFG_DIR} |
| -d ${DOCS_DOCTREE_DIR} |
| -w ${DOCS_BUILD_DIR}/latex.log |
| ${SPHINX_TAGS_ARGS} |
| -t convertimages |
| ${SPHINXOPTS} |
| ${SPHINXOPTS_EXTRA} |
| ${DOCS_SRC_DIR} |
| ${DOCS_LATEX_DIR} |
| USES_TERMINAL |
| COMMENT "Running Sphinx LaTeX build..." |
| ) |
| |
| set_target_properties( |
| latex latex-nodeps |
| PROPERTIES |
| ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_LATEX_DIR};${DOCS_DOCTREE_DIR}" |
| ) |
| |
| add_dependencies(latex devicetree requirements) |
| endif() |
| |
| if(SPHINXBUILD AND LATEX_PDFLATEX_FOUND AND LATEXMK) |
| if(WIN32) |
| set(PDF_BUILD_COMMAND "make.bat") |
| else() |
| find_program(MAKE make) |
| if(NOT MAKE) |
| message(FATAL_ERROR "The 'make' command was not found") |
| endif() |
| set(PDF_BUILD_COMMAND ${MAKE}) |
| endif() |
| |
| add_custom_target( |
| pdf |
| COMMAND ${CMAKE_COMMAND} -E env LATEXMKOPTS="${LATEXMKOPTS}" |
| ${PDF_BUILD_COMMAND} |
| WORKING_DIRECTORY ${DOCS_LATEX_DIR} |
| COMMENT "Building PDF file..." |
| USES_TERMINAL |
| ) |
| |
| add_dependencies(pdf latex) |
| endif() |
| |
| #------------------------------------------------------------------------------- |
| # linkcheck |
| |
| if(SPHINXBUILD) |
| add_doc_target( |
| linkcheck |
| COMMAND ${CMAKE_COMMAND} -E env ${SPHINX_ENV} OUTPUT_DIR=${DOCS_LINKCHECK_DIR} |
| ${SPHINXBUILD} |
| -b linkcheck |
| -c ${DOCS_CFG_DIR} |
| -d ${DOCS_DOCTREE_DIR} |
| -w ${DOCS_BUILD_DIR}/linkcheck.log |
| ${SPHINX_TAGS_ARGS} |
| ${SPHINXOPTS} |
| ${SPHINXOPTS_EXTRA} |
| ${DOCS_SRC_DIR} |
| ${DOCS_LINKCHECK_DIR} |
| USES_TERMINAL |
| COMMENT "Running Sphinx link check..." |
| ) |
| |
| set_target_properties( |
| linkcheck linkcheck-nodeps |
| PROPERTIES |
| ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_LINKCHECK_DIR};${DOCS_DOCTREE_DIR}" |
| ) |
| |
| add_dependencies(linkcheck devicetree requirements) |
| endif() |
| |
| #------------------------------------------------------------------------------- |
| # others |
| |
| add_custom_target( |
| pristine |
| COMMAND ${CMAKE_COMMAND} -P ${ZEPHYR_BASE}/cmake/pristine.cmake |
| ) |