コールグラフを描く2つのツール(EgyptとCodeViz)

休日(でなくてもいいけれど)の読書の題材としてコンピュータ・プログラムを選んだとき、単にコードを読むだけでなく、何か図形的な補佐が欲しいと思うことがある。

オブジェクト指向の言語だとUML図が便利だが、別のパラダイムではあまり役に立たない。

たとえばC言語では、プログラムの構成要素である関数(というか手続き)の呼び出し合う関係を視覚化できると少しうれしい(「すごくうれしい」とまではいかない)。

次のようなコードがあったとする。

#include <stdio.h>

int fib(int n)
{
  if (n<3) return 1;
  return fib(n-2)+fib(n-1);
}

int main()
{
  int i;
  for (i=1; i<=10; ++i) {
    printf("fibonacci(%d) = %d\n", i, fib(i));
  }
  return 0;
}

2つの関数fibとmainの呼び出し関係は次のようになっている。

  • main→fib
  • fib→fib

このような、有向グラフをコールグラフと呼ぶ。

GNU Binutilsに含まれるgprofを使えばコールグラフを生成できるのだが、そのためには一度プログラムを実行しなければならず、得られるコールグラフも、実行時に呼び出された関数のみのものだという欠点がある。

ついでに、グラフがあればそれを描画したいというのが人情だから(グラフが大きいとあまり意味がないのだが)、下のような絵が描けるとうれしい。

というわけで、コールグラフを描画するためのツールであるEgyptとCodeVizを試す。

  • Egypt: Cのコードを解析してコールグラフを生成
  • CodeViz: CとC++のコードを解析してコールグラフを生成。パッチを当てたGCCを用意するため、導入に少し時間がかかる

準備

想定する環境はUbuntu。

共通の準備

2つのツールともグラフの描画まではやってくれない。どちらも描画はGraphVizに任せるようになっているため、まずはGraphVizをインストールする。

apt-get install graphviz

Egypt

Egyptのインストール手順は以下の通り。

wget http://www.gson.org/egypt/download/egypt-1.6.tar.gz
tar zxf egypt-1.6.tar.gz
cd egypt-1.6
perl Makefile.PL
make
sudo make install

Cygwinでは最後の「make install」で失敗した(というわけで想定環境はUbuntu)。

CodeViz

CodeVizのインストール手順は以下の通り。

wget http://www.csn.ul.ie/~mel/projects/codeviz/codeviz-1.0.11.tar.gz
tar zxf codeviz-1.0.11.tar.gz
cd codeviz-1.0.11/compilers
wget http://ftp.yz.yamagata-u.ac.jp/pub/GNU/gcc/gcc-3.4.6/gcc-3.4.6.tar.gz
cd ..
./configure --prefix=インストール先
make
sudo make install
export PATH=インストール先/gccgraph/bin:$PATH

使い方

Egypt

Egyptの使い方は以下の通り(詳しい使い方は「man egypt」)。

gcc -dr fib.c #fib.c.131r.expandができる
egypt fib.c.131r.expand > egypt.dot
dot -Tgif -Grankdir=LR egypt.dot -o egypt.gif

「-dr」はRTLを生成するためのオプション。「-Grankdir=LR」は階層を左から右に向かって描くためのオプション(デフォルトは上から下)。最後に紙に出力したいなら、「-Tps」としてPostscriptにするといいだろう。

CodeViz

CodeVizの使い方は以下の通り。

gcc fib.c #fib.c.cdepnができる
genfull #full.graphができる。詳しい使い方は「genfull --man」
dot -Tgif -Grankdir=LR full.graph -o full.gif

今読んでいるコード中にあるものだけに限定したい場合は、gengraphを使う(-fは最上位の関数を指定、–plainはdotファイルを出力するための、–no-externは外部のファイルを無視するためのオプション。詳しい使い方は「gengraph –man」)

gengraph -f main --plain --no-extern #main.plainができる。
dot -Tgif -Grankdir=LR main.plain -o main.gif

Startrek

グラフが少しでも大きくなると実用性に疑問が生じてくる。

Chris NystromさんのSuper Star Trek Classicコードで試す。このコードはBASICをそのままCに翻訳したものであるため、今日の基準では、読みやすいとは言えないだろう。それでも読みたいというときに、コールグラフが役立つはず。(Startrek自体に興味がある向きはWikipediaの記事を参照)

Egypt

CodeViz

Code Reading―オープンソースから学ぶソフトウェア開発技法 (単行本)コールグラフは扱われていないが、休日の読書のガイドにはDiomidis Spinellis『Code Reading』(毎日コミュニケーションズ, 2004)がおすすめ。(新版