用Doxygen和Graphviz给Contiki文档添加类图和调用图
2016-04-19 23:38
906 查看
目录
目录如何根据源码绘制数据结构
安装Doxygen和Graphviz
修改Doxygen配置文件并运行doxygen
生成的各种图的效果
TODO
如何根据源码绘制数据结构?
在学习Contiki系统的过程中,阅读源码是搞清楚实现细节的最好方法。但直接阅读源码有时候也不是很容易的事情,即便有SourceInsight这样的源码阅读利器帮助,你还是时不时会希望能不能看到类的继承关系?能不能看到函数的调用关系?答案是肯定的,搜了一下网上开源的方案不少,例如在emacs中利用Graphviz绘制数据结构图的 、使用编译器特性生成CVG格式的数据结构图的、使用Python或者Java实现这一功能的,等等。但最方便,功能最强大的还是Doxygen+Graphviz。Contiki 是瑞典计算机科学学院的大牛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。
相关文章推荐
- doxygen学习笔记 2012-02-28
- C#数据结构之顺序表(SeqList)实例详解
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C#数据结构之单链表(LinkList)实例详解
- 数据结构之Treap详解
- 用C语言举例讲解数据结构中的算法复杂度结与顺序表
- C#数据结构之堆栈(Stack)实例详解
- C#数据结构之双向链表(DbLinkList)实例详解
- JavaScript数据结构和算法之图和图算法
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- Java数据结构及算法实例:插入排序 Insertion Sort
- Java数据结构及算法实例:考拉兹猜想 Collatz Conjecture
- java数据结构之java实现栈
- java数据结构之实现双向链表的示例
- Java数据结构及算法实例:选择排序 Selection Sort
- Java数据结构及算法实例:朴素字符匹配 Brute Force
- Java数据结构及算法实例:汉诺塔问题 Hanoi