专栏导读
本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解。
前言
codeviz官网:https://github.com/petersenna/codeviz
codeviz是一款分析C/C++源代码函数调用关系的工具,通过它可以生成函数调用关系图(call graph)。其基本原理是给gcc打个补丁,让gcc在编译每个源文件时,将其中的函数的调用关系以文本形式保存在 .cdepn 文件中,然后使用 Perl 脚本(genfull和gengraph)把 .cdepn 文件转成 dot 文件,最后由graphviz 将dot文件转成图片文件(如gif、png等)。
给gcc打补丁的过程是:
1. 下载codeviz要求的特定版本的gcc源码(跟你环境中已安装的gcc是不同的);
2. 使用codeviz的补丁文件修改gcc源码(即打补丁);
3. 编译gcc源码,得到打完补丁的gcc可执行文件(利用这个gcc可执行文件再来编译我们项目的源文件,从而得到函数调用关系);
在安装codeviz的过程中,最难的也就是编译打完补丁的gcc源码,会遇到各种编译出错,得逐个解决,大部分时间也是耗在这上面。整个安装过程大致步骤如下:
- 安装graphviz,因为codeviz依赖graphviz,所以要先安装graphviz。
- 安装codeviz,这里面包括脚本自动下载依赖的gcc源码,自动打补丁,自动编译gcc源码,最后安装codeviz。
安装graphviz
codeviz 依赖 graphviz,所以要先安装 graphviz:
# sudo apt-get install graphviz
安装codeviz
codeviz源码包下载地址:
https://web.archive.org/web/20150502053825/http://www.csn.ul.ie/~mel/projects/codeviz/#download
安装步骤:
# wget https://web.archive.org/web/20150802030038/http://www.csn.ul.ie/~mel/projects/codeviz/codeviz-1.0.12.tar.gz
# tar zxvf codeviz-1.0.12.tar.gz
# cd codeviz-1.0.12/
# ./configure && make && make install
执行make的过程中,codeviz的安装脚本 compilers/install_gcc-4.6.2.sh 会自动检测 compilers 目录下是否有其依赖的 gcc 版本的源码包(版本codeviz-1.0.12 依赖的是 gcc-4.6.2),如果没有,则会将 gcc-4.6.2.tar.gz 源码自动下载到 compilers 目录中,并将 gcc-4.6.2.tar.gz 解压到 gcc-graph 目录,然后打上补丁,最后开始编译。这个过程,其实是codeviz-1.0.12/compilers/install_gcc-4.6.2.sh脚本自动实现的。
codeviz-1.0.12/
├── bin
├── compilers
│ ├── install_gcc-4.6.2.sh <-- 执行该脚本将:
│ ├── gcc-4.6.2.tar.gz 1. download gcc-4.6.2.tar.gz
│ ├── gcc-graph 2. mkdir gcc-graph
│ │ ├── gcc-4.6.2 3. untar it into gcc-graph
│ ├── gcc-patches 4. patch it
│ 5. compile it
我在编译的过程中,遇到了以下几个问题,最后一个问题没能解决,所以安装也宣告失败,不管怎样,把这次安装过程做个记录,留给需要的人参考。
问题1:无法自动下载gcc-4.6.2
如果出现无法正常下载gcc的情况,就要检查下install_gcc-4.6.2.sh脚本了。截取该脚本部分内容:
#!/bin/bash
INSTALL_PATH=$HOME/gcc-graph
if [ "$1" != "" ]; then INSTALL_PATH=$1; fi
if [ "$2" = "compile-only" ]; then export COMPILE_ONLY=yes; fi
echo Installing gcc to $INSTALL_PATH
NCFTP=`which ncftpget`
EXIT=$?
if [ "$EXIT" != "0" ]; then
NCFTP=ftp
fi
if [ ! -e gcc-4.6.2.tar.gz ]; then
echo gcc-4.6.2.tar.gz not found, downloading
$NCFTP ftp://ftp.gnu.org/pub/gnu/gcc/gcc-4.6.2/gcc-4.6.2.tar.gz
if [ ! -e gcc-4.6.2.tar.gz ]; then
echo Failed to download gcc, download gcc-4.6.2.tar.gz from www.gnu.org
exit
fi
fi
......
因为我的环境没有安装ncftpget,但有wget,所以我将:
NCFTP=`which ncftpget`
改为:
NCFTP=`which wget`
就能顺利下载gcc了。
当然,你也可以自己下载 gcc-4.6.2.tar.gz ,再把它拷贝到 codeviz-1.0.12/compilers 目录中。我还是更倾向于修改 install_gcc-4.6.2.sh 脚本,让这些过程「自动化」。
问题2:找不到依赖库gmp、mpfr、mpc
编译gcc-4.6.2的过程遇到如下错误:
configure: error: Building GCC requires GMP 4.2+, MPFR 2.3.1+ and MPC 0.8.0+.
这是因为缺少相应的依赖库,要先执行gcc源码中自带的依赖库安装脚本download_prerequisites,如下所示:
# cd codeviz-1.0.12/compilers/gcc-graph/gcc-4.6.2/
# ./contrib/download_prerequisites
注意:以上 cd 的路径是有讲究的,务必跟以上命令保持一致,这样gmp、mpfr、mpc才能下载到codeviz-1.0.12/compilers/gcc-graph/gcc-4.6.2/目录下,才能保证顺利编译。
为了让这个过程「自动化」,也可以把以上命令放到 install_gcc-4.6.2.sh 脚本中去执行。当然,如果你的环境没有报这个错,就没必要了。
问题3:linux-unwind.h编译失败
编译gcc-4.6.2的过程遇到如下错误:
../../../../gcc-4.6.2/libgcc/../gcc/config/i386/linux-unwind.h:138:17: error: field ‘info’ has incomplete type
解决方法1:
这是因为我的环境是linux 64-bit内核, struct siginfo不兼容64-bit内核,将以下文件:
codeviz-1.0.12/compilers/gcc-graph/gcc-4.6.2/gcc/config/i386/linux-unwind.h
中的 struct siginfo 替换为siginfo_t 即可,因为每次重新执行make,脚本install_gcc-4.6.2.sh都会重新解压gcc-4.6.2并覆盖linux-unwind.h,所以这样的替换要在 install_gcc-4.6.2.sh 脚本中执行,按如下修改install_gcc-4.6.2.sh 脚本内容:
tar -zxf gcc-4.6.2.tar.gz -C gcc-graph || exit
sed -i 's/struct siginfo/siginfo_t/g' ./gcc-graph/gcc-4.6.2/gcc/config/i386/linux-unwind.h
即在解压gcc-4.6.2后,使用sed命令将linux-unwind.h文件中的struct siginfo 替换为siginfo_t,如此,重新执行make指令即可编译通过。
解决方法2:
在脚本 install_gcc-4.6.2.sh 文件中增加编译选项:
--disable-multilib
问题4:找不到crt1.o
编译gcc-4.6.2的过程遇到如下错误:
cannot find crt1.o: No such file or directory
先找出crt1.o在哪(你的路径可能跟我不一样):
# find /usr/ -name crti.o
/usr/lib/x86_64-linux-gnu/crti.o
解决方法:
# export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu && make
问题5:找不到CXXABI_1.3.8
编译gcc-4.6.2的过程遇到如下错误:
msgfmt: /opt/codeviz-1.0.12/compilers/gcc-graph/objdir/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)
根据提示,查看其 libstdc++.so.6,确实没有 CXXABI_1.3.8:
# strings /opt/codeviz-1.0.12/compilers/gcc-graph/objdir/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6 | grep CXXABI
CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.2
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3
CXXABI_1.3.2
CXXABI_1.3.1
CXXABI_1.3.5
CXXABI_1.3.4
CXXABI_1.3.3
尝试了网上说的很多方法,该问题依然没有解决,感觉跟版本依赖性有关,水挺深的,最终放弃,如果有读者知道怎么解决,诚盼你的留言告知。
总结
由于codeviz必须依赖特定版本的gcc(给其打补丁,并重新编译),codeviz 的版本迭代远远跟不上gcc,造成安装过于费劲(甚至以失败告终,本次体验就没能安装成功),让人望而却步