前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >搭建大型源码阅读环境——使用 OpenGrok

搭建大型源码阅读环境——使用 OpenGrok

作者头像
零式的天空
发布2022-03-28 20:09:39
2.1K0
发布2022-03-28 20:09:39
举报
文章被收录于专栏:零域Blog

RTFSC 是程序员打怪升级路上避不开的功课,那营造一个舒适的环境来提升上课的体验就很有必要了。

比如阅读 AOSP 这种大型源码,用什么姿势来阅读才能丝般顺滑,让 F**king Source Code 也变得不那么可恶呢?

工具的选择

阅读源码的工具我尝试过以下几类:

  1. IDE 在看特定类型项目时这是我的首选。比如它原本就是一个 Visual Studio 工程,那当然用 Visual Studio 来打开阅读,看 Android App 或者 Library 源码当然用 Android Studio 体验更好。
  2. 编辑器配合插件 比如 Vim + Ctags + Cscope,再配合文件模糊查找插件 LeaderF 和神器 YouCompleteMe,在源码规模不大时很方便,打开也轻快,阅读一些小项目时我还是乐意使用它们。
  3. 专门的源码阅读工具 在针对特大型源码时,比如 AOSP 和 Chromium,使用上述两种方案可能会感觉乏力,这时候就需要祭出专门的源码阅读工具了。 一类是商业软件,比如 Windows 下有著名的 Source Insight,跨平台的有 Understand,功能都很强大,都是不错的选择。当然它们都价格不菲。 而我这里要讲的主角 OpenGrok 属于另一类,免费,开源,运行流畅,功能也毫不逊色。

如果你还在寻觅适合你自己的解决方案,大可以花一点时间将以上几种都尝试一遍,哪个称手用哪个,也可以像我一样,针对不同的项目使用不同的工具。想直观了解 OpenGrok 的同学可以直接先看看一些使用 OpenGrok 的在线源码查看网站,看看它能否满足你的需求,其中的一些列在 OpenGrok installations

OpenGrok 特性

译自官方 Wiki

OpenGrok 提供如下特性:

  1. 快速搜索代码的引擎
    • 搜索全文、定义、符号、文件路径和修改历史
    • 搜索任意指定子目录(分层搜索)
    • 增量更新索引文件
    • 支持类似 Google 的查询语法,比如 path:Makefile defs:target
    • 搜索日期范围内修改的文件
    • 支持使用通配符搜索,如 * 表示多个字符,? 表示单个字符
    • 在搜索结果中展示匹配行
  2. 一个 Web 只读版的版本历史查看界面
    • 文件的修改日志
    • 文件在两个版本间的 diff
    • 文件夹的历史记录
  3. 带语法高亮的交叉引用显示,可以使用 CSS 自定义样式
  4. 可以开发插件支持新的语言和版本控制系统 已经支持的语言: Supported Languages and Formats 已经支持的版本控制系统:Supported Revision Control Systems

配置 OpenGrok

安装和配置

如下以 Windows 下为例,Mac OS X 与 Linux 下与此类似,很多步骤能使用 brew 或者 apt-get 会更方便。

安装 JDK,并配置 JAVA_HOME 或者 JRE_HOME 环境变量为安装目录。

下载 Tomcat,解压到一个目录,如 D:\Programs\apache-tomcat-8.5.8,并将此目录添加为 CATALINA_HOME 环境变量。

下载 Universal Ctags for Windows,将 ctags.exe 文件所在目录添加到 PATH 环境变量。

下载 OpenGrok 的最新包,比如 opengrok-0.13-rc4.zip,解压到一个目录,如 D:\Programs\opengrok-0.13-rc4。

配置 data root。

将 OpenGrok 的 lib 目录里的 source.war 解压到 D:\Programs\apache-tomcat-8.5.8\webapps\source,配置 WEB-INF\web.xml 文件的 CONFIGURATION 为上一步生成的 data 目录下的 configureation.xml,比如我的配置:

注:这里只是配置一个文件路径,具体的 configuration.xml 会在第 8 步时自动生成。

配置 source root。

我的做法是在 OpenGrok 下创建了一个子目录 D:\Programs\opengrok-0.13-rc4\projects,然后将需要阅读的源码使用符号链接的方式链接到这个目录里:

这样就有一个叫 android 的工程,它实际对应 D:\sources\android_5.1 下的源码,一个叫 openjdk7 的工程,它实际对应 D:\sources\openjdk7 下的源码。

建立索引。

代码语言:javascript
复制
java -jar /path/to/opengrok.jar -P -S -v -s /path/to/source/root -d /path/to/data/root -W /path/to/configuration.xml

-S 表示搜索并添加 “external” source repositories。

-s 表示指定 source root。

-W 表示指定将配置写到该文件。

比如我使用的完整命令行:

每次需要建立或更新索引的时候敲这么长一个命令当然很不爽,使用 doskey 或者 Cmder 里的 alias 命令将其 alias 为 opengrok-index 命令会省力不少,再不济把这命令存成个 bat 文件也行啊。

启动 Tomcat,愉快地 RTFSC。

用你最爱的浏览器打开 http://localhost:8080/source/,然后就能愉快地跟 OpenGrok 玩耍了。

配置多项目

我曾经为如何在 OpenGrok 里配置多项目苦恼了好久——一开始我是把 Android 源码的根目录当作 source root 的,可想而知 OpenGrok 把 Android 分成了好多个子项目,而这时我也没法再添加新的工程了。

后来才发现建一个专用的 source root,然后把各种项目源码根目录软链接过来,让 OpenGrok 为 source root 下的每个 symbol 一级子目录建立一个项目才是正确的使用方法。

Windows 下建立软链接的方法是使用 mklink /J android D:\sources\android_5.1,Mac OS X 和 Linux 下可以使用 ln -s /path/to/source project_name

折腾狂魔

在 Vim 里使用

没错,还有人做了支持在 Vim 里使用 OpenGrok 的插件,如果你是 Vim 控+折腾狂魔,可以一试,这里仅给出插件地址:

反正像我这种智商是折腾不动了,就安心在浏览器里用了。

在源码里做笔记

配合 Chrome 插件 Diigo,还能给源码加标签,写注释等等。

参考:https://www.zhihu.com/question/33505693/answer/132224974

常见问题

打开网页后报错

代码语言:javascript
复制
There was an error!
CONFIGURATION parameter has not been configured in web.xml! Please configure your webapp.
Unable to determine source root path. Missing configuration?
java.io.FileNotFoundException: Unable to determine source root path. Missing configuration?
	at org.opensolaris.opengrok.web.PageConfig.checkSourceRootExistence(PageConfig.java:1562)
	at org.apache.jsp.index_jsp._jspService(index_jsp.java:222)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:443)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.opensolaris.opengrok.web.StatisticsFilter.doFilter(StatisticsFilter.java:55)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.opensolaris.opengrok.web.AuthorizationFilter.doFilter(AuthorizationFilter.java:83)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

这一般是由于更新或切换了 OpenGrok 版本,但却没有将 tomcat 的 webapps 目录下的 source 文件夹替换为对应版本。

后话

古人教会了我们工欲善其事,必先利其器的智慧,但我们也不能沉迷和徘徊于各种利器之间,选择一样自己感觉最称手的工具,把它用熟练,少再在这上面花时间折腾,毕竟把有限的生命投入到无限的 RTFSC 才是正道不是么。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 工具的选择
  • OpenGrok 特性
  • 配置 OpenGrok
    • 安装和配置
      • 配置多项目
        • 折腾狂魔
        • 常见问题
          • 打开网页后报错
          • 后话
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档