Doxgen的安装与使用!
Doxgen的安装与使用
背景:使用CCS开发DSP工程时,当随着工程逐渐增大,代码的可读性时逐渐下降的。此时如何能够快速的了解代码工程就显得尤为重要。如果能够解决这个问题,或许也能够约束代码编写时的格式不统一的问题。提升代码的编写质量和可读性。
参考:
Eclipse Doxygen Installation also Code Composer Studio v5.x (coder-tronics.com)
callgraph工具, 函数调用关系 | cflow, egypt 和 doxygen 使用 - whilewell - 博客园 (cnblogs.com)
相关插件工具:
实现:
首先参考了第一条的安装过程,先下载并安装了doxygen(1.12.0)软件,并且在CCS的市场中安装了插件eclox(0.13.0)
然后使用对应插件,并配置对应的doxygen工具的安装目录,使用插件建立得到一份doxygen.file文件
编译boxygen文件得到对应的html文件
安装Graphviz工具,手动配置对应工具的bin文件夹路径,然后指定生成图片的格式,深度等细节,再次编译doxygen文件。
重新查看对应的html文件,可以看到对应的说明文件已经更新了插图。(SVG格式比PNG格式要清晰)
参考
能根据代码给出函数调用关系的工具
有一些工具可以分析代码并生成函数调用关系图,帮助你理解代码的结构和函数之间的依赖关系。以下是几种常用的工具:
1. Doxygen
支持语言:C/C++、Java、Python 等多种语言。
功能:Doxygen 是一个自动生成文档的工具,可以分析代码并生成函数调用关系图。它可以输出多种格式,包括 HTML、LaTeX 和 XML。如果你启用
CALL_GRAPH
和CALLER_GRAPH
选项,它还能为每个函数生成调用者和被调用者的图。使用方法:
编写配置文件
Doxyfile
。在
Doxyfile
中启用CALL_GRAPH = YES
和CALLER_GRAPH = YES
。运行 Doxygen,它会生成包含函数调用关系的文档。
2. Gprof
支持语言:C/C++。
功能:Gprof 是一个性能分析工具,能生成程序的函数调用图。它主要用于检测程序的性能瓶颈,但也能展示函数之间的调用关系。
使用方法:
编译程序时加上
-pg
选项生成可执行文件。运行程序,生成
gmon.out
文件。使用
gprof
分析gmon.out
文件,查看函数调用关系。
3. Cscope
支持语言:C/C++。
功能:Cscope 是一个交互式的代码浏览工具,可以查找函数的定义、调用、全局变量等信息,适合分析大规模的 C/C++ 项目。
使用方法:
生成索引文件:
cscope -R
。在 Cscope 的交互界面中查找函数调用关系。
4. Code2flow
支持语言:Python、JavaScript、Ruby、PHP 等。
功能:Code2flow 是一个简单的工具,可以从代码中生成流程图和调用图,适用于不需要深度分析的小项目。
使用方法:
安装
code2flow
。运行
code2flow your_file.py
,工具会生成相应的调用图。
5. Callgrind (结合 KCachegrind 使用)
支持语言:C/C++。
功能:Callgrind 是 Valgrind 的一个工具,专门用于分析函数调用关系和性能。生成的报告可以用 KCachegrind 可视化,展示函数调用的详细图谱。
使用方法:
使用
valgrind --tool=callgrind ./your_program
运行程序。生成的
callgrind.out
文件可以使用kcachegrind
查看调用关系。
这些工具各有特点,适合不同语言和场景的需求。如果你是在做 C/C++ 项目,可以考虑 Doxygen 和 Gprof。如果是其他语言,Code2flow 和 Cscope 也是不错的选择。你可以根据具体情况选择合适的工具。
Doxygen生成函数调用图
Doxygen 是一个非常强大的文档生成工具,它不仅可以为代码生成文档,还可以生成函数调用图。要生成函数调用图,必须正确配置 Doxygen。以下是如何使用 Doxygen 生成函数调用图的详细步骤:
1. 安装 Doxygen
首先,你需要确保 Doxygen 已安装在你的系统中。你可以通过以下方式进行安装:
Windows:可以从 Doxygen官网 下载可执行安装文件。
Linux:通过包管理器安装,例如:
sudo apt-get install doxygen graphviz
macOS:使用 Homebrew 安装:
brew install doxygen graphviz
Graphviz 是一个用于生成图的工具,Doxygen 生成调用图时依赖于它。因此,你还需要安装 Graphviz。
2. 配置 Doxygen
Doxygen 通过配置文件
Doxyfile
来控制生成文档的行为。你可以通过以下方式生成该文件:doxygen -g
这将创建一个名为
Doxyfile
的默认配置文件。3. 修改
Doxyfile
配置文件打开
Doxyfile
,并根据需要修改以下选项以启用函数调用图的生成:启用调用图和调用者图:
CALL_GRAPH = YES # 生成函数的调用图(显示被哪些函数调用) CALLER_GRAPH = YES # 生成函数的调用者图(显示调用了哪些函数)
启用图形输出格式:
HAVE_DOT = YES # 确保 Graphviz 的 dot 工具可用
如果
HAVE_DOT
被设置为NO
,则需要将其更改为YES
以支持图形生成。图形显示样式(可选):
DOT_IMAGE_FORMAT = svg # 可以选择生成的图形格式,如 png 或 svg
SVG 格式通常质量更好并支持放大缩小操作。
限制图的深度(可选):
如果你的项目很大,可以设置调用图的最大深度以避免生成过于复杂的图:MAX_DOT_GRAPH_DEPTH = 2 # 控制生成图的最大深度
4. 生成文档
配置好
Doxyfile
后,在项目根目录下运行以下命令生成文档:doxygen Doxyfile
Doxygen 将自动分析你的源代码,并生成包含函数调用图的 HTML 文档。
5. 查看生成的函数调用图
在 Doxygen 生成的文档目录中,打开
index.html
文件,通过浏览器访问。如果正确配置,点击某个函数时,它的调用图和调用者图将会显示在页面上。调用图 (Call Graph):显示当前函数调用了哪些其他函数。
调用者图 (Caller Graph):显示哪些函数调用了当前函数。
6. 优化图形显示(可选)
调整图的布局:
DOT_GRAPH_MAX_NODES = 50 # 控制图形中的最大节点数,防止图形过于复杂 DOT_TRANSPARENT = YES # 使图形背景透明(更易嵌入到网页)
函数聚类:
如果你想让相关函数聚集在一起,可以启用函数聚类选项:DOT_CLUSTERING = YES
7. 示例调用图
如果配置成功,生成的调用图可能看起来像这样:
+--------+ +----------+ +---------+ | func A | -->| func B | -->| func C | +--------+ +----------+ +---------+
8. 调试常见问题
调用图未生成:确保
HAVE_DOT
设置为YES
并且系统中安装了 Graphviz。生成的图为空或不完整:检查
MAX_DOT_GRAPH_DEPTH
设置,增加图的深度。图形显示不清晰:尝试将
DOT_IMAGE_FORMAT
设置为svg
或其他矢量图格式。
通过以上步骤,你可以生成函数的调用关系图,帮助你更好地理解项目中的函数调用逻辑。
实例
enum Colors {
RED = 1, /**< Represents the color red */
GREEN = 2, /**< Represents the color green */
BLUE = 3 /**< Represents the color blue */
};
/**
* @brief Adds two integers.
*
* @details This function uses simple addition and assumes the input integers are valid.
* Special care is taken to avoid overflow by ensuring the sum stays within a valid range.
*
* @note This function does not check for integer overflow.
*
* @param a First integer
* @param b Second integer
* @return The sum of a and b
*/
int add1(int a, int b) {
//! This variable stores the sum of a and b
int result = 0; /**< The accumulated sum */
// Add integers with overflow check
if ((a > 0 && b > 0 && a > INT_MAX - b) || (a < 0 && b < 0 && a < INT_MIN - b)) {
// Handle overflow case
return -1; //!< Return error code if overflow occurs
}
result = a + b; //!< Perform the addition
return result; //!< Return the result
}
int add2(int a, int b) {
int result = 0; /**< The variable that stores the sum of a and b */
result += a; /**< Add the value of a to the result */
result += b; /**< Add the value of b to the result */
return result; /**< Return the calculated sum */
}
/**
* @brief Adds two integers.
*
* This function takes two integers and returns their sum.
*
* @param a First integer
* @param b Second integer
* @return The sum of a and b
*/
int add3(int a, int b) {
//! Initialize the result variable to zero.
int result = 0;
//! Add the first integer to the result.
result += a;
//! Add the second integer to the result.
result += b;
//! Return the final result.
return result;
}
/**
* @brief Adds two integers.
*
* @details
* This function uses the following local variables:
* - `result`: Stores the sum of the two input integers.
*
* @param a First integer
* @param b Second integer
* @return The sum of a and b
*/
int add4(int a, int b) {
int result = 0; // Local variable to store the sum
result += a;
result += b;
return result;
}
/**
* @brief Computes the average of an integer array.
*
* This function takes an array of integers and its size as input, and returns
* the average of the array elements. It handles cases where the array is empty.
*
* @details
* The function iterates over the array to compute the sum of its elements.
* If the array is empty, it returns 0 to avoid division by zero.
*
* Local variables used in this function:
* - `sum`: Accumulates the sum of array elements.
* - `i`: Loop counter for iterating through the array.
*
* Example usage:
* @code
* int arr[] = {1, 2, 3, 4, 5};
* double avg = compute_average(arr, 5);
* printf("Average: %f\n", avg);
* @endcode
*
* @param arr The input array of integers.
* @param size The number of elements in the array.
* @return The average of the array elements. If the array is empty, returns 0.
*
* @note The return value is of type `double` to allow for decimal averages.
*/
double compute_average(const int* arr, size_t size) {
//! Sum of the array elements
int sum = 0;
//! Loop counter to iterate through the array
size_t i;
// If the array is empty, return 0 to avoid division by zero
if (size == 0) {
return 0.0;
}
// Sum all elements in the array
for (i = 0; i < size; ++i) {
sum += arr[i];
}
//! Return the computed average as a double
return (double)sum / size;
}
/**
* @brief Adds two integers.
*
* @details This function uses simple addition and assumes the input integers are valid.
* Special care is taken to avoid overflow by ensuring the sum stays within a valid range.
*
* @note This function does not check for integer overflow.
*
* @param a First integer
* @param b Second integer
* @return The sum of a and b
*/
int add6(int a, int b) {
int result = 0; /**< The accumulated sum */
// Add integers with overflow check
if ((a > 0 && b > 0 && a > INT_MAX - b) || (a < 0 && b < 0 && a < INT_MIN - b)) {
// Handle overflow case
return -1; //!< Return error code if overflow occurs
}
result = a + b; //!< Perform the addition
return result; //!< Return the result
}
int add7(int a, int b) {
int result = 0; /**< The variable that stores the sum of a and b */
result += a; /**< Add the value of a to the result */
result += b; /**< Add the value of b to the result */
return result; /**< Return the calculated sum */
}
/**
* @defgroup GeometricShapes Geometric Shape Calculations
* @brief This module handles the calculations of areas for geometric shapes like circles, squares, and triangles.
*
* The functions in this module compute the areas of various geometric shapes by using their respective formulas.
* @{
*/
/**
* @brief Initializes the system to compute geometric areas.
*
* This function can be used to set up any necessary initial values before computing the areas of shapes.
*/
void init_area_computation(void) {
shape_count = 0; // Initialize shape counter
}
/** @} */ // End of GeometricShapes group
/**
* @brief Computes the area of a circle.
*
* This function takes a pointer to a `Circle` structure and calculates its area using the formula:
* @f$ Area = \pi \times radius^2 @f$.
*
* @f[
* Area = \pi \times radius^2
* @f]
*
* @param[in] circle A pointer to the `Circle` structure containing the radius.
* @return The area of the circle.
*/
double compute_circle_area(const Circle* circle) {
return PI * circle->radius * circle->radius;
}
/**
* @file example.h
* @brief This file contains definitions, function prototypes, and data structures
* for a simple system that computes geometric shapes' areas.
*
* This file demonstrates how to use Doxygen to document a C header file.
* It includes macros, structures, function prototypes, and enumeration types.
*
* @author John Doe
* @date 2024-10-11
*/
/**
* @def PI
* @brief The mathematical constant Pi (3.14159...).
*
* This macro defines the value of Pi, which is used in geometric calculations.
*/
#define PI 3.141592653589793
/**
* @enum ShapeType
* @brief Defines the types of geometric shapes.
*
* This enumeration is used to specify the type of shape,
* such as a circle, square, or triangle.
*/
typedef enum {
SHAPE_CIRCLE, /**< Circle shape */
SHAPE_SQUARE, /**< Square shape */
SHAPE_TRIANGLE /**< Triangle shape */
} ShapeType;
/**
* @struct Triangle
* @brief Represents a triangle with a base and height.
*
* This structure stores the base and height of a triangle for area calculations.
*/
typedef struct {
double base; /**< The base length of the triangle */
double height; /**< The height of the triangle */
} Triangle;
/**
* @struct Circle
* @brief Represents a circle with a radius.
*
* This structure is used to store the radius of a circle for area calculations.
*/
typedef struct {
double radius; /**< The radius of the circle */
} Circle;
/**
* @struct Square
* @brief Represents a square with a side length.
*
* This structure stores the side length of a square for area calculations.
*/
typedef struct {
double side_length; /**< The length of one side of the square */
} Square;
/**
* @var shape_count
* @brief Keeps track of the number of shapes processed.
*
* This global variable is incremented every time a new shape's area is computed.
*/
int shape_count = 0;
/**
* @brief Computes the area of a square.
*
* This function calculates the area of a square based on its side length.
*
* @param[in] square A pointer to the `Square` structure containing the side length.
* @return The area of the square.
*/
double compute_square_area(const Square* square) {
return square->side_length * square->side_length;
}
/**
* @brief Computes the area of a triangle.
*
* This function computes the area of a triangle using the formula:
* @f$ Area = \frac{1}{2} \times base \times height @f$.
*
* @param[in] triangle A pointer to the `Triangle` structure containing the base and height.
* @return The area of the triangle.
*/
double compute_triangle_area(const Triangle* triangle) {
return 0.5 * triangle->base * triangle->height;
}
在使用 Doxygen 生成文档时,函数内的注释可以通过特定的标记来实现。Doxygen 支持在函数内部添加详细的说明,解释代码逻辑、变量用途或步骤等。这些注释将显示在生成的文档中,帮助开发者理解函数的实现细节。
以下是几种常见的函数内注释方式:
1. 使用 //!
或 ///
可以在函数体内直接使用 //!
或 ///
注释每个逻辑部分。例如:
好的,下面是一个全面的 C 语言项目注释示例,包含了常见的 Doxygen 注释用法,涵盖文件、函数、变量、结构体、枚举、宏定义、以及组(modules)等内容。这样你可以在实际项目中参考使用,确保所有重要元素都得到充分注释和文档化。
### 文件注释
```c
/**
* @file example.h
* @brief This file contains definitions, function prototypes, and data structures
* for a simple system that computes geometric shapes' areas.
*
* This file demonstrates how to use Doxygen to document a C header file.
* It includes macros, structures, function prototypes, and enumeration types.
*
* @author John Doe
* @date 2024-10-11
*/
宏定义注释
/**
* @def PI
* @brief The mathematical constant Pi (3.14159...).
*
* This macro defines the value of Pi, which is used in geometric calculations.
*/
#define PI 3.141592653589793
枚举类型注释
/**
* @enum ShapeType
* @brief Defines the types of geometric shapes.
*
* This enumeration is used to specify the type of shape,
* such as a circle, square, or triangle.
*/
typedef enum {
SHAPE_CIRCLE, /**< Circle shape */
SHAPE_SQUARE, /**< Square shape */
SHAPE_TRIANGLE /**< Triangle shape */
} ShapeType;
结构体注释
/**
* @struct Circle
* @brief Represents a circle with a radius.
*
* This structure is used to store the radius of a circle for area calculations.
*/
typedef struct {
double radius; /**< The radius of the circle */
} Circle;
/**
* @struct Square
* @brief Represents a square with a side length.
*
* This structure stores the side length of a square for area calculations.
*/
typedef struct {
double side_length; /**< The length of one side of the square */
} Square;
/**
* @struct Triangle
* @brief Represents a triangle with a base and height.
*
* This structure stores the base and height of a triangle for area calculations.
*/
typedef struct {
double base; /**< The base length of the triangle */
double height; /**< The height of the triangle */
} Triangle;
全局变量注释
/**
* @var shape_count
* @brief Keeps track of the number of shapes processed.
*
* This global variable is incremented every time a new shape's area is computed.
*/
int shape_count = 0;
函数注释
/**
* @brief Computes the area of a circle.
*
* This function takes a pointer to a `Circle` structure and calculates its area using the formula:
* @f$ Area = \pi \times radius^2 @f$.
*
* @param[in] circle A pointer to the `Circle` structure containing the radius.
* @return The area of the circle.
*/
double compute_circle_area(const Circle* circle) {
return PI * circle->radius * circle->radius;
}
/**
* @brief Computes the area of a square.
*
* This function calculates the area of a square based on its side length.
*
* @param[in] square A pointer to the `Square` structure containing the side length.
* @return The area of the square.
*/
double compute_square_area(const Square* square) {
return square->side_length * square->side_length;
}
/**
* @brief Computes the area of a triangle.
*
* This function computes the area of a triangle using the formula:
* @f$ Area = \frac{1}{2} \times base \times height @f$.
*
* @param[in] triangle A pointer to the `Triangle` structure containing the base and height.
* @return The area of the triangle.
*/
double compute_triangle_area(const Triangle* triangle) {
return 0.5 * triangle->base * triangle->height;
}
组(Modules)注释
为了组织代码,你可以使用 Doxygen 的 @defgroup
和 @addtogroup
标签将相关函数、结构体等归为一组,便于文档阅读。
/**
* @defgroup GeometricShapes Geometric Shape Calculations
* @brief This module handles the calculations of areas for geometric shapes like circles, squares, and triangles.
*
* The functions in this module compute the areas of various geometric shapes by using their respective formulas.
* @{
*/
/**
* @brief Initializes the system to compute geometric areas.
*
* This function can be used to set up any necessary initial values before computing the areas of shapes.
*/
void init_area_computation(void) {
shape_count = 0; // Initialize shape counter
}
/** @} */ // End of GeometricShapes group
main.c 中的代码示例
为了结合所有的注释,以下是一个主程序文件中使用这些函数的示例。
#include "example.h"
int main(void) {
Circle circle = {5.0}; // Circle with radius 5.0
Square square = {4.0}; // Square with side length 4.0
Triangle triangle = {3.0, 6.0}; // Triangle with base 3.0 and height 6.0
init_area_computation();
double circle_area = compute_circle_area(&circle);
double square_area = compute_square_area(&square);
double triangle_area = compute_triangle_area(&triangle);
printf("Circle Area: %f\n", circle_area);
printf("Square Area: %f\n", square_area);
printf("Triangle Area: %f\n", triangle_area);
return 0;
}
其他注释标签
@param
和@return
:用于注释函数参数和返回值。@file
:用于文件级别的注释。@struct
和@typedef
:用于结构体和类型定义。@brief
:简要描述。@details
:详细描述。@note
:给出提示或注意事项。@code
和@endcode
:用于嵌入代码示例。@ingroup
:将元素添加到组中。
总结
这是一套完整的 Doxygen 注释示例,展示了如何为 C 语言中常见的元素(如文件、函数、变量、结构体、枚举、宏和组)进行注释。使用这些注释方式,可以确保生成的文档清晰、全面,方便团队协作和代码维护。
### 2. 使用 `/**<` 在变量声明中注释
如果想对函数内部局部变量进行注释的话应该怎么办
最后得到的只是写的注释,并没有给出局部变量的名字
对于函数内的变量,您可以使用 `/**<` 来直接注释变量的声明,帮助读者了解每个变量的作用:
int add(int a, int b) {
int result = 0; /**< The variable that stores the sum of a and b */
result += a; /**< Add the value of a to the result */
result += b; /**< Add the value of b to the result */
return result; /**< Return the calculated sum */
}
### 3. 使用 `@details` 和 `@note`
对于较为复杂的函数,可以使用 `@details` 和 `@note` 来解释函数中的特定细节或提醒:
/**
@brief Adds two integers.
@details This function uses simple addition and assumes the input integers are valid.
Special care is taken to avoid overflow by ensuring the sum stays within a valid range.
@note This function does not check for integer overflow.
@param a First integer
@param b Second integer
@return The sum of a and b
*/
int add(int a, int b) {
int result = 0; /**< The accumulated sum */// Add integers with overflow check
if ((a > 0 && b > 0 && a > INT_MAX - b) || (a < 0 && b < 0 && a < INT_MIN - b)) {
// Handle overflow case
return -1; //!< Return error code if overflow occurs
}result = a + b; //!< Perform the addition
return result; //!< Return the result
}
### 小结
在函数内部添加详细的注释有助于提升代码的可读性和维护性,Doxygen 支持多种注释格式,可以根据项目需求灵活选择。
如果最后生成的文档显示的公式是 `$ Area = \pi \times radius^2 $` 而不是公式的数学格式,可能是 Doxygen 没有正确识别 LaTeX 公式的标记。为了让 Doxygen 正确地显示数学公式,可以尝试以下几种解决方案:
### 1. 确保使用正确的 `@f$` 标签
Doxygen 支持 LaTeX 公式,但它需要你使用正确的标签格式。如果你想让公式显示为数学格式,应该用 `@f$` 来标记公式的开始和结束。例如:
/**
@brief Computes the area of a circle.
The area of a circle is given by the formula:
@f$Area = \pi \times radius^2 @f$.
@param[in] radius The radius of the circle.
@return The area of the circle.
*/
double compute_circle_area(double radius) {
return PI * radius * radius;
}
在生成文档时,Doxygen 会识别 `@f$` 标签并将其转换为 LaTeX 格式,显示为:
[\\text{Area} \= \\pi \\times \\text{radius}\^2]
### 2. 使用 `@f[` 和 `@f]` 包围公式
如果公式较长或你想换行,可以使用 `@f[` 和 `@f]` 标签将整个公式包围起来,生成更加清晰的数学公式表示。例如:
/**
@brief Computes the area of a circle.
The area of a circle is calculated as:
@f[
Area = \pi \times radius^2
@f]
@param[in] radius The radius of the circle.
@return The area of the circle.
*/
double compute_circle_area(double radius) {
return PI * radius * radius;
}
这样,公式将会被识别为块状公式,并正确渲染。
### 3. 确保 Doxygen 配置支持 LaTeX
Doxygen 需要特定的配置才能正确处理 LaTeX 公式:
* 打开 `Doxyfile`,确保以下设置启用:
* `USE_MATHJAX = YES` 让 Doxygen 使用 MathJax 来渲染数学公式。
* 如果没有 MathJax,你可以设置 `LATEX_OUTPUT = YES`,以确保 LaTeX 能被正确编译成 PDF 或 HTML 格式。
USE_MATHJAX = YES
MATHJAX_FORMAT = HTML
### 4. 确保 MathJax 或 LaTeX 环境可用
* 如果生成 HTML 文档并希望公式正确显示,你需要确保 MathJax 脚本能够正常加载。如果是生成 PDF,你需要 LaTeX 环境来正确编译数学公式。
### 结论
总结来说,确保使用 `@f$` 标签正确标记公式,并且检查 Doxygen 的配置文件是否启用了 MathJax 或 LaTeX 支持。
效果图
- 感谢你赐予我前进的力量