Sphinx 找不到 Doxygen 导出的 xml 中的内容的解决方法

Sphinx + Breathe + Doxygen + CMake 的教程看这个就够了

https://devblogs.microsoft.com/cppblog/clear-functional-c-documentation-with-sphinx-breathe-doxygen-cmake/

但是他还是少写了一些东西,所以还是有一些小坑的

这些坑会导致 Sphinx 找不到 Doxygen 导出的 xml 中的内容,或者是报错

第一个是 conf.py 可能一直找不到 sphinx_rtd_theme 这个 module,即使你更新了 pip,重新下载了 sphinx_rtd_theme 好多遍,也没有办法

这个原因很简单,就是因为他没有找到你的 python 下载包的路径

我的 cmake 配置如下,主要是设置了一个虚拟环境,放在输出目录中,这样我们就可以不污染主机的 python 环境,也可以清楚地知道自己的包下载到哪里了

projectRoot/CMakeLists.txt

cmake 复制代码
...

# Docs only available if this is the main app
find_package(Doxygen)
if(Doxygen_FOUND)
    message(STATUS "Found Doxygen, building docs")
    add_subdirectory(docs)
else()
    message(STATUS "Doxygen not found, not building docs")
endif()

projectRoot/docs/CMakeLists.txt

cmake 复制代码
option(BUILD_DOCS_USE_VENV "Generate Python virtual environment" ON)

find_package(Python COMPONENTS Interpreter REQUIRED)
if (BUILD_DOCS_USE_VENV)
    set(DOCS_VENV "${CMAKE_CURRENT_BINARY_DIR}/venv")
    message(STATUS "Creating Python venv at ${DOCS_VENV}")
    execute_process(COMMAND ${Python_EXECUTABLE} -m venv ${DOCS_VENV})
    set(ENV{VIRTUAL_ENV} ${DOCS_VENV})
    set(Python_FIND_VIRTUALENV FIRST)
    unset(Python_EXECUTABLE)
    find_package(Python COMPONENTS Interpreter REQUIRED)

    execute_process(
        COMMAND ${Python_EXECUTABLE} -m pip install --no-cache wheel
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        COMMAND_ERROR_IS_FATAL ANY
    )
    execute_process(
        COMMAND ${Python_EXECUTABLE} -m pip install --no-cache -r requirements.txt
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        COMMAND_ERROR_IS_FATAL ANY
    )
endif()

execute_process(
    COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../helper/req_check.py requirements.txt
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMMAND_ERROR_IS_FATAL ANY
)

find_program(SPHINX_EXECUTABLE sphinx-build HINTS ${DOCS_VENV}/Scripts ${DOCS_VENV}/bin REQUIRED)
message(STATUS "Found Sphinx: ${SPHINX_EXECUTABLE}")

