前言

当进入到一个陌生的大型项目, 又或是为了疑难杂症要去阅读开源项目, 比如AOSPOpenJDKLinux Kernel这种大型开源项目, 会发现这些项目, 不仅仅代码量大得惊人(AOSP clone下来就有50G了), 还常常混合多种语言. 如何快速准确的查找代码调用关系、理清逻辑, 是非常大的挑战. 能胜任这种场景的工具, 可能只有Source Insight.

因为Source Insight, 可以提供:

  • 准确完善的代码解析和分析查找功能
  • 极高的性能
  • 极低的系统资源占用

可惜SI只在Win平台上面有. 在Mac上, 用Wine或者用虚拟机来启动它,又慢又不稳定.

1 常见编辑器能替代SI吗?

1.1 IDE

IntelliJ 或Eclipse等IDE, 主要还是用来写代码的, 这会导致IDE, 不适应我们阅读源码的场景.

比如AOSP项目, 是由接近300个子项目组成, 这些子项目中, 像 chrominum 本身就是一个复杂项目, 有着自己的代码结构和编译配置. IDE大多针对某种语言的垂直场景, 适应不了这么复杂的场景.

如果不把项目build success, 并且把依赖按照IDE的方式配置好. 就得面对一堆堆的红色报错, 和部分功能不可用的问题. 但是, AOSP之类的源码, build非常麻烦, 编译成本非常高. 一方面是编译时间, 一方面是会占用海量的硬盘空间. 最新AOSP, 不开启CCACHE, 编译后, 会占100G左右空间. 如果开启默认建议的20+G 的CCACHE, 会占用更多硬盘空间.

还有就是, IDE大多针对中小型项目的开发, 从IDE设计者的角度, 是用空间换时间, 所以消耗的资源, 是与项目大小强相关的, 项目越大消耗的资源就越大, load 大项目的IDEA, 简直卡得不要不要的

1.2 Vim + vim-awesome插件包

不管什么编辑器, 我都会安装Vim plugin, 所以我也非常喜欢独立的, 通过vim-awesome配置的Vim环境。当然, 少不了会安装ctags+cscope+NERDTree 等等插件包。

不过, 说实话, 这种环境, 偶尔秀一下还可以, 真要在一个陌生项目中, 频繁的跳转和查找调用关系,手很容易抽筋的. 这种环境更适合阅读和开发有一定熟悉度的代码,而不适合相对陌生, 需要频繁查找和跳转的大型项目。

1.3 Sublime || Atom || VS Code

另一种常见环境,是基于Sublime+ctags+cscope。

Sublime 有一个至今未解决的, 具有普遍性的bug Sublime keeps indexing and heating up my computer. 这个bug, 在open 文件多的大型项目后, 即使用户什么都不做, 它都会不停的index, 导致笔记本严重发热, 电量快速下降.

另外, Sublime已经逐渐被一些插件开发者抛弃, 类似material-theme的 Deprecation note

1.4 ctags & cscope的问题

无论是把Sublime换成Atom 或 VS Code, 又或是Vim环境, 都会遇到下面这两个问题:

第一, ctags & cscope都不支持增量索引, 每次更新代码后, 都需要对整个项目重建索引, 时间成本非常高

第二, ctags默认配置对包含java c++等多语言的项目支持比较差. 要确保准确解析包含多语言的项目, 需要配置下面这种, 天书一样的参数.

ctag-config

2. 体验OpenGrok

一个偶然的机会,我找到了Sun的OpenGrok, OpenGrok的界面, 浓浓的历史味道, 让人觉得这货不简单. 随着长时间的体验, 我更认定它就是Source Insight在Mac平台的替代品。

OpenGrok is a source code search and cross reference engine. It helps programmers to search, cross-reference and navigate source code trees

2.1 使用OpenGrok的案例

非常多的公益大型源码阅读网站, 是基于OpenGrok部署的, 可以体验

main-ui

3 OpenGrok的功能介绍

3.1 Analysis功能

OpenGrok有强大的Analysis功能

Analysis支持主流的版本控制系统, 如CVS、Git、Mercurial等, 并能对SCM的记录进行分析, 然后提供快速查找history和展示Annotations的功能.

Analysis还内置了很多分析引擎, 比如C/C++, 比如Shell, 比如XML等等, 在index的过程中, 每个文件, 会分配到这些引擎上解析, 为源码的变量/对象、结构体/类、函数/接口、宏等生成可供快速搜索的索引文件

analysis

3.2 搜索功能

与IDE的侧边栏文件树不同, OpenGrok提供的是搜索直达. 这也非常符合我们看源码的场景, 源码非常庞杂, 我们常常是带着问题, 以某个函数或接口切入, 去摸索的.

