Help us understand the problem. What is going on with this article?

最強のC/C++インデクサー "Rtags" を本気で使う

More than 3 years have passed since last update.

関数定義や参照へキーひとつで飛ぶことのできるタグジャンプ。いまやコードリーディングに無くてはならない機能ですが、これを可能にするのがCtagsやGNU GLOBAL (Gtags) といった「インデクサー」です。
本記事では、C/C++用の優れたインデクサーであるRtagsのセットアップの方法、そしてVimとの連携の仕方について書いていきます。

Rtagsの利点

インデクサーは、ソースコードをパースして関数や変数などのシンボル名と位置を記録したタグ(インデックス)データベースを作成するプログラムです。
Ctagsは現在最も広く使われているインデクサーの一つで、Cを始めとしてRubyやPythonなど、40あまりの言語に対応しています。ところがC++では文法の複雑さゆえに内部のパーサーが十分に対応できず、正しくシンボル名を認識できなかったりします。Gtagsも同様の問題を抱えています。
そこで最近登場したのがRtagsです。RtagsはC/C++コンパイラであるclangの構文解析インターフェースを利用しているのが特徴です。コンパイラがソースコードのパースをやるわけですからミスは起こりえませんし、非常に合理的です。

Rtagsのインストール

インストール自体はビルドが必要なだけで、特に難しくはありません。

必要なパッケージ

  • libclang >= 3.2 (3.5以上推奨)
  • GCC >=4.7 もしくは clang >= 3.2
  • CMake >= 2.8

私のUbuntu-14.04では下記のコマンドで入りました。llvm-configでlibclangのバージョンを調べると、3.4であることが分かります。

$ sudo apt-get install clang libclang-dev cmake
$ llvm-config --version
3.4

このままでも問題ありませんが、libclangは3.5以上推奨とありますので、3.6を入れてみるのも良いでしょう。

$ sudo apt-get install libclang-3.6-dev
$ /usr/lib/llvm-3.6/bin/llvm-config --version
3.6

この場合はあとでcmakeを行う際に、下記のようにLIBCLANG_LLVM_CONFIG_EXECUTABLEに3.6のllvm-configのパスを与えて実行する必要があります。これを忘れるとデフォルトの3.4が使われてしまいます。

$ LIBCLANG_LLVM_CONFIG_EXECUTABLE=/usr/lib/llvm-3.6/bin/llvm-config cmake ..

ビルド

レポジトリをクローンして、依存するサブモジュールを更新します。

$ git clone https://github.com/Andersbakken/rtags
$ cd rtags
$ git submodule init
$ git submodule update

cmakeでMakefileを生成しビルドします。buildディレクトリを作ってそこからout-of-sourceビルドします。

$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install

out-of-sourceビルドって何?という方はこちらの記事が詳しいです。

Rtagsのセットアップ

インストールが完了すると、rcrdmとというコマンドが使えるようになっているはずです。Rtagsはクライアント・サーバー型のタグシステムで、以下がインデクシングのおおまかな流れになります。

  1. rdmを起動
  2. rcでインデクシング対象ソースファイルのコンパイルコマンドを与える
  3. rdmrcから上記のコマンドを受け取り、インデクシングを行う

rcにコンパイルコマンドを与える方法が一番の肝です。おおまかに2種類の方法があります。

  1. rc -cコマンドで直接渡す
    • 1-1. 直接手打ち
    • 1-2. ラッパースクリプトを使う
  2. rc -Jコマンドでcompile_commands.jsonファイルで渡す
    • 2-1. cmake / ninjaを使う
    • 2-2. bearを使う ★オススメ!

方法1: rc -cコマンドで直接渡す

対象となるソースファイルのコンパイルコマンドを、下記のようにrcに直接渡します。

$ rc -c g++ a.cpp b.cpp