# Find all the public headers from runtime
get_target_property(RUNTIME_PUBLIC_HEADER_DIR ${RUNTIME_NAME} INTERFACE_INCLUDE_DIRECTORIES)
file(GLOB_RECURSE RUNTIME_PUBLIC_HEADERS CONFIGURE_DEPENDS ${RUNTIME_PUBLIC_HEADER_DIR}/*.h)

# Find all the public headers from editor
get_target_property(EDITOR_PUBLIC_HEADER_DIR ${EDITOR_NAME} INTERFACE_INCLUDE_DIRECTORIES)
file(GLOB_RECURSE EDITOR_PUBLIC_HEADERS CONFIGURE_DEPENDS ${EDITOR_PUBLIC_HEADER_DIR}/*.h)

message(--------------)
message(STATUS "${RUNTIME_PUBLIC_HEADERS}")
message(STATUS "${EDITOR_PUBLIC_HEADERS}")
message(--------------)

set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR}/src)
set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doxygen)
set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/xml/index.xml)
set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)

# Replace variables inside @@ with the current values
configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY)

# Doxygen won't create this for us
file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR})

# Only regenerate Doxygen when the Doxyfile or public headers change
add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE}
                   DEPENDS ${RUNTIME_PUBLIC_HEADERS} ${EDITOR_PUBLIC_HEADERS}
                   COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT}
                   MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN}
                   COMMENT "Generating docs"
                   VERBATIM)

# Nice named target so we can run the job easily
add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE})

set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/sphinx)
set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html)

# Only regenerate Sphinx when:
# - Doxygen has rerun
# - Our doc files have been updated
# - The Sphinx config has been updated
add_custom_command(OUTPUT ${SPHINX_INDEX_FILE}
                   COMMAND 
                     ${SPHINX_EXECUTABLE} -b html
                     # Tell Breathe where to find the Doxygen output
                     -Dbreathe_projects.MeowEngine=${DOXYGEN_OUTPUT_DIR}/xml
                   ${SPHINX_SOURCE} ${SPHINX_BUILD}
                   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
                   DEPENDS
                   # Other docs files you want to track should go here (or in some variable)
                   ${CMAKE_CURRENT_SOURCE_DIR}/index.rst
                   ${DOXYGEN_INDEX_FILE}
                   MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py
                   COMMENT "Generating documentation with Sphinx")

# Nice named target so we can run the job easily
add_custom_target(Sphinx ALL DEPENDS ${SPHINX_INDEX_FILE})

# Add an install target to install the docs
include(GNUInstallDirs)
install(DIRECTORY ${SPHINX_BUILD}
DESTINATION ${CMAKE_INSTALL_DOCDIR})

其中,获取 Doxygen 所需要的头文件那里,那里是我自己的项目的情况,一个 runtime 一个 engine,这个具体实现因项目而异

然后我们现在已经知道自己下载的包在哪里了,我们就在 conf.py 中直接把这个路径写进去

projectRoot/docs/conf.py

python 复制代码
import sys
from pathlib import Path

sys.path.insert(0, str(Path('../build/docs/venv/Lib/site-packages/').resolve()))

然后还有一点坑的就是,在 conf.py 中我们要写明 breathe 的项目的名称和对应的 doxygen 输出的 xml 的位置:

projectRoot/docs/conf.py

python 复制代码
breathe_projects = {
    "MeowEngine": "../build/docs/doxygen/xml"
}

完整的 conf.py

projectRoot/docs/conf.py

python 复制代码
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

import sys
from pathlib import Path

sys.path.insert(0, str(Path('../build/docs/venv/Lib/site-packages/').resolve()))

import sphinx_rtd_theme

project = 'MeowEngine'
copyright = '2023, CheapMeow'
author = 'CheapMeow'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = ['sphinx_rtd_theme', 'breathe']

breathe_projects = {
    "MeowEngine": "../build/docs/doxygen/xml"
}

templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_static_path = ['_static']

如果现在 sphinx 还是没有办法找到你的类的话,可能是你没有写明命名空间

projectRoot/docs/index.rst

rst 复制代码
.. doxygenclass:: Meow::MeowEngine
   :project: MeowEngine
   :members:

因为你可以看到 xml 里面的输出是带着命名空间的

projectRoot/build/docs/doxygen/xml/class_meow_1_1_meow_engine.xml

xml 复制代码
  <compounddef id="class_meow_1_1_meow_engine" kind="class" language="C++" prot="public">
    <compoundname>Meow::MeowEngine</compoundname>
相关推荐
武子康2 天前
Java-39 深入浅出 Spring - AOP切面增强 核心概念 通知类型 XML+注解方式 附代码
xml·java·大数据·开发语言·后端·spring
Ll13045252984 天前
基于 COM 的 XML 解析技术(MSXML) 的总结
xml
在代码的海洋中寻找亚特兰蒂斯4 天前
AJAX对于XML和JSON的处理
xml·ajax·json
BinField6 天前
ToolsSet之:XML工具
xml·windows·microsoft
SEO-狼术6 天前
Connect Directly to Oracle XML Data
xml·数据库·oracle
YSoup6 天前
2025年目前最新版本Android Studio自定义xml预览的屏幕分辨率
android·xml·android studio
abcnull7 天前
mybatis的mapper对应的xml写法
xml·sql·spring·mybatis·mapper
Blue桃之夭夭7 天前
HTML、XML、JSON 是什么?有什么区别?又是做什么的?
xml·html·json
小于村7 天前
pom.xml 文件中配置你项目中的外部 jar 包打包方式
xml·java·jar
扶风呀7 天前
pom.xml中标签详解_
xml