You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多目标CMake项目如何用doxygen_add_docs()构建时生成统一文档

问题描述

项目结构

myproject/
├─ build/
├─ cmake/
│  └─ DoxygenFun.cmake
├─ docs/
├─ src/
│  ├─ CMakeLists.txt
│  ├─ superlib/
│  │  ├─ CMakeLists.txt
│  │  ├─ lib1/
│  │  │  ├─ include/
│  │  │  │  └─ lib1.h
│  │  │  ├─ lib1.cpp
│  │  │  └─ CMakeLists.txt
│  │  └─ lib2/
│  │     ├─ include/
│  │     │  └─ lib2.h
│  │     ├─ lib2.cpp
│  │     └─ CMakeLists.txt
│  └─ exec/
│     ├─ main.cpp
│     ├─ aux.h
│     └─ CMakeLists.txt
└─ CMakeLists.txt

项目说明:

  • superlib包含lib1、lib2两个库(lib2依赖lib1),通过add_library()定义
  • exec是依赖lib2的可执行程序,通过add_executable()定义
  • 各层级CMakeLists.txt仅包含add_subdirectory()指令

当前Doxygen配置问题

DoxygenFun.cmake中定义的函数:

function(DoxygenFun target input)
  set(DOXYGEN_HTML_OUTPUT            ${PROJECT_BINARY_DIR}/docs) # ?????
  set(DOXYGEN_JAVADOC_AUTOBRIEF      YES)
  set(DOXYGEN_GENERATE_HTML          YES)
  set(DOXYGEN_HAVE_DOT               YES)

# other DOXYGEN_... options

  doxygen_add_docs(doxygen-${target}
      ${input}
      ALL  # add to the default build target
      COMMENT "Generate HTML documentation"
      )
endfunction()

顶层CMakeLists.txt:

cmake_minimum_required(VERSION 3.24)
project(myproject VERSION 0.1.0 LANGUAGES CXX)

list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")

find_package(Doxygen REQUIRED dot)
include(DoxygenFun)

add_subdirectory(src bin)

add_custom_target(doc_doxygen ALL
    COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/docs
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
)

现在每个目标的CMakeLists.txt都调用DoxygenFun(targetname ${CMAKE_CURRENT_SOURCE_DIR}),导致:

  1. 每个目标在各自的${CMAKE_CURRENT_BINARY_DIR}生成单独的Doxyfile,自定义的doc_doxygen目标无效
  2. 手动运行各Doxyfile时,生成的HTML文档会互相覆盖

用户疑问:

  • 是否误解了doxygen_add_docs()的用法?
  • 是否需要收集所有源文件和头文件,仅调用一次doxygen_add_docs()?对应的目标应该是什么?
  • 是否需要在docs目录下添加CMakeLists.txt并在顶层文件中调用add_subdirectory(docs)?

解决方案

关于doxygen_add_docs()的用法误解

没错,你确实误解了这个函数的用法:doxygen_add_docs()会为每次调用生成独立的Doxyfile和构建目标,多次调用就会生成多个独立的文档构建流程,这就是为什么会出现多份Doxyfile、文档互相覆盖的问题。

正确的实现方式:单调用生成统一文档

不需要在每个目标里调用DoxygenFun,应该收集全项目的源文件和头文件,仅调用一次doxygen_add_docs(),具体步骤如下:

  1. 移除顶层无效的自定义目标
    删掉顶层CMakeLists.txt里的doc_doxygen自定义目标,因为doxygen_add_docs()已经可以生成对应的构建目标,无需手动调用DOXYGEN_EXECUTABLE。

  2. 收集全项目的源文件
    在顶层CMakeLists.txt中,添加代码收集所有需要生成文档的文件:

# 收集项目内的所有头文件和源文件,CONFIGURE_DEPENDS让CMake自动检测文件变化
file(GLOB_RECURSE DOC_SOURCES CONFIGURE_DEPENDS
    ${PROJECT_SOURCE_DIR}/src/**/*.h
    ${PROJECT_SOURCE_DIR}/src/**/*.cpp
)

如果有不需要包含的文件,可以用list(REMOVE_ITEM)剔除。

  1. 调用DoxygenFun生成统一文档
    在顶层CMakeLists.txt中,调用DoxygenFun一次即可:
DoxygenFun(myproject "${DOC_SOURCES}")
  1. 调整DoxygenFun函数
    确保输出路径正确,还可以添加项目名称和版本的配置,修改后的函数:
function(DoxygenFun target input)
  set(DOXYGEN_HTML_OUTPUT            ${PROJECT_BINARY_DIR}/docs)
  set(DOXYGEN_JAVADOC_AUTOBRIEF      YES)
  set(DOXYGEN_GENERATE_HTML          YES)
  set(DOXYGEN_HAVE_DOT               YES)
  # 添加项目标识配置
  set(DOXYGEN_PROJECT_NAME           ${PROJECT_NAME})
  set(DOXYGEN_PROJECT_VERSION        ${PROJECT_VERSION})

  # other DOXYGEN_... options

  doxygen_add_docs(doxygen-${target}
      ${input}
      ALL  # 添加到默认构建目标,执行make/all时自动生成文档
      COMMENT "Generate unified HTML documentation for ${PROJECT_NAME}"
      )
endfunction()

关于docs目录的处理

不需要在docs目录添加CMakeLists.txt和调用add_subdirectory(docs),除非你需要在该目录放置自定义的Doxygen配置模板(比如Doxyfile.in),但当前的方式已经足够生成统一文档。

额外优化建议

  • 如果项目文件固定,也可以手动列出所有需要的文件,避免GLOB_RECURSE意外包含临时文件;如果文件经常变动,GLOB_RECURSE配合CONFIGURE_DEPENDS更方便。
  • 如果需要单独为某个库生成文档,可以保留局部的DoxygenFun调用,但要修改DOXYGEN_HTML_OUTPUT为不同的子目录(比如${PROJECT_BINARY_DIR}/docs/lib1),避免覆盖。

内容的提问来源于stack exchange,提问作者Breno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:17:37