使用Woboq CodeBrowser搭建源代码网站

背景

在日常学习工作中,我们不免需要浏览一些库的源码。在本地浏览源代码,例如使用Source Insight,当然是可以的,但问题是一是不方便,二是很多库下载下来是以头文件配合静态库或动态库的形式存在的,看不到cpp代码,因此阅读会受限。现在Web技术高速发展,有没有办法用网页直接查看源代码,并且还有类似于Code的代码跳转功能呢?换句话说,如何把C/C++代码转化为前端页面,并且最好是静态的前端页面,就是一个难题了。

幸运的是,github上有人提前考虑到了这件事情,并且有了具体的项目,已经有1k多的star。并且原作者还基于这个框架弄出了一个在线的源代码网站,方便开发者查看各个C/C++库的源代码,例如QtGCCLinux KernelGNU C Library等。

那么问题来了,都有在线的网站了为什么还要自己搭建一个呢?原因就是这个网站在国内被墙了。有人会说?开梯子啊,不是每个节点都能上,我嫌他烦,因此决定自己搭建一个源代码网站一劳永逸。我的源码网站地址:https://davidingplus.github.io/code-browser/

工作原理简介

Woboq CodeBrowser是基于LLVM/Clang实现的一个命令行工具。它通过深度解析C/C++源码生成最终我们需要的静态HTML文件。Woboq CodeBrowser包含codebrowser_generatorcodebrowser_indexgenerator两个子命令。生成HTML文件到最终可以通过浏览器阅读代码,整体分三个步骤:

  1. 先通过codebrowser_generator解析.h.cpp生成对应的.h.html.cpp.html
  2. 然后通过codebrowser_indexgenerator为所有目录生成 index.html
  3. 最后我们可以把这些HTML文件拷贝到某个Web服务器上,就可以在浏览器里愉快地浏览C/C++项目的源码了。

安装Woboq CodeBrowser工具

我们通过源码编译安装这个工具。

首先将该项目克隆到本地,由于需要用LLVM/Clang工具链,强烈建议在Linux下操作。

1
git clone https://github.com/KDAB/codebrowser.git

克隆下的项目中有三个目录比较重要,一是data目录,这是一些前端的资源文件,例如pngcssjs等;二是generator目录,这是可执行文件codebrowser_generator的源码目录;三是indexgenerator,这是可执行文件codebrowser_indexgenerator的源码目录。

前面提到,编译这个工具需要用到LLVM/Clang工具链,结合github上的issue#119,使用llvm-14clang-14的版本比较合适。以Ubuntu为例:

1
sudo apt install llvm-14 clang-14 libclang-14-dev

但是在Ubuntu20.04及以下的版本上会出现定位不到软件包的问题,官方提供了一个解决方案,参见博客https://blog.csdn.net/weixin_50749380/article/details/128319851

这样我们的编译环境就安装好了,紧接着我们需要构建这个项目并且将编译后的文件安装到本地。项目受CMake管理,同时参考官方文档,构建流程就很简单了。

1
2
3
4
5
6
mkdir -p build
cd build

cmake -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_BUILD_TYPE=Release .. # 除了 clang 还可能安装了 gcc 等其他的编译器,所以指定一下;同时指定编译选项为 Release ,这个在 Linux 下没有影响
make
sudo make install # 必要加上 sudo

安装完毕以后data目录,两个可执行文件codebrowser_generatorcodebrowser_indexgenerator就成功安装到本地了。

image-20240718105543595

如何使用

接下来以googletest-1.12.1为例,展示如何使用这个工具构建静态的源代码网站。

生成compile_commands.json

compile_commands.json文件是一种特定格式的compilation database文件,而所谓compilation database其实很简单,它里面记录的是每一个源码文件在编译时详细的信息(包括文件路径,文件名,编译选项等等)。而compile_commands.json文件是LibTooling需要的以json格式呈现的compilation database文件,以下截取的是compile_commands.json中的一个entry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[
...
{
"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也不要担心,Bearcompdb工具可以帮我们生成compile_commands.json文件。

现在让我们一起生成googletest-1.12.1项目对应的compile_commands.json。首先我们拉取googletest的源码到本地。源码采用CMake工具的管理,这样正好很方便的能帮我们生成compile_commands.json。之所以这么推荐CMake是因为使用其他的工具可能需要编译整个工程才能生成该文件,费事费力。

因为我是C++11标准的环境,因此需要使用的版本是1.12.1,切换到对应的tag。当然直接下载对应的release源码也行。

1
git checkout release-1.12.1 # target tag

然后我们使用CMake工具生成compile_commands.json文件,个人建议使用gcc/g++编译器。

1
2
3
4
mkdir -p build
cd build

cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER="gcc" -DCMAKE_CXX_COMPILER="g++" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..

build目录下看到compile_commands.json文件正确生成即为成功。

使用codebrowser_generator生成html

codebrowser_generator是一个可执行文件,有各种执行参数,说明如下:

  • -a:处理compile_commands.json中的所有文件。如果没有传递这个参数,那么就需要传递要处理的文件列表
  • -o:指定文件输出目录
  • -b:是指包含compile_commands.json的构建目录。如果没有传递这个参数,编译参数可以在--后通过命令行传递
  • -p:(一个或多个)用于项目规范。即项目的名称、源代码的绝对路径和用冒号分隔的版本信息。示例:-p projectname:/path/to/source/code:0.3beta
  • -d:指定包含所有JavaScriptCSS文件的数据URL。默认为相对于输出目录的../data。示例:-d https://codebrowser.dev/data/
  • -e:是对外部项目的引用。示例: -e clang/include/clang:/opt/llvm/include/clang/:https://codebrowser.dev/llvm

例如,对于当前googletest-1.12.1项目,一条合适的命令可能是这样的:

1
codebrowser_generator -b ./compile_commands.json -a -p googletest-1.12.1:"${PWD}/..":1.12.1 -o ./docs -d ../data

执行完的结果是这样的:

image-20240730153744964

需要注意的是,上面的操作都是在根目录的build构建目录执行的,这也是CMake用户的构建习惯。

同时,-o ./docs代表文件输出在build/docs中,-d ../data是指定资源文件的相对路径,代表资源文件位于生成目录docs的父级目录。至于为什么是../data,后面会详细解释。安装好Woboq CodeBrowser工具以后data目录会被安装在/usr/local/share/woboq/data,将其拷贝为build/data即可。

使用codebrowser_indexgenerator为每个目录生成index.html

codebrowser_indexgenerator同样有很多执行参数,说明如下:

  • -p:(一个或多个)用于项目规范。即项目的名称、源代码的绝对路径和用冒号分隔的版本信息。示例:-p projectname:/path/to/source/code:0.3beta
  • -d:指定包含所有JavaScriptCSS文件的数据URL。默认为相对于输出目录的 ../data。示例:-d https://codebrowser.dev/data/

同样执行类似命令:

1
codebrowser_indexgenerator ./docs -d ../data

类似执行结果如下,可以看到每个目录对应都有了index.html

image-20240730154020528

关于-d参数以及资源文件

上面提到,为什么我使用的是-d ../data呢?我们先弄清楚data目录是干嘛的。

data目录存放着前端代码需要的资源文件,例如CSSJS和图片资源等。因此需要指明这个目录的路径,绝对路径或者相对路径。由于我的code-browser项目需要存放很多库的源代码,因此我将data目录统一在根目录中,每个库的源代码对应一个自己的子目录,因此最终的结果是这样的:

image-20240730154929638

这样就能正确定位到资源文件的路径了,codebrowser_generator生成的html文件同理。用户使用自己的习惯和方式即可。

参考文档

  1. https://blog.csdn.net/astrotycoon/article/details/104831055
  2. https://blog.csdn.net/weixin_42148156/article/details/121727163
  3. https://blduan.top/post/工具使用/codebrowser之从浏览器阅读源码
使用搜索:必应百度