以下の内容はhttps://daisuke20240310.hatenablog.com/entry/globalより取得しました。


GNU Globalとcflowでソースコードを可視化してみる

最近、ソースコードを読むことが多いので、便利そうなツールを探しています。

しかし、なかなか、新しいよく出来たツールはありません。やはり、昔ながらのツールがいいのかなと思ったりしてます。GNU Global は、昔、サクラエディタで使えるようになった時期があって、少しの間使っていましたが、ctags で十分かな、と思って、いつの間にか使わなくなっていました。

あと、コールツリー(コールグラフ)も、いいツールが無いか、探して見ましたが、結局、cflow になりました。cflow は、C++ には対応していないので、注意が必要です。

GNU Global と cflow を連携させて、HTML化するのは初めて知りました。こちらも紹介したいと思います。

それでは、やっていきます。

GNU Global

GNU Global の公式サイトです。

www.gnu.org

リポジトリを見ると、数か月前に更新がありますね。

インストール

インストールは簡単です。

最新は、6.6.14 ですが、apt でインストールされたのは、6.6.9 です。そんなに古くないので、このままでいきます。

$ sudo apt install global

$ global --version
global (Global) 6.6.9
Powered by Berkeley DB 1.85 and SQLite3 3.40.1.
Copyright (c) 1996-2022 Tama Communications Corporation
License GPLv3+: GNU GPL version 3 or later <http://www.gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

チュートリアル

公式サイトのチュートリアル(https://www.gnu.org/software/global/globaldoc_toc.html)を参考に進めていきます。

まずは、gtagsコマンドで、タグファイルを作成します。

今回は、最近見ていた libusb を対象にやってみます。バージョンは、Parrot OS にデフォルトでインストールされていたバージョンに合わせました。

チュートリアルでは、gtagsコマンドだけを実行していましたが、-v を付けて、verbose mode(出力するログを多くする)で実行しました。

$ git clone https://github.com/libusb/libusb.git

$ cd libusb/

$ git checkout -b v1.0.26 refs/tags/v1.0.26

$ gtags -v
[Sun May 25 20:22:24 JST 2025] Gtags started.
 Using configuration file '/etc/gtags/gtags.conf'.
 Using configuration label 'default'.
[Sun May 25 20:22:24 JST 2025] Creating 'GTAGS' and 'GRTAGS'.
 [1] extracting tags of Xcode/config.h
 [2] extracting tags of android/config.h
 [3] extracting tags of android/examples/unrooted_android.h
(途中、割愛)
 [59] extracting tags of tests/stress.c
 [60] extracting tags of tests/testlib.c
 [61] extracting tags of tests/umockdev.c
[Sun May 25 20:22:25 JST 2025] Done.

$ ll G*
-rw-r--r-- 1 user user  40K  525 20:22 GPATH
-rw-r--r-- 1 user user 592K  525 20:22 GRTAGS
-rw-r--r-- 1 user user 176K  525 20:22 GTAGS

3つのタグファイルが出来ました。それぞれの役割は以下です。

  • GTAGS:definition database(定義データベース)
  • GRTAGS:reference database(参照データベース)
  • GPATH:path name database(パス名データベース)

チュートリアル通り、次は、指定した関数の定義場所を表示し、その後、指定した関数の参照元を表示してみます。

$ global -x libusb_get_device_list
libusb_get_device_list  816 libusb/core.c    ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,

$ global -rx libusb_get_device_list
libusb_get_device_list  184 examples/fxload.c           if (libusb_get_device_list(NULL, &devs) < 0) {
libusb_get_device_list   62 examples/listdevs.c         cnt = libusb_get_device_list(NULL, &devs);
libusb_get_device_list  297 examples/testlibusb.c               cnt = libusb_get_device_list(NULL, &devs);
libusb_get_device_list 1362 libusb/core.c       if (libusb_get_device_list(ctx, &devs) < 0)
libusb_get_device_list  386 libusb/hotplug.c            len = libusb_get_device_list(ctx, &devs);
libusb_get_device_list 1373 libusb/libusb.h  ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx,
libusb_get_device_list   62 tests/stress.c              ssize_t list_size = libusb_get_device_list(ctx, &device_list);
libusb_get_device_list   96 tests/stress.c              ssize_t list_size = libusb_get_device_list(ctx, &device_lists[i]);
libusb_get_device_list  440 tests/umockdev.c    g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, devcount);
libusb_get_device_list  490 tests/umockdev.c            int count = libusb_get_device_list(fixture->ctx, &devs);
libusb_get_device_list  532 tests/umockdev.c    g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 1);
libusb_get_device_list  567 tests/umockdev.c    g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
libusb_get_device_list  572 tests/umockdev.c    g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
libusb_get_device_list  577 tests/umockdev.c    g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
libusb_get_device_list 1084 tests/umockdev.c    g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 1);
libusb_get_device_list 1100 tests/umockdev.c    g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 0);

基本的な使い方は以上です。

lessコマンドでglobalを使ってみる

本来は、エディタと連携させて使うところですが、まずは、lessコマンドでやってみます。

以下を実行すると、lessコマンドで、指定した関数が表示されます。対象が複数ある場合は、t を入力すると次のタグへ移動し、T を入力すると前のタグに戻ります。

$ echo $LESSGLOBALTAGS

$ export LESSGLOBALTAGS=global

$ less -t libusb_get_device_list

HTMLで参照できるようにする

ソースコードを HTML化します。ブラウザ上で、ソースコードを表示することが出来て、ソースコードの中のリンクで関数の定義を確認したりできます。

やり方はとても簡単です。htagsコマンドを実行すると、HTMLディレクトリが作成されます。その中にある index.html をブラウザでアクセスすると、表示できます。

$ htags

