您的位置:首页 > 理论基础 > 数据结构算法

用Doxygen和Graphviz给Contiki文档添加类图和调用图

2016-04-19 23:38 906 查看

目录

目录

如何根据源码绘制数据结构

安装Doxygen和Graphviz

修改Doxygen配置文件并运行doxygen

生成的各种图的效果

TODO

如何根据源码绘制数据结构?

在学习Contiki系统的过程中,阅读源码是搞清楚实现细节的最好方法。但直接阅读源码有时候也不是很容易的事情,即便有SourceInsight这样的源码阅读利器帮助,你还是时不时会希望能不能看到类的继承关系?能不能看到函数的调用关系?答案是肯定的,搜了一下网上开源的方案不少,例如在emacs中利用Graphviz绘制数据结构图的使用编译器特性生成CVG格式的数据结构图的、使用Python或者Java实现这一功能的,等等。但最方便,功能最强大的还是Doxygen+GraphvizContiki 是瑞典计算机科学学院的大牛Adam Dunkels 带领团队开发的适用于MCU构成的传感器网络节点的嵌入式操作系统。Contiki麻雀虽小,五脏俱全,集成了uIP协议栈,支持6LoWPAN,代表着传感器网络业界最新的发展方向。其文档也相当的完善,是使用Doxygen自动生成的,但默认没有打开绘制数据结构和调用图的功能,我们只需要将其打开即可,一行代码都不用写。

安装Doxygen和Graphviz

Doxygen和Graphviz都可以从前面给出的官方网站下载源码,Doxygen还可以从github获取。Ubuntu的各个版本都有集成,这里也不用专门定制,就用包管理器直接安装了:

# aptitude install graphviz doxygen


安装完后运行一下dot (graphviz默认用于有向图绘制的工具),确认graphviz能够正常工作:

# dot -V
# dot - graphviz version 2.26.3 (20100126.1600)


修改Doxygen配置文件并运行doxygen

用Doxygen生成html文档非常的简单,只需要设置好配置文件,让Doxygen扫描源码目录,Doxygen便能根据配置生成需要的描述信息并进行组织,使得使用者可以按照软件开发者在代码中提供的注释信息和帮助文档按图索骥。这里我们不需要生成全新的配置文件并进行配置,contiki源码目录下的doc/Doxyfile就是contiki项目所使用的配置文件。我们只需要复制一份到工作目录(例如新建一个my_doc,避免污染源文档目录)并打开相应的选项。配置文件里#开头的为注释,中文为我自己添加的说明。配置选项非常的多,可以参考Doxygen文档config一节 的说明进行配置

# Doxyfile 1.4.1

#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME           = "Contiki 2.6"
PROJECT_NUMBER         =
OUTPUT_DIRECTORY       = my_doc     #生成的html和latex文档及doxygen的日志会放到这个目录下
CREATE_SUBDIRS         = NO
OUTPUT_LANGUAGE        = English
USE_WINDOWS_ENCODING   = YES
BRIEF_MEMBER_DESC      = YES
REPEAT_BRIEF           = YES
ABBREVIATE_BRIEF       =
ALWAYS_DETAILED_SEC    = NO
INLINE_INHERITED_MEMB  = NO
FULL_PATH_NAMES        = YES
STRIP_FROM_PATH        = $(docroot)
STRIP_FROM_INC_PATH    = $(docroot)
SHORT_NAMES            = YES
JAVADOC_AUTOBRIEF      = YES
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP         = YES
INHERIT_DOCS           = YES
DISTRIBUTE_GROUP_DOC   = NO
TAB_SIZE               = 8
ALIASES                =
OPTIMIZE_OUTPUT_FOR_C  = YES    # Contiki主要是C代码,所以C-YES,Java-NO
OPTIMIZE_OUTPUT_JAVA   = NO
SUBGROUPING            = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL            = YES    # 这里我将全部的EXTRACT_XXX都打开了, 后面可以根据需要进行删减
EXTRACT_PRIVATE        = YES    # 这几个选项控制要针对哪些符号生成文档,例如这里将类的私有属性和
EXTRACT_STATIC         = YES    # 方法都提取出来
EXTRACT_LOCAL_CLASSES  = YES
EXTRACT_LOCAL_METHODS  = YES
HIDE_UNDOC_MEMBERS     = NO     # 是否显示没有文档说明的成员和类?
HIDE_UNDOC_CLASSES     = NO
HIDE_FRIEND_COMPOUNDS  = YES
HIDE_IN_BODY_DOCS      = NO
INTERNAL_DOCS          = NO
CASE_SENSE_NAMES       = YES
HIDE_SCOPE_NAMES       = NO
SHOW_INCLUDE_FILES     = YES
INLINE_INFO            = YES
SORT_MEMBER_DOCS       = YES
SORT_BRIEF_DOCS        = NO
SORT_BY_SCOPE_NAME     = NO
GENERATE_TODOLIST      = YES
GENERATE_TESTLIST      = YES
GENERATE_BUGLIST       = NO
GENERATE_DEPRECATEDLIST= NO
ENABLED_SECTIONS       =
MAX_INITIALIZER_LINES  = 30
SHOW_USED_FILES        = NO
SHOW_DIRECTORIES       = YES
FILE_VERSION_FILTER    =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET                  = NO     #这一段控制输出到doxygen.log文件中的信息
WARNINGS               = YES
WARN_IF_UNDOCUMENTED   = YES
WARN_IF_DOC_ERROR      = YES
WARN_NO_PARAMDOC       = YES
WARN_FORMAT            = "$file:$line: $text"
WARN_LOGFILE           = doxygen.log
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT                  = $(docsrc)

