Doxygen+linux
一:安装
因为官网提供的bin文件缺少文件貌似,而且是由Ubuntu内核3.13编译的,而我的是centos7内核版本为3.10,所以还是决定采取源码编译的方式。
下载doxygen-1.8.10.src.tar.gz
1.#tar zxvf doxygen-1.8.10.src.tar.gz
2.#cd doxygen-1.8.10
3.#mkdir build
4.#cd build
5.#cmake “Unix Makefiles” ..
其中cmake版本至少需要2.8.12(下载下来的BUILD.txt说需要至少3.0及以上,官网文档说至少需要2.8.12其实我用的2.8.12.2就是OK的)。
6.#make
7.#cmake -Dbuild_doc=YES
8.#make docs
其中:
步骤5的时候会提示缺少包,这也是源码编译常遇到的问题,比如我遇到下面的问题:
提示缺少FLEX,先用yum list flex查找到flex.x86_64,再用命令yum install flex.x86_64安装。
继续执行又提示缺少BISON.同样的方法yum install bison.x86_64.
继续执行安装成功,默认安装在/usr/local/bin
其次还需安装一个graphviz,命令
Yum install graphviz即可。
二:Doxygen配置
进入项目所在目录
#doxygen [-s] -g [your_own_config_file]产生配置文件Doxyfile或者你自己的配置文件,-s取消产生的注释。
配置文件中进行相应的配置,具体看生成的模板即可,给出常用配置如下:
#这可以让doxygen从配置文件所在的文件夹开始,递归地搜索所有的子目录及源文件
RECURSIVE = YES
#这会在最后生成的文档中,把所有的源代码包含在其中
SOURCE BROWSER = YES
#这会把函数的实现部分的代码包含在每个函数的说明部分,可以方便地查看函数的实现
#方式,但会让整个文档显得有些凌乱,故不推荐使用
INLINE SOURCES = YES
#这会在HTML文档中,添加一个侧边栏,并以树状结构显示包、 类、接口等的关系
GENERATE TREEVIEW = ALL
#这个设置将导致doxygen不生成pdf文档,不太喜欢pdf文档,把它 关了吧
GENERATE_LATEX = NO
#给出所有文档的输出目录
OUTPUT_DIRECTORY = doc
#设置使用的语言
OUTPUT_LANGUAGE = English
#生成chm格式的压缩html文档
GENERATE_HTMLHELP = YES
#指定doxygen分析的输入文件(目录)
INPUT = src lib
#指定分析的文件的类型(扩展名)
INCLUDE_FILE_PATTERNS = *.cpp *.h
#处理完一个函数的文档之后,对函数调用的函数也列出相关的链接。
REFERENCES_RELATION = YES
# 项目名称,将作为于所生成的程序文档首页标题
PROJECT_NAME = “Test”
# 文档版本号,可对应于项目版本号,譬如 svn、cvs 所生成的项目版本号
PROJECT_NUMBER = "1.0.0”
# 程序文档输出目录
OUTPUT_DIRECTORY = doc/
#提取信息,包含类的私有数据成员和静态成员
EXTRACT_ALL = yes
EXTRACT_PRIVATE = yes
EXTRACT_STATIC = yes
# 对于使用 typedef 定义的结构体、枚举、联合等数据类型,只按照 typedef 定义的类型名进行文档化
TYPEDEF_HIDES_STRUCT = YES
# 在 C++ 程序文档中,该值可以设置为 NO,而在 C 程序文档中,由于 C 语言没有所谓的域/名字空间这样的概念,所以此处设置为 YES
HIDE_SCOPE_NAMES = YES
# 让 doxygen 静悄悄地为你生成文档,只有出现警告或错误时,才在终端输出提示信息
QUIET = YES
# 允许程序文档中显示本文档化的函数相互调用关系
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
# 在程序文档中允许以图例形式显示函数调用关系,前提是你已经安装了 graphviz 软件包
HAVE_DOT = YES
CALL_GRAPH = YES
CALLER_GRAPH = YES
#在最后生成的文档中,把所有的源代码包含在其中
SOURCE BROWSER = YES
$这会在HTML文档中,添加一个侧边栏,并以树状结构显示包、类、接口等的关系
GENERATE TREEVIEW = ALL
三:源码文档化
Doxygen 认可的行间注释标记见下例:
/**
* 这是行间注释标记示例
*/
行内注释标记见下例:
double coord[3]; /// <这是行内注释示例
1.所有注释都可以使用///开始(C++风格)。
2.类体前必须加上///描述,否则会产生警告【Compound 类名 is not documented】
描述中最好不要带有此类的类名,否则会产生两个链接(但指向同一个文件)影响美观。
3.public和protected会自动生成,但是private要在Expert的Build选项里勾中EXTRACT_PRIVATE,static成员也是如此。
4.函数注释方式
/// Constructor【函数描述】
/// @param [in] pos The position of Camera in world coordinate 【参数描述1】
/// @param [in] lookat The point Camera looks at in world coordinate 【参数描述2】
BaseCamera( const D3DXVECTOR3& pos, const D3DXVECTOR3& lookat );
5.产生描述顺序和注释顺序相同,一般风格为
/// 函数描述
/// @param 参数描述
/// @return 返回值描述
/// @retval 返回值1 返回值1描述
/// @retval 返回值2 返回值2描述
/// @remarks 注意事项
/// @note 注意事项,功能同@remarks,显示字样不同
/// @par 自定义图块,后面可跟示例代码之类
/// @code(必须使用@endcode结束)
/// 示例代码(无需缩进)
/// @endcode
/// @see 其他参考项【产生指向参考的链接】
函数代码声明
6.特殊符号
/// - 产生一个黑色圆点
7.定义在类体里面的enum
/// Camera types
enum CAMERA_TYPE
{
CAMERA_MODEL_VIEW,///< Camera that looks from the third view
};
两种风格相同。
以下开始的项都是全局非类内定义,在文件最开始(我尝试是在include之前) 必须加上【/// \file 文件名】,否则不会生成注释【没有File Member页】。
8. 定义在文件里面的宏
#define CAMERA_TYPE_NUMBER ///< The number of camera types.
四:程序文档化
#doxygen Doxyfile
到生成的doc/html目录下,打开index.html即可。
另附doxygen自带manual:
Comment blocks for C-like languages (C/C++/C#/Objective-C/PHP/Java)
For each entity in the code there are two (or in some cases three) types of descriptions, which together form the documentation for that
entity; a brief description and detailed description, both are optional. For methods and functions there is also a third type of description,
the so called in body description, which consists of the concatenation of all comment blocks found within the body of the method or
function.
Having more than one brief or detailed description is allowed (but not recommended, as the order in which the descriptions will
appear is not specified).
As the name suggest, a brief description is a short one-liner, whereas the detailed description provides longer, more detailed
documentation. An "in body" description can also act as
a detailed description or can describe a collection of implementation details. For the HTML output brief descriptions are also
used to provide tooltips at places where an item is referenced.
There are several ways to mark a comment block as a detailed description:
You can use the JavaDoc style, which consist of a C-style comment block starting with two *'s, like this:
/**
* ... text ...
*/
or you can use the Qt style and add an exclamation mark (!) after the opening of a C-style comment block, as shown in this example:
/*!
* ... text ...
*/
In both cases the intermediate *'s are optional, so
/*!
... text ...
*/
is also valid.
A third alternative is to use a block of at least two C++ comment lines, where each line starts with an additional slash or an
exclamation mark. Here are examples of the two cases:
///
/// ... text ...
///
or
//!
//!... text ...
//!
Note that a blank line ends a documentation block in this case.
Some people like to make their comment blocks more visible in the documentation. For this purpose you can use the following:
/********************************************//**
* ... text
***********************************************/
(note the 2 slashes to end the normal comment block and start a special comment block).
or
/
/// ... text ...
/
For the brief description there are also several possibilities:
One could use the \brief command with one of the above comment blocks. This command ends at the end of a paragraph,
so the detailed description follows after an empty line.
Here is an example:
/*! \brief Brief description.
* Brief description continued.
*
* Detailed description starts here.
*/
If JAVADOC_AUTOBRIEF is set to YES in the configuration file, then using JavaDoc style comment blocks will automatically
start a brief description which ends at the first dot followed by a space or new line. Here is an example:
/** Brief description which ends at this dot. Details follow
* here.
*/
The option has the same effect for multi-line special C++ comments:
/// Brief description which ends at this dot. Details follow
/// here.
A third option is to use a special C++ style comment which does not span more than one line. Here are two examples:
/// Brief description.
/** Detailed description. */
or
//! Brief description.
//! Detailed description
//! starts here.
Note the blank line in the last example, which is required to separate the brief description from the block containing the
detailed description. The JAVADOC_AUTOBRIEF should also be set to NO for this case.
As you can see doxygen is quite flexible. If you have multiple detailed descriptions, like in the following example:
//! Brief description, which is
//! really a detailed description since it spans multiple lines.
/*! Another detailed description!
*/
They will be joined. Note that this is also the case if the descriptions are at different places in the code! In this case
the order will depend on the order in which doxygen parses the code.
Unlike most other documentation systems, doxygen also allows you to put the documentation of members
(including global functions) in front of the definition. This way the documentation can be placed in the source
file instead of the header file. This keeps the header file compact, and allows the implementer of the members
more direct access to the documentation. As a compromise the brief description could be placed before the
declaration and the detailed description before the member definition.
Putting documentation after members
If you want to document the members of a file, struct, union, class, or enum, it is sometimes desired to place
the documentation block after the member instead of before. For this purpose you have to put an additional
< marker in the comment block. Note that this also works for the parameters of a function.
Here are some examples:
int var; /*!< Detailed description after the member */
This block can be used to put a Qt style detailed documentation block after a member.
Other ways to do the same are:
int var; /**< Detailed description after the member */
or
int var; //!< Detailed description after the member
//!<
or
int var; ///< Detailed description after the member
///<
Most often one only wants to put a brief description after a member. This is done as follows:
int var; //!< Brief description after the member
or
int var; ///< Brief description after the member
For functions one can use the @param command to document the parameters and then use [in], [out],
[in,out] to document the direction. For inline documentation this is also possible by starting with the direction attribute, e.g.
void foo(int v /**< [in] docs for input parameter v. */);
Note that these blocks have the same structure and meaning as the special comment blocks in the
previous section only the < indicates that the member is located in front of the block instead of after the block.
Here is an example of the use of these comment blocks:
/*! A test class */
class Test
{
public:
/** An enum type.
* The documentation block cannot be put after the enum!
*/
enum EnumType
{
int EVal1, /**< enum value 1 */
int EVal2 /**< enum value 2 */
};
void member(); //!< a member function.
protected:
int value; /*!< an integer value */
};
Click here for the corresponding HTML documentation that is generated by doxygen.
Warning
These blocks can only be used to document members and parameters. They cannot be used to document files,
classes, unions, structs, groups, namespaces and enums themselves. Furthermore,
the structural commands mentioned in the next section (like \class) are not allowed inside these comment blocks.
Examples
Here is an example of a documented piece of C++ code using the Qt style:
//! A test class.
/*!
A more elaborate class description.
*/
class Test
{
public:
//! An enum.
/*! More detailed enum description. */
enum TEnum {
TVal1, /*!< Enum value TVal1. */
TVal2, /*!< Enum value TVal2. */
TVal3 /*!< Enum value TVal3. */
}
//! Enum pointer.
/*! Details. */
*enumPtr,
//! Enum variable.
/*! Details. */
enumVar;
//! A constructor.
/*!
A more elaborate description of the constructor.
*/
Test();
//! A destructor.
/*!
A more elaborate description of the destructor.
*/
~Test();
//! A normal member taking two arguments and returning an integer value.
/*!
\param a an integer argument.
\param s a constant character pointer.
\return The test results
\sa Test(), ~Test(), testMeToo() and publicVar()
*/
int testMe(int a,const char *s);
//! A pure virtual member.
/*!
\sa testMe()
\param c1 the first argument.
\param c2 the second argument.
*/
virtual void testMeToo(char c1,char c2) = 0;
//! A public variable.
/*!
Details.
*/
int publicVar;
//! A function variable.
/*!
Details.
*/
int (*handler)(int a,int b);
};
Click here for the corresponding HTML documentation that is generated by doxygen.
The brief descriptions are included in the member overview of a class, namespace or file and are
printed using a small italic font (this description can be hidden by setting BRIEF_MEMBER_DESC to
NO in the config file). By default the brief descriptions become the first sentence of the detailed
descriptions (but this can be changed by setting the REPEAT_BRIEF tag to NO). Both the brief
and the detailed descriptions are optional for the Qt style.
By default a JavaDoc style documentation block behaves the same way as a Qt style documentation block.
This is not according the JavaDoc specification however, where the first sentence of the documentation
block is automatically treated as a brief description. To enable this behavior you should
set JAVADOC_AUTOBRIEF to YES in the configuration file. If you enable this option and want to
put a dot in the middle of a sentence without ending it, you should put a backslash and a space
after it. Here is an example:
/** Brief description (e.g.\ using only a few words). Details follow. */
Here is the same piece of code as shown above, this time documented using the JavaDoc
style and JAVADOC_AUTOBRIEF set to YES:
/**
* A test class. A more elaborate class description.
*/
class Test
{
public:
/**
* An enum.
* More detailed enum description.
*/
enum TEnum {
TVal1, /**< enum value TVal1. */
TVal2, /**< enum value TVal2. */
TVal3 /**< enum value TVal3. */
}
*enumPtr, /**< enum pointer. Details. */
enumVar; /**< enum variable. Details. */
/**
* A constructor.
* A more elaborate description of the constructor.
*/
Test();
/**
* A destructor.
* A more elaborate description of the destructor.
*/
~Test();
/**
* a normal member taking two arguments and returning an integer value.
* @param a an integer argument.
* @param s a constant character pointer.
* @see Test()
* @see ~Test()
* @see testMeToo()
* @see publicVar()
* @return The test results
*/
int testMe(int a,const char *s);
/**
* A pure virtual member.
* @see testMe()
* @param c1 the first argument.
* @param c2 the second argument.
*/
virtual void testMeToo(char c1,char c2) = 0;
/**
* a public variable.
* Details.
*/
int publicVar;
/**
* a function variable.
* Details.
*/
int (*handler)(int a,int b);
};
Click here for the corresponding HTML documentation that is generated by doxygen.
Similarly, if one wishes the first sentence of a Qt style documentation block to automatically be treated
as a brief description, one may set QT_AUTOBRIEF to YES in the configuration file.
Documentation at other places
In the examples in the previous section the comment blocks were always located in front of the declaration
or definition of a file, class or namespace or in front or after one of its members. Although this is often
comfortable, there may sometimes be reasons to put the documentation somewhere else.
For documenting a file this is even required since there is no such thing as "in front of a file".
Doxygen allows you to put your documentation blocks practically anywhere (the exception is
inside the body of a function or inside a normal C style comment block).
The price you pay for not putting the documentation block directly before (or after) an item is the
need to put a structural command inside the documentation block, which leads to some duplication
of information. So in practice you should avoid the use of structural commands unless other
requirements force you to do so.
Structural commands (like all other commands) start with a backslash (\), or an at-sign (@)
if you prefer JavaDoc style, followed by a command name and one or more parameters.
For instance, if you want to document the class Test in the example above, you could have also
put the following documentation block somewhere in the input that is read by doxygen:
/*! \class Test
\brief A test class.
A more detailed class description.
*/
Here the special command \class is used to indicate that the comment block contains
documentation for the class Test. Other structural commands are:
\struct to document a C-struct.
\union to document a union.
\enum to document an enumeration type.
\fn to document a function.
\var to document a variable or typedef or enum value.
\def to document a #define.
\typedef to document a type definition.
\file to document a file.
\namespace to document a namespace.
\package to document a Java package.
\interface to document an IDL interface.
See section Special Commands for detailed information about these and many other commands.
To document a member of a C++ class, you must also document the class itself. The same holds
for namespaces. To document a global C function, typedef, enum or preprocessor definition you
must first document the file that contains it (usually this will be a header file, because that file
contains the information that is exported to other source files).
Attention
Let's repeat that, because it is often overlooked: to document global objects (functions, typedefs,
enum, macros, etc), you must document the file in which they are defined. In other words, there must at least be a
/*! \file */
or a
/** @file */
line in this file.
Here is an example of a C header named structcmd.h that is documented using structural commands:
/*! \file structcmd.h
\brief A Documented file.
Details.
*/
/*! \def MAX(a,b)
\brief A macro that returns the maximum of \a a and \a b.
Details.
*/
/*! \var typedef unsigned int UINT32
\brief A type definition for a .
Details.
*/
/*! \var int errno
\brief Contains the last error code.
\warning Not thread safe!
*/
/*! \fn int open(const char *pathname,int flags)
\brief Opens a file descriptor.
\param pathname The name of the descriptor.
\param flags Opening flags.
*/
/*! \fn int close(int fd)
\brief Closes the file descriptor \a fd.
\param fd The descriptor to close.
*/
/*! \fn size_t write(int fd,const char *buf, size_t count)
\brief Writes \a count bytes from \a buf to the filedescriptor \a fd.
\param fd The descriptor to write to.
\param buf The data buffer to write.
\param count The number of bytes to write.
*/
/*! \fn int read(int fd,char *buf,size_t count)
\brief Read bytes from a file descriptor.
\param fd The descriptor to read from.
\param buf The buffer to read into.
\param count The number of bytes to read.
*/
#define MAX(a,b) (((a)>(b))?(a):(b))
typedef unsigned int UINT32;
int errno;
int open(const char *,int);
int close(int);
size_t write(int,const char *, size_t);
int read(int,char *,size_t);
Click here for the corresponding HTML documentation that is generated by doxygen.
Because each comment block in the example above contains a structural command,
all the comment blocks could be moved to another location or input file (the source file for instance),
without affecting the generated documentation. The disadvantage of this approach is that prototypes are duplicated,
so all changes have to be made twice! Because of this you should first consider if this is really needed,
and avoid structural commands if possible. I often receive examples that contain \fn command in comment
blocks which are place in front of a function. This is clearly a case where the \fn command is redundant and will only lead to problems.
When you place a comment block in a file with one of the following extensions .dox, .txt, or .doc then doxygen will hide this file from the file list.
If you have a file that doxygen cannot parse but still would like to document it, you can show it as-is using \verbinclude, e.g.
/*! \file myscript.sh
* Look at this nice script:
* \verbinclude myscript.sh
*/
Make sure that the script is explicitly listed in the INPUT or that FILE_PATTERNS includes the .sh extention and the the script can be found in the path set via EXAMPLE_PATH.