数個のソースファイルならこれでも良いですが、大抵の場合は毎回このようにコマンドを打つのは苦痛です。そこで、作者が用意しているラッパースクリプトを使用する方法があります。以下のようにするのがおすすめです。

## 自分のホームディレクトリにbinディレクトリを作成
$ mkdir ~/bin

## サーチパスの先頭におく
$ echo 'export PATH=${HOME}/bin:${PATH}' >> .bashrc

## ラッパースクリプトをコピー
$ cp rtags/bin/gcc-rtags-wrapper.sh ~/bin/gcc
$ cp rtags/bin/gcc-rtags-wrapper.sh ~/bin/g++

このようにすると、gcc, g++コマンドを打つたびに実際にはこのラッパースクリプトが呼ばれ、内部でrc -cを実行してくれます。コンパイルのたびにインデクシングが行われて大変便利です。もちろんgcc, g++の動作に影響は与えません。

方法2: rc -Jコマンドでcompile_commands.jsonを読み込ませる

compile_commands.jsonは、JSON Compilation Databaseというもので、コンパイルに必要な情報を記録したJSONファイルです。このファイルをrcに読み込ませることでインデクシングを行うことができます

cmakeやninjaといった最近のビルドシステムはビルド時にJSON Compilation Databaseを出力することができますので、下記のようにすればOKです。

## cmakeを使う場合
$ cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=1
$ rc -J .

## ninjaを使う場合
$ ninja -t commands | rc -c -

小規模なプロジェクトでGNU Makeしか使っていないような場合は、Bearというツールの助けを借りることでCompilation Databaseを出力することができます。このやり方が個人的には最もオススメです。
下記のようにビルド&インストールします。

$ git clone https://github.com/rizsotto/Bear
$ cd Bear
$ mkdir build && cd build
$ cmake ..
$ make && sudo make install

使い方は簡単で、通常のmakeコマンドの前にbearと打つだけです。これでMakefileより呼ばれたコンパイルコマンドをもとにCompilation Databaseが出力されます。

$ bear make
$ rc -J .

RtagsをVimから使う

vim-rtagsというプラグインがあります。まだ開発中とのことですが、現時点でも十分な機能を備えています。

インストール・設定

Python拡張を使用していますので+pythonが必須です。NeoBundleで簡単に入ります。

NeoBundle 'lyuts/vim-rtags'

デフォルトのキーマップはストローク数が多くてちょっと打ちづらいです。plugin/rtags.vimにマッピングを行っている箇所があるので、これを参考にして別のキーに割り当てると良いでしょう。私は下記のように設定しています。

" 定義へジャンプ
nnoremap <silent> <F3> :call rtags#JumpTo()<CR>
" 参照へジャンプ
nnoremap <silent> <F4> :<C-u>Unite<Space>rtags/references<CR>
" クラス・関数定義内にいたらその先頭へジャンプ
nnoremap <silent> <F5> :call rtags#JumpToParent()<CR>

使い方

すでにcompile_commands.jsonを出力し、rc -J .を一度は実行させているとします。rdmが起動していなければ起動しておきましょう。

$ rdm --daemon

実際に動かしてみるとこんな感じです。

定義へのジャンプはもちろん、参照へのジャンプも自在です。参照のリストはUniteのウィンドウで開かれるので、絞り込みも簡単です。また、rdmはファイルの変更も監視していて、ソースファイルを保存するとインデックスも同時に自動的に更新されます。

RtagsをEmacsから使う

Rtagsには作者製のEmacs用のプラグインが同梱されています。こちらこちらにすでに詳しい解説がありますので、ご参照ください。

終わりに

以上、C/C++用インデクサー "Rtags" の使い方について説明しました。テキストエディタでIDEと同等以上のコードナビゲーションが可能となり、非常に捗ります。セットアップは少し面倒ですが、C++をメイン言語としている方は導入の価値は大いにあると思います。

kota65535
Web系に憧れる組み込みエンジニア
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした