doxygen代码文档

导入

上篇博客讲到了项目如何发布,虽然隔了好久,还是想讲一下doxygen。doxygen是一个代码文档生成工具,根据特定的注释语法自动生成。相信读者都看过很多的开源项目的API文档,doxygen就可以生成这种在线文档效果,通过浏览器查看,也可以用是LaTeX格式。这是跟项目发布息息相关的,项目发布,尤其是闭源项目的话,API文档是开发者了解项目的最重要途径,因此必须清晰且完善。而对于开源项目,重要性也是一样得,很多开发者发布的开源项目,就一个简单README.md,其他没有任何的文档,让使用者很是头疼,还需要慢慢看代码才行。

API文档只是暴露API函数,不暴露内部函数,因此doxygen是可以选择你想暴露的函数的,如果完全暴露,此时代码文档就相当于一个清晰的代码阅读器,每个文件包含哪些类,包含哪些函数,位于源代码多少行,参数返回值作用,异常值等情况,让读者看代码更加高效。

简单语法

doxygen整体是非常简单的,主要还是知不知道使用,详细的语法可以去官网查看,这里简单的说明几个关键语法:

  • 文件注释:在每个文件的开头,使用 /*! 或 /** 开始一个文档块,描述文件的总体信息,包括作者、日期、文件描述等
  /*!
 * @file   example.cpp
 * @brief  这里是对本文件的简要描述
 * @author Your Name
 * @date   YYYY-MM-DD
 */
  • 类和结构体注释:在每个类或结构体声明之前,使用 /*! 或 /** 开始一个文档块,描述该类或结构体的用途、属性等
  /**
 * @class   ExampleClass
 * @brief   这里是类的简要描述
 *
 * 更详细的描述可以放在这里,包括类的用途、注意事项等。
 *
 * @author Your Name
 * @date   YYYY-MM-DD
 */
class ExampleClass {
    // ...
};
  • 函数注释:在每个函数声明或定义之前,使用 /*! 或 /** 开始一个文档块,描述函数的功能、参数、返回值等,常见还有@node 和 @excpetion表示注解和异常。
  /**
 * @brief   函数的简要描述
 * @param   param1 描述参数1
 * @param   param2 描述参数2
 * @return  描述返回值
 */
int exampleFunction(int param1, int param2) {
    // ...
}
  • 代码段:@code … @endcode 用于在文档中插入代码段,保持原始格式
  /**
 * @par	示例代码:
 * @code{.cpp}
 * int main() {
 *     return 0;
 * }
 * @endcode
 */
  • TODO和 FIXME:在代码中使用 @todo 和 @fixme 标记未完成的任务或需要修复的问题
  /**
 * @todo 实现这个函数
 */
void unfinishedFunction() {
    // ...
}
  • 编号列表:使用 -# 来创建编号列表
  /**
 * 操作步骤:
 * -# 第一步
 * -# 第二步
 * -# 第三步
 */
  • 创建链接:@link … @endlink 用于创建指向文档内部或外部资源的链接
  /**
 * 更多信息请参见 @link http://www.example.com 这里 @endlink。
 */

例子


/**
 * @file example.cpp
 * @brief 一个简单的数学运算示例程序
 * @author cryer
 * @date 2017-10-3
 */

#include <iostream>
#include <cmath>

/**
 * @brief 计算两个数的和
 * @param a 第一个加数
 * @param b 第二个加数
 * @return 两个数的和
 */
double add(double a, double b) {
    return a + b;
}

/**
 * @brief 计算两个数的差
 * @param a 被减数
 * @param b 减数
 * @return 两个数的差
 */
double subtract(double a, double b) {
    return a - b;
}

/**
 * @brief 计算平方根
 * @param x 需要计算平方根的数
 * @return 平方根值
 * @note 如果x为负数,将返回NaN
 */
double squareRoot(double x) {
    return sqrt(x);
}

/**
 * @brief MathOperations类提供基本数学运算
 */
class MathOperations {
public:
    /**
     * @brief 计算两个数的乘积
     * @param a 第一个因数
     * @param b 第二个因数
     * @return 两个数的乘积
     */
    double multiply(double a, double b) {
        return a * b;
    }

    /**
     * @brief 计算两个数的商
     * @param a 被除数
     * @param b 除数
     * @return 两个数的商
     * @exception std::invalid_argument 当除数为0时抛出
     */
    double divide(double a, double b) {
        if (b == 0) {
            throw std::invalid_argument("除数不能为0");
        }
        return a / b;
    }
};

/**
 * @brief 程序入口点
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return 程序退出状态码
 */
int main(int argc, char* argv[]) {
    MathOperations math;
    
    std::cout << "5 + 3 = " << add(5, 3) << std::endl;
    std::cout << "5 - 3 = " << subtract(5, 3) << std::endl;
    std::cout << "5 * 3 = " << math.multiply(5, 3) << std::endl;
    
    try {
        std::cout << "5 / 3 = " << math.divide(5, 3) << std::endl;
        std::cout << "5 / 0 = " << math.divide(5, 0) << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << std::endl;
    }
    
    std::cout << "√25 = " << squareRoot(25) << std::endl;
    
    return 0;
}


现在为这个简单的C++代码生成代码文档。官网下载doxygen后,使用GUI操作即可,也可以手动编写Doxyfile,然后doxygen -g Doxyfile编译,但是GUI界面更加直观。

开始界面是这样的,配置好以下几点:

  • 工作目录就是配置文件Doxyfile的保存目录,方便下次直接加载配置,设置成项目根目录即可

  • 文档名,版本,源代码目录按实际情况设置即可,输出目录建议设置成项目根目录下doc文件夹

然后选择Mode选项,,设置抽取所有实体和C++优化,因为是C++项目

Output目录选择输出格式,选择HTML即可,需要需要LaTeX可以选择LaTeX,只不过需要额外再编译一下。

最后图标标签,可以使用内置的图表生成器,也可以另外安装GraphViz,使用更加精细的图表。

然后切换到Expert选项,设置输出文档的语言,这里我就选中文

还有一个要注意的地方就是Build选项下的Extract ALL,这是默认打勾的,当我们开源发布项目的时候都会选这个,如果是闭源,只发布API文档的话,这个就要去掉,另外还要配置关闭源代码浏览,隐藏文件列表等,这里只说明开源项目。

最后切换到Run选项下运行即可再doc目录下生成HTML文件夹。

效果

打开HTML文件夹中的index.html

这个界面是不是有熟悉的感觉了,像openCV之类的API文档差不多都是这个样子的,都可以用doxygen来生成。右侧截图之外还有搜索栏,可以直接搜索想要查看的函数。

具体的函数样式如下:

可以看到之前代码中使用的doxygen的语法效果,注解就是@note语法的效果。

总结

代码文档可以说是一个项目的脸面,作者觉得对于任何的工程项目,代码文档是必须要写好的,而且从上面不难看出,使用doxygen写文档也并不复杂。