OpenGrok的搜索功能是非常强大的:

  1. 对 full text, definitions, symbols, path 或 revision history等进行搜索
  2. 限制在某个子目录里面搜索
  3. 支持类似Google Search的搜索语法, 比如 path:Makefile defs:target
  4. 支持根据修改时间段进行搜索
  5. 支持模糊匹配搜索, * 匹配多个字符, ? 匹配单个字符
  6. 支持正则 path:/ma[a-zA-Z]*/
  7. 支持多条件 -“/usr/bin/perl” +”/bin/perl”
  8. 极速. 得益于index和Apache Lucene, 可以在几十万文件中, 进行多条件搜索, 只需要几毫秒

详细的搜索帮助, 可以通过点击搜索框底部的help按钮进行学习, 会路由到一个help.jsp页面, 如 https://opengrok.housegordon.com/source/help.jsp

一个搜索到例子如下:

opengrok-search

3.3 主界面使用

3.3.1 Navigate

点击导航栏上面的 Navigate# , 可以切换右侧方法列表展示

image

3.3.2 intelligence window

先把鼠标箭头, 移动到目标方法上面, 然后按一下键盘上的数字 1, 可以呼出 intelligence window

这里面有

  • Highlight / UnHighlight
  • Search definitions
  • Search references

等等辅助理解代码关系的功能

image

3.3.3 highlight

先把鼠标箭头, 移动到目标方法上面, 然后按一下键盘上的数字 2, 可以快速切换Highlight / UnHighlight

这个功能, 在理解某个方法的时候非常有用.

4 安装本地OpenGrok

受制于网络情况和GFW, 本地会更加实用. 官方安装流程 分为几大步骤:

  1. 安装tomcat
  2. 安装ctags
  3. 安装opengrok
  4. 部署opengrok到tomcat
  5. 配置参数
  6. 索引代码, 开始使用

4.1 我推荐的安装版本

我之前有搭建了最新版本的OpenGrok + Universal Ctags, 但是我在索引Android源码的时候, 遇到了很多问题, 比如说android.view.View这种复杂一点的类, 会解析不完整. 但是同样基于OpenGrok的 AndroidXRef 就可以完美解析

我后来有去咨询OpenGrok, 得到的回复如下:

For reference, androidxref seems to be using 0.11.1

然后, 我测试了, 从0.11.1到1.0等多个版本, 发现, 只要是可以使用Exuberant Ctags, 就没有问题. 1.0以后逐渐默认切到了Universal ctags, 但还不够成熟, 在大型项目的兼容性上, 还不是特别稳定
最终, 我在Mac下使用了如下版本进行搭建, 可以完美解析Android 源码和其他各个大型项目源码:

4.2 具体安装流程

4.2.1 安装Tomcat

我们下载tomcat 8.5.31, 解压到目录, 比如~/env/tomcat, 然后将该目录添加到环境变量
export OPENGROK_TOMCAT_BASE=~/env/tomcat

4.2.2 安装ctags

使用 brew install ctags 安装ctags, 并确保 ctags —version 输出的, 是Exuberant Ctags

4.2.3 安装opengrok

下载OpenGrok 1.0 tar , 并解压到目录,比如 ~/opengrok, 然后将该目录添加到环境变量:

1
export OPENGROK_INSTANCE_BASE=~/opengrok
4.2.4 部署opengrok到tomcat

在命令行进入刚才的~/opengrok/bin目录, 执行

1
./OpenGrok deploy

可以看到如下输出

Loading the default instance configuration …
Installing ./../lib/source.war to /Users/xiaoxinpeng/env/tomcat/webapps …

Start your application server (Tomcat), if it is not already
running, or wait until it loads the just installed web application.

OpenGrok should be available on :/source
where HOST and PORT are configured in Tomcat.

4.2.5 配置参数

首先是对tomcat的配置, 在刚才的安装目录 ~/env/tomcat 下, 我们对conf/server.xml文件进行修改, 该文件70行附近, 有对Connector的配置, 我们加入maxHttpHeaderSize=”65536”,如下

1
2
3
4
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxHttpHeaderSize="65536"
redirectPort="8443" />
4.2.6 提升index速度

然后是对opengrok索引速度的修改:
将下面几行, 加入环境变量, 即可极大加速opengrok的index速度:

1
2
3
4
5
export JAVA_OPTS="-Xmx8192m -server"
export OPENGROK_FLUSH_RAM_BUFFER_SIZE="-m 256"
#下面这两行可以极大加速index的速度
export OPENGROK_SCAN_REPOS=false
export OPENGROK_GENERATE_HISTORY=off
4.2.7 index

我们先进入 ~/opengrok/bin目录

再执行 ./OpenGrok index

等整个索引结束以后, 在浏览器, 打开 http://127.0.0.1:8080/source/ 就可以使用了

References