$ ll HTML/
合計 216K
drwxr-xr-x 1 user user  188  525 20:48 ./
drwxr-xr-x 1 user user  534  525 20:48 ../
drwxr-xr-x 1 user user 2.7K  525 20:48 D/
-rw-r--r-- 1 user user 2.0K  525 20:48 FILEMAP
drwxr-xr-x 1 user user   32  525 20:48 I/
drwxr-xr-x 1 user user  142  525 20:48 J/
drwxr-xr-x 1 user user  16K  525 20:48 R/
drwxr-xr-x 1 user user  880  525 20:48 S/
drwxr-xr-x 1 user user   20  525 20:48 defines/
-rw-r--r-- 1 user user 185K  525 20:48 defines.html
drwxr-xr-x 1 user user  164  525 20:48 files/
-rw-r--r-- 1 user user  880  525 20:48 files.html
-rw-r--r-- 1 user user  922  525 20:48 help.html
-rw-r--r-- 1 user user 2.6K  525 20:48 index.html
-rw-r--r-- 1 user user 2.6K  525 20:48 mains.html
-rw-r----- 1 user user  555  525 20:48 rebuild.sh
-rwxr-xr-x 1 user user 2.0K  525 20:48 style.css*

globalでHTML化
globalでHTML化

これは、とても便利だと思います。

よく使いそうなオプションを整理しておきます。

オプション 内容
-a アルファベットの一覧を作成してくれる
-g 事前に gtagsコマンドを実行してくれる
-I アイコンを使ってくれる(フォルダのアイコンとか)
-n ソースコードに行番号を付けてくれる
-s 定義と参照以外のシンボルもリンクを作ってくれる

GNU cflow

cflow の公式ページ?です。

www.gnu.org

Git を見ると、まだ更新されてますね。

最新バージョンは、1.7 のようです。

インストール

インストールは簡単です。最新の 1.7 が入りました。

$ sudo apt install cflow

$ cflow -V
cflow (GNU cflow) 1.7
Copyright (C) 2005-2021 Sergey Poznyakoff
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Sergey Poznyakoff.

使ってみる

以下に、cflow のマニュアルがあります。

www.gnu.org

ここの whoami.c をそのまま使わせてもらいます。

いつものソースの貼り方だと、行番号が分からないので、画像で貼ります。画像で貼るとコピペが出来ないので、普段はやらないのですが、上のマニュアルにソースコードはあるので、今回は大丈夫とします。

whoami.c
whoami.c

では、マニュアルにあるように、実行してみます。

同じ出力が得られました。

$ cflow whoami.c
main() <int main (int argc, char **argv) at whoami.c:26>:
    fprintf()
    who_am_i() <int who_am_i (void) at whoami.c:8>:
        getpwuid()
        geteuid()
        getenv()
        fprintf()
        printf()

出力形式は、デフォルトは gnu ですが、posix と dot も選べます。やってみます。

$ cflow -f posix whoami.c
    1 main: int (int argc, char **argv), <whoami.c 26>
    2     fprintf: <>
    3     who_am_i: int (void), <whoami.c 8>
    4         getpwuid: <>
    5         geteuid: <>
    6         getenv: <>
    7         fprintf: <>
    8         printf: <>

$ cflow -f dot whoami.c
digraph cflow {
    node [shape="box"]
    main [label="int main (int argc, char **argv)
whoami.c:26"]
    main -> fprintf
    main -> who_am_i
    fprintf [label="fprintf()"]
    who_am_i [label="int who_am_i (void)
whoami.c:8"]
    who_am_i -> getpwuid
    who_am_i -> geteuid
    who_am_i -> getenv
    who_am_i -> fprintf
    who_am_i -> printf
    getpwuid [label="getpwuid()"]
    geteuid [label="geteuid()"]
    getenv [label="getenv()"]
    printf [label="printf()"]
}

$ sudo apt install graphviz

$ cflow -f dot --output=whoami.dot whoami.c

$ dot -Tpng whoami.dot -o whoami.png

GraphViz を使って、dotファイルを画像ファイルに変換します。いい感じですね。

whoami.png
whoami.png

使えそうなオプションを列挙しておきます。

オプション 内容
--depth=数値 フローグラフの深さを指定した数値に制限する
--format=名前 出力形式を指定する(使用可能: gnu(デフォルト)、posixdot
-o(--output)=ファイル名 出力ファイル名を指定(デフォルトは -、つまり標準出力)
--omit-arguments 関数定義の引数リストを表示しない
-T(--tree) ASCII アートでツリーを描画する

使い方が簡単なので、ソースコードを読むときに、まず動かしてみるのもいいですね。

GNU Globalとcflowを連携させる

以下を参考にさせて頂きました。

lab.mitty.jp

libusb を対象としてやってみます。

$ gtags
$ cflow --tree --format=posix `global -P` > cflow.out
$ cflow --tree --format=posix --reverse `global -P` > cflow-r.out
$ htags -agIns --call-tree cflow.out --callee-tree cflow-r.out --fixed-guide

以下の感じになりました。

HTML化(トップ)
HTML化(トップ)

HTML化(ソースコード)
HTML化(ソースコード)

HTML化(コールツリー)
HTML化(コールツリー)

HTML化(コールツリーリバース)
HTML化(コールツリーリバース)

おわりに

今回は、Linux で使用するツールである tmux の紹介でした。私の場合、常に使っているツールというわけではないのですが、使用頻度が低いだけに、何をどうやって、インストールしたかを忘れてしまうので、記事にした感じです(笑)

最後になりましたが、エンジニアグループのランキングに参加中です。

気楽にポチッとよろしくお願いいたします🙇

今回は以上です!

最後までお読みいただき、ありがとうございました。




以上の内容はhttps://daisuke20240310.hatenablog.com/entry/globalより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14