文档生成工具:使用FetchContent下载Doxygen、Sphinx、MkDocs

说实话,很多C++项目做完了,文档却一塌糊涂。我见过太多团队,代码写得挺漂亮,但README就几句话,API文档更是没有。你想想看,一个项目如果没有好文档,别人怎么用?半年后你自己都可能看不懂。

我个人习惯,在项目初期就把文档工具链集成进来。用CMake的FetchContent,可以一键拉取Doxygen、Sphinx、MkDocs这些工具。今天我就跟你聊聊,怎么用FetchContent搞定文档生成。

为什么要在CMake里管文档?

你可能觉得,文档工具单独装不就行了?嗯,我以前也这么想。直到有一次,新同事入职,折腾了半天装Doxygen,版本还不一致,生成的文档格式乱七八糟。

用FetchContent的好处很明显:

  • 版本锁定——整个团队用同一个版本,不会出现「我本地能生成,你那边不行」
  • 一键构建——cmake --build . 的时候,文档也顺带生成了
  • CI/CD友好——流水线上不用额外安装工具,CMake自己拉

核心思路:把文档工具当作项目的「构建依赖」,而不是「环境依赖」。

用FetchContent下载Doxygen

Doxygen是C++文档的老牌工具。我从2008年开始用,那时候还是命令行手动跑。现在用CMake集成,方便太多了。

include(FetchContent)

FetchContent_Declare(
  doxygen
  GIT_REPOSITORY https://github.com/doxygen/doxygen.git
  GIT_TAG Release_1_9_8
  GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(doxygen)

# 设置Doxygen可执行路径
set(DOXYGEN_EXECUTABLE ${doxygen_SOURCE_DIR}/build/bin/doxygen)

这里有个坑,我踩过。Doxygen本身是用CMake构建的,所以FetchContent拉下来后,你得先编译它。可以加个自定义目标:

# 编译Doxygen
ExternalProject_Add(
  doxygen_build
  SOURCE_DIR ${doxygen_SOURCE_DIR}
  CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/doxygen_install
  BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/doxygen_install/bin/doxygen
)

add_dependencies(doxygen_build doxygen)

小技巧:如果不想每次都编译Doxygen,可以用GIT_SHALLOW TRUE只拉最新提交,减少下载时间。

集成Sphinx生成API文档

Sphinx本来是Python文档工具,但配合Breathe插件,可以解析Doxygen的XML输出,生成漂亮的HTML文档。我在一个嵌入式项目里用过这套组合,效果不错。

FetchContent_Declare(
  sphinx
  GIT_REPOSITORY https://github.com/sphinx-doc/sphinx.git
  GIT_TAG v7.2.6
  GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(sphinx)

# 安装Sphinx依赖
execute_process(
  COMMAND ${Python3_EXECUTABLE} -m pip install -r 
          ${sphinx_SOURCE_DIR}/requirements.txt
  WORKING_DIRECTORY ${sphinx_SOURCE_DIR}
)

为什么要用FetchContent拉Sphinx?直接pip安装不行吗?

说实话,也可以。但如果你在离线环境或者内网开发,FetchContent配合Git仓库镜像,比配pip源要省心。我曾经在一个军工项目里,网络完全隔离,所有依赖都得走内部GitLab,这时候FetchContent就派上大用场了。

MkDocs:轻量级文档利器

MkDocs适合写项目手册、用户指南这类非API文档。它用Markdown写,生成静态HTML,风格简洁。

FetchContent_Declare(
  mkdocs
  GIT_REPOSITORY https://github.com/mkdocs/mkdocs.git
  GIT_TAG 1.5.3
  GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(mkdocs)

# 创建MkDocs构建目标
add_custom_target(mkdocs_build
  COMMAND ${Python3_EXECUTABLE} -m mkdocs build
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
  COMMENT "Building MkDocs documentation..."
)

注意:MkDocs需要Python环境。确保你的系统上有Python3,并且在CMake中find_package(Python3)成功了。

三合一:统一文档生成目标

我建议把三个工具整合成一个目标,一键生成所有文档:

add_custom_target(docs ALL
  COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/Doxyfile
  COMMAND ${Python3_EXECUTABLE} -m sphinx -b html 
          ${CMAKE_SOURCE_DIR}/docs/sphinx ${CMAKE_BINARY_DIR}/docs/sphinx
  COMMAND ${Python3_EXECUTABLE} -m mkdocs build 
          -f ${CMAKE_SOURCE_DIR}/docs/mkdocs.yml
  COMMENT "Generating all documentation..."
  DEPENDS doxygen_build sphinx_build mkdocs_build
)

这样,你只需要运行 cmake --build . --target docs,三份文档就都生成了。

知识体系总览

下面这张图,帮你理清三个工具的关系和分工:

CMake FetchContent 文档工具集成 FetchContent Doxygen Sphinx + Breathe MkDocs 输出:XML / HTML 输出:HTML / PDF 输出:静态HTML API文档 / 代码注释 API文档 + 手册 用户指南 / 教程 统一构建目标:cmake --build . --target docs

版本管理策略

用FetchContent管理文档工具,版本控制是关键。我建议这样组织:

工具 推荐版本 GIT_TAG写法 备注
Doxygen 1.9.8 Release_1_9_8 稳定版,支持C++20
Sphinx 7.2.x v7.2.6 配合Breathe 4.35+
MkDocs 1.5.x 1.5.3 轻量,适合小团队

我的习惯:在项目根目录放一个 docs/versions.cmake 文件,专门定义这些版本号。这样升级版本时,只改一个文件。

避坑指南

用FetchContent下载文档工具,有几个坑我帮你踩过了:

  • 编译Doxygen很慢——第一次构建可能要10分钟。建议用GIT_SHALLOW TRUE,并且把doxygen_build加到CI的缓存里。
  • Python依赖冲突——Sphinx和MkDocs都用Python,如果系统里已经装了其他版本,可能打架。我建议用虚拟环境,或者在CMake里指定Python解释器路径。
  • 文档生成顺序——先跑Doxygen生成XML,再跑Sphinx解析。顺序错了,Sphinx会报错。用add_dependencies确保依赖关系。

我曾经在一个项目里,因为忘了设置GIT_SHALLOW,CI每次构建都拉Doxygen的完整历史,足足800MB。后来改成浅克隆,构建时间从15分钟降到了3分钟。嗯,细节决定成败。

总结

用FetchContent管理文档工具,说白了就是把「环境依赖」变成「构建依赖」。团队里每个人只要装了CMake和Python,就能一键生成文档。版本统一,流程自动化,省心省力。

你想想看,如果每个项目都能这样,文档质量是不是能提升一大截?


公众号:蓝海资料掘金营,微信 deep3321