FILE_PATTERNS          = *.h *.c *.doc.html *.txt
RECURSIVE              = YES    #这个选项很关键,需要打开才能对源码目录进行递归扫描,把所有的
EXCLUDE                =        #源码都扫描到
EXCLUDE_SYMLINKS       = YES
#下面一行指定了不扫描含有printf的文件,因为printf主要是用来输出
#信息的,并不体现其所在函数的代码逻辑,在callgraph里出现反而会干
#扰呈现主干的调用关系。
EXCLUDE_PATTERNS       = *-printf.c printf.c
EXAMPLE_PATH           = . ../examples/rime ../examples/multi-threading
EXAMPLE_PATTERNS       =
EXAMPLE_RECURSIVE      = NO
IMAGE_PATH             = pics
INPUT_FILTER           =
FILTER_PATTERNS        =
FILTER_SOURCE_FILES    = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER         = YES
INLINE_SOURCES         = NO
STRIP_CODE_COMMENTS    = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION    = YES
VERBATIM_HEADERS       = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX     = YES
COLS_IN_ALPHA_INDEX    = 5
IGNORE_PREFIX          =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML          = YES    #默认只生成HTML文档和LaTeX文档
HTML_OUTPUT            = html
HTML_FILE_EXTENSION    = .html
HTML_HEADER            =
HTML_FOOTER            =
HTML_STYLESHEET        =
HTML_ALIGN_MEMBERS     = YES
GENERATE_HTMLHELP      = YES
CHM_FILE               =
HHC_LOCATION           =
GENERATE_CHI           = YES
BINARY_TOC             = YES
TOC_EXPAND             = YES
DISABLE_INDEX          = NO
ENUM_VALUES_PER_LINE   = 4
GENERATE_TREEVIEW      = YES
TREEVIEW_WIDTH         = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX         = $(doclatex)
LATEX_OUTPUT           = latex
LATEX_CMD_NAME         = latex
MAKEINDEX_CMD_NAME     = makeindex
COMPACT_LATEX          = YES
PAPER_TYPE             = a4wide
EXTRA_PACKAGES         =
LATEX_HEADER           =
PDF_HYPERLINKS         = YES
USE_PDFLATEX           = YES
LATEX_BATCHMODE        = NO
LATEX_HIDE_INDICES     = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF           = NO
RTF_OUTPUT             = rtf
COMPACT_RTF            = NO
RTF_HYPERLINKS         = NO
RTF_STYLESHEET_FILE    =
RTF_EXTENSIONS_FILE    =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN           = NO
MAN_OUTPUT             = man
MAN_EXTENSION          = .3
MAN_LINKS              = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML           = NO
XML_OUTPUT             = xml
XML_SCHEMA             =
XML_DTD                =
XML_PROGRAMLISTING     = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF   = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD       = NO
PERLMOD_LATEX          = NO
PERLMOD_PRETTY         = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING   = YES
MACRO_EXPANSION        = NO
EXPAND_ONLY_PREDEF     = NO
SEARCH_INCLUDES        = YES
INCLUDE_PATH           =
INCLUDE_FILE_PATTERNS  =
PREDEFINED             = CC_FUNCTION_POINTER_ARGS \
WITH_UIP6 UIP_CONF_IPV6 UIP_CONF_IPV6_RPL \
WITH_LOADER_ARCH \
DOXYGEN \
"ASCCMD(name, flags, args)=void CMD_ASCII(name)"
EXPAND_AS_DEFINED      =
SKIP_FUNCTION_MACROS   = NO
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES               = "contiki_tags"
GENERATE_TAGFILE       =
ALLEXTERNALS           = NO
EXTERNAL_GROUPS        = YES
PERL_PATH              = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS         = YES    # 与 HAVE_DOT 互斥的
HIDE_UNDOC_RELATIONS   = NO
HAVE_DOT               = YES
CLASS_GRAPH            = YES
COLLABORATION_GRAPH    = YES
GROUP_GRAPHS           = YES
UML_LOOK               = YES
TEMPLATE_RELATIONS     = YES
INCLUDE_GRAPH          = NO
INCLUDED_BY_GRAPH      = NO
CALL_GRAPH             = YES
GRAPHICAL_HIERARCHY    = YES
DIRECTORY_GRAPH        = YES
DOT_IMAGE_FORMAT       = png
DOT_PATH               =/dot
DOTFILE_DIRS           = ./dot
MAX_DOT_GRAPH_WIDTH    = 1920
MAX_DOT_GRAPH_HEIGHT   = 1080
MAX_DOT_GRAPH_DEPTH    = 9
DOT_TRANSPARENT        = YES
DOT_MULTI_TARGETS      = YES
GENERATE_LEGEND        = YES
DOT_CLEANUP            = YES
#这一段配置是我们要重点关注的内容。HAVE_DOT设置成YES,这样Doxygen就会调用dot程序来绘制callgraph。
#这里把所有支持的图都选择上了,可以根据需要删减。DOT_PATH指定dot程序的位置,但这里出现了一个小BUG:
#Doxygen在分析dot程序的绝对路径时会漏掉一个“/”把/usr/bin/dot变成/usr/bindot。这样一来到了使用dot
#时就会报错,这里只好把dot放到项目目录里并把这个变量设成/dot。后面的MAX指定生成的各种图最大的分辨率
#和调用层数,GENERATE_LEGEND选上可以方便随时查看图例(在每个graph下方都会有一个[legend]标签,打开
#会显示图例)
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE           = NO


