学习工作中阅读学习C/C++项目代码,在Windows下大多数人使用Source Insight这个工具,而在Linux下我一般喜欢vim配合ctags来使用。不过发现它们有一个共同的问题,就是对C++中的符号解析得不够精细,例如不支持从运算符重载函数声明处跳转到其定义处。因此通过Google搜索希望有更好的工具来替代,这才发现了本文将向大家推荐的工具,它就是woboq_codebrowser。
网站https://woboq.com向我们展示了利用woboq_codebrowser
解析的几个大型C/C++项目,包括 Qt | GLibc | LLVM | Boost | GCC | Linux。通过实际体验,发现woboq_codebrowser
的确强大,尤其对C++的符号解析得更加精细。
本文首先会简单介绍下woboq_codebrowser
的工作原理,然后带领大家一步步安装woboq_codebrowser
,最后通过实际使用它来解析一个C++项目,完整地向大家展示woboq_codebrowser
的用法。
woboq_codebrowser
当然有它的缺点,那就是不支持代码编辑。
首先大致了解下woboq_codebrowser
的工作原理吧。
woboq_codebrowser
是基于LLVM/Clang实现的一个命令行工具。它通过深度解析C/C++源码生成最终我们需要的静态HTML文件。woboq_codebrowser
包含codebrowser_generator
和codebrowser_indexgenerator
两个子命令。生成HTML文件到最终可以通过浏览器阅读代码,整体分三个步骤:
codebrowser_generator
解析.h和.cpp生成对应的 .h.html 和 .cpp.html。codebrowser_indexgenerator
为所有目录生成 index.html。本文演示在Ubuntu 18.04 LTS上通过源码编译安装woboq_codebrowser
的完整步骤。
通过git把woboq_codebrowser
源码clone到本地。
$ git clone https://github.com/woboq/woboq_codebrowser
其中 generator 和 indexgenerator 目录里的代码分别是命令codebrowser_generator
和codebrowser_indexgenerator
的源码。
特别的,data 目录里的文件并不是源码,而是一些网页数据,你可以看到一些Javascript脚本文件,CSS文件以及很多png格式的图片。这些网页数据会在make install
时拷贝到系统相应的位置,例如woboq_codebrowser
默认的 install prefix 是 /usr/local,那么codebrowser_generator
和codebrowser_indexgenerator
最终会安装到 /usr/local/bin 目录里,data 目录会被拷贝到 /usr/local/share/woboq 目录下。
另外一点需要注意:通过阅读README文件,了解到在Ubuntu系统上LLVM的版本需要大于等于7版本,否则会报找不到ClangConfig.cmake文件的错误。并且通过issue#74了解到这其实不是LLVM的bug,而是debian包管理出现的一个bug(Ubuntu包管理是基于debian包管理的)。因此我们在下一步编译时可以指定特定版本的编译器来避免这个坑。
woboq_codebrowser
需要使用cmake来构建,因此需要确保系统已经安装好了cmake。
我们可以告诉cmake是用g++编译还是clang++编译。
命令如下(我的g++版本是(Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0):
# gcc
cmake . -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER=g++ \
-DLLVM_DIR="/usr/lib/llvm-7/cmake"
make && sudo make install
注意到了吗? 我通过指定LLVM_DIR为LLVM-7的路径,这就避免了刚刚提到的issue#74问题。当然了,也可以指定更高版本的LLVM路径,都是可以的。
命令如下:
$ cmake . -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_DIR="/usr/lib/llvm-7/cmake"
$ make && sudo make install
至此,不出意外的话,woboq_codebrowser
这就编译安装成功了。
这里我通过LIEF这个项目来做演示,详细展示使用woboq_codebrowser
的具体步骤。
compile_commands.json
文件是一种特定格式的 compilation database 文件,而所谓 compilation database 其实很简单,它里面记录的是每一个源码文件在编译时详细的信息(包括文件路径,文件名,编译选项等等)。而compile_commands.json
文件是 LibTooling 需要的以JSON格式呈现的 compilation database 文件,以下截取的是compile_commands.json
中的一个entry:
[
...
{
"arguments": [
"c++",
"-c",
"-g",
"-O2",
"-Werror",
"-std=c++0x",
"-Wall",
"-fPIC",
"-o",
"attrs.o",
"attrs.cc"
],
"directory": "/home/astrol/libelfin/dwarf",
"file": "attrs.cc"
},
...
]
前面说过woboq_codebrowser
是基于LLVM/Clang实现的工具,那么自然也是基于compile_commands.json
来分析源码关系的。
就是说,要想使用woboq_codebrowser
,必须首先生成compile_commands.json
文件。如果项目是由cmake构建的,那么恭喜你,只需加上-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
即可。如果是传统的make build system也不要担心,Bear和compdb工具可以帮我们生成compile_commands.json
文件。特别的,Android从7.0版本之后,构建系统换做Soong之后也提供了对应的方法。
先来简单了解下woboq_codebrowser
常用参数的意义如下,更多的参数可以通过woboq_codebrowser --help
去查看。
-a
process all files from the compile_commands.json. If this argument is not passed, the list of files to process need to be passedwoboq_codebrowser
处理compile_commands.json
中记录的每一个文件。-o=<output path>
Output directory where the generated files will be putwoboq_codebrowser
生成的HTML存放在哪个目录。-b=<compile_commands.json>
Path to the compilation database (compile_commands.json) If this argument is not passed, the compilation arguments can be passed on the command line after ‘–’woboq_codebrowser
在哪个路径可以找到compile_commands.json
-p=<<project>:<path>[:<revision>]>
Project specification: The name of the project, the absolute path of the source code, and the revision separated by colons. Example: -p projectname:/path/to/source/code:0.3betawoboq_codebrowser
一些当前需要处理的project的信息,包括project名称,路径以及版本信息。命令codebrowser_indexgenerator
的使用比codebrower_generator
要简单很多,后头直接指定一个路径就好。
现在以LIEF为列(我当前处于LIEF源码目录内,并成功生成了compile_commands.json
):
#/usr/bin/env bash
DATA_DIRECTORY=/usr/local/share/woboq/data
OUTPUT_DIRECTORY=/tmp/lief
if [ -d ${OUTPUT_DIRECTORY} ]; then
rm -rf ${OUTPUT_DIRECTORY}/*
else
mkdir -p ${OUTPUT_DIRECTORY}
fi
BUILD_DIRECTORY=$PWD
SOURCE_DIRECTORY=$PWD
VERSION=`git describe --always --tags`
codebrowser_generator -color -a -b $BUILD_DIRECTORY -o $OUTPUT_DIRECTORY \
-p LEIF:$SOURCE_DIRECTORY:$VERSION -d ${DATA_DIRECTORY}
codebrowser_indexgenerator $OUTPUT_DIRECTORY
cp -rfd $DATA_DIRECTORY $OUTPUT_DIRECTORY
这里推荐大家使用nginx在本地搭建一个web服务器使用,可以参考《搭建Nginx本地web开发服务》。
《Compilation databases for Clang-based tools》
《Compilation database》
《JSON Compilation Database Format Specification》
《Compilation database》