配置完成后我们就进入contiki源码的根目录,运行doxygen进行扫描。执行的时候需要指定我们修改过的配置文件。

# doxygen my_doc/Doxyfile


由于打开了很多选项扫,描并生成整个contiki源码的文档还是比较耗时的。如果需要加速,可以添加一个配置项:

DOT_NUM_THREADS = 0


Doxygen会根据你的CPU核数并发地调用多个dot线程同时处理。

完成后,就可以进入/my_doc/html目录下查看整个项目源码的文档了,各种数据结构和调用关系的图都是链接到对应的类和函数中的,非常清晰。这里只把图片单独抠出来展示一下效果。

生成的各种图的效果

图例:



类图:



协作图:



调用图



TODO

这里对Doxygen和Graphviz的使用还是很粗浅的,这两个工具的强大远远不止这些,下一步的工作就是控制Doxygen的扫描和对生成的dot代码进行修改,使得显示的结果更精确,只关注我们需要研究的部分,
a4e4
这样绘制出来的图才能更好地起到辅助理解程序逻辑的作用。

另外,由于是对代码的静态扫描分析,所以这里生成的调用图对于理解程序逻辑是有局限性的:它无法跟踪C语言中通过函数指针实现的动态绑定。这种调用关系只有依靠Profiling工具,例如内核中的oprofile才能捕捉到,之后再送至dot处理绘制callgraph。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息