#author("2024-09-28T12:11:40+09:00","","") #author("2024-09-28T12:13:20+09:00","","") #topicpath /////////////////////////////////////////////////////////////////////////////// * 目次 [#d598aa76] #contents(); /////////////////////////////////////////////////////////////////////////////// * rtags [#aded69fa] - rtags は、llvm をバックエンドに使用したタグ検索システム。 - コンパイラのライブラリを使って解析する為、同名の関数や多重継承でオーバーライドされた関数が複数あっても正しいものに辿り着ける。 - サーバ&クライアントシステムになっている。 -- rtags システムにはコンパイル方法を入力し(直接コンパイルするコマンドを与えるか、compile_commands.json を読み込ませる)、それを基にサーバが解析を行う。 -- クライアントからの問い合わせを受けてからサーバが解析を始めることもあるらしく、応答が遅いときがある。 - Linux kernel のような巨大な project では、タグ生成の為の情報として使われる json ファイルの生成や問い合わせ時の解析時のパフォーマンスが下がるので、あまり適さない。 - コメント文字列のような、コンパイルに使われないものについては検索出来ない。(cscopeではコメント文字列も検索対象に出来る) - このように、cscope や gtags 等の他のタグシステムとは長所・短所共に異なるので、これらのタグシステムの一つと組み合わせて使うのが良いと思われる。 //============================================================================== ** 環境構築(debian パッケージを使用) [#build-env-debian-package] + 必要な関連パッケージをインストールする # apt-get install rtags + コマンド名はオリジナルから若干アレンジされているので注意(他パッケージとの名前の干渉を避ける為と思われる)。 |>|~コマンド名 | |~オリジナル |~debian パッケージ版 | |rc |rtags-rc | |rdm |rtags-rdm | |rp |rp | -- rtags-rc に関しては、9base パッケージの rc コマンドとの重複を避けるためと思われる。 -- 記載が煩雑になるが、本頁では rc, rdm について、説明文中では &color(red){rc};, &color(red){rdm}; とし、コマンドラインについては Debian ベースの &color(red){rtags-rc};, &color(red){rtags-rdm}; の表記を使用する。 //============================================================================== ** 環境構築(自前ビルド) [#build-env-build] + 必要な関連パッケージをインストールする # apt-get install clang libclang-dev cmake + rtags をビルドする(rtags がディストリビューションでパッケージが用意されているなら、そちらを使うと良い) ++ コードを取得する $ git clone --recursive https://github.com/Andersbakken/rtags ++ ビルドする $ cd rtags $ git submodule init $ git submodule update $ mkdir build $ cd build $ cmake .. $ make $ sudo make install ~ + rtags をインストールする -- ビルドすると rtags/build/bin に以下の実行形式が生成されるので、環境変数 PATH の通っているところに配置する。 $ ls rtags/build/bin rtags-rc rtags-dm rp //============================================================================== ** タグを生成する [#u9c384fe] + まず、daemon を起動する $ rtags-dm --daemon + タグを生成する方法は2つある //------------------------------------------------------------------------------ *** 1. rc コマンドに直接渡す [#p77de85a] - 実際に compile するときのコマンドを rc に渡す。 $ rtags-rc gcc $(CFLAGS) $(SRCS) //------------------------------------------------------------------------------ *** 2. rc -Jコマンドで compile_commands.json を読み込ませる [#xa2d2a47] - compile_commands.json の生成方法は、[[compile_commands.json の生成方法>#create_compile_commands_json]] を参照。 - rc -Jコマンドで compile_commands.json を読み込ませる $ rtags-rc -J <compile_commands.jsonが置かれているディレクトリのパス> -- ここでエラーになる場合、compile_commands.json が無意味な内容になっている可能性がある。 --- 原因としては、ビルド済みの環境で bear コマンドを走らせていた可能性がある。 --- 対策としては、make clean してから再度 bear -- make を実行する必要がある。 -- compile_commands.json の中でのソースファイル等のパスは / からの絶対パスで記述されるため、compile_commands.json を他の場所に移動してから使用しても全く問題ない。 //============================================================================== ** rtags-rdm の終了 [#ta139a3e] - rdm を終了するには、 rc にて以下のコマンドを実行する: $ rtags-rc -q //============================================================================== ** プロジェクト情報の unload [#w3a904bc] - rtags サーバ (rdm / rtags-rdm) は、quit しても、それまでに load したプロジェクト情報を忘れないようになっている。つまり、再度起動したときには、前回終了した時点で load 済だったプロジェクト情報を load した状態となる。 - load したプロジェクト情報を rtags サーバに忘れさせるには、明示的にその旨コマンド実行する必要がある。 -- 指定したプロジェクトを unload する。 $ rtags-rc --delete-project [keyword-project-to-be-deleted] --- [keyword-project-to-be-deleted] にマッチする全ての project 情報を unload する。 -- 全ての project 情報を unload する。 $ rtags-rc --clear //============================================================================== ** current project の切り替え [#x4de7023] - 複数の project を読み込んでいる時、current project になっていないコードのシンボルを上手く検索出来ない場合がある(どういうときにそうなるのかはイマイチ不明)。 - そうした場合に、検索対象のコードが属する project を current project に切り替える。 $ rtags-rc -p <current projectにしたいproject> -- <current projectにしたいproject> は、rtags-rc -p を引数なしで実行した際に表示される project 一覧 project を特定出来る最小限の文字列を指定すれば OK //============================================================================== ** トラブルシューティング [#ca4c6252] //------------------------------------------------------------------------------ *** "Can't seem to connect to server (/run/user/1000/rdm.socket)" [#h08b2dc0] - rtags-rdm のプロセスが存在するが、ソケットが存在しない状態。 - pgrep で PID を確認し、その PID を指定して強制終了する。 -- 実行例: $ pgrep -l rtags 19044 rtags-rdm $ kill -KILL 19044 - 上記の実施後、改めて rtags-rdm を起動し、コンパイル情報を与える。 /////////////////////////////////////////////////////////////////////////////// * emacs から rtags を使う [#rtags-emacs] //============================================================================== ** emacs の設定 [#b2c2d73e] - ディストリビューションで提供しているパッケージで rtags と emacs を導入済みであれば、rtags.el が emacs の load-path の通っているところに配置される筈。もしなければ手動で配置する。rtags.el は、rtag リポジトリの下記にある。 build/src/rtags.el - rtags.el の標準のキーバインドは、rtags.el を読み込んだだけでは有効にはならない。読み込んだ後に以下を設定に書く必要がある: (rtags-enable-standard-keybindings); enable rtags standard keymap - submenu-list も、必要なら同様に設定する: (rtags-submenu-list) ; enable rtags submenu list keymap - init.el の設定例 ;;; rtags.el の設定 (when (require 'rtags nil 'noerror) (when (executable-find "rtags-rc") (setq rtags-rc-binary-name "rtags-rc")) ; debian では rc -> rtags-rc に変更されている (when (executable-find "rtags-rdm") (setq rtags-rdm-binary-name "rtags-rdm")) ; debian では rdm -> rtags-rdm に変更さている (defun rtags-local-conf () (rtags-mode) (rtags-start-process-unless-running) (setq rtags-autostart-diagnostics t) (rtags-diagnostics) (setq rtags-completions-enabled t) (rtags-enable-standard-keybindings) ; enable rtags standard keymap (rtags-submenu-list) ; enable rtags submenu list ;;; キーバインド:ネットでよく見掛ける設定だが、行末コメントの通り他のバインドを上書きしていてあまり良くないので使わない。 ; (local-set-key (kbd "M-.") 'rtags-find-symbol-at-point) ; batting with 'xref-find-definitions' ; (local-set-key (kbd "M-;") 'rtags-find-symbol) ; batting with 'comment-dwim' ; (local-set-key (kbd "M-@") 'rtags-find-references) ; batting with 'mark-word' ; (local-set-key (kbd "M-,") 'rtags-location-stack-back) ; batting with 'xref-pop-marker-stack' ; (local-set-key (kbd "M-<") 'rtags-location-stack-back) ; batting with 'beginning-of-buffer' ; (local-set-key (kbd "M->") 'rtags-location-stack-forward) ; batting with 'end-of-buffer' ;;; キーバインド:実際にはこちらを使う ;;; xcscope.el に操作感を似せつつ、併用出来るようキーバインドが被らないようにしている (local-set-key (kbd "C-c d d") 'rtags-find-symbol-at-point) (local-set-key (kbd "C-c d s") 'rtags-find-symbol) (local-set-key (kbd "C-c d r") 'rtags-find-all-references-at-point) (local-set-key (kbd "C-c d c") 'rtags-find-all-functions-called-this-function) (local-set-key (kbd "C-c d f") 'rtags-find-file) (local-set-key (kbd "C-c d i") 'rtags-symbol-info) (local-set-key (kbd "C-c d m") 'rtags-imenu) (local-set-key (kbd "C-c d t") 'rtags-taglist) (local-set-key (kbd "C-c d C") 'rtags-print-class-hierarchy) (local-set-key (kbd "C-c d <") 'rtags-location-stack-back) (local-set-key (kbd "C-c d >") 'rtags-location-stack-forward) (define-key rtags-mode-map "p" 'rtags-previous-match) (define-key rtags-mode-map "n" 'rtags-next-match) ) (add-hook 'c-mode-common-hook 'rtags-local-conf) (add-hook 'c++-mode-common-hook 'rtags-local-conf) (add-hook 'objc-mode-hook 'rtags-local-conf) ) -- 上記では、Debian / Ubuntu のパッケージで rc, rdm のコマンド名が変更されているのにも対応している。 //============================================================================== ** rtags.el の標準キーバインド [#t5a7c8b3] |~binding |~function |~description |~remark | |C-c r ,|rtags-find-references-at-point |現在のカーソル位置のシンボルの定義を検索 | | |C-c r .|rtags-find-symbol-at-point |現在のカーソル位置のシンボルを検索 | | |C-c r /|rtags-find-all-references-at-point |現在のカーソル位置のシンボルの参照元を検索 | | |C-c r ;|rtags-find-file |現在のカーソル位置のファイル名を検索 |複数ある場合は検索対象をTAB補完で選択 | |C-c r ;|rtags-find-file |ファイル名からファイルを検索して開く |複数ある場合は検索対象をTAB補完で選択 | |C-c r <|rtags-find-references | | | |C-c r >|rtags-find-symbol |対話式に指定したシンボルを検索 | | |C-c r A|rtags-find-functions-called-by-this-function |指定した関数から呼び出している関数を検索 |結果一覧(*RTags*バッファ)上で [Enter] 押しで、呼び出された側の関数の関数定義に Jump する | |C-c r B|rtags-show-rtags-buffer | | | |C-c r C|rtags-compile-file | | | |C-c r D|rtags-diagnostics | | | |C-c r E|rtags-preprocess-file | | | |C-c r F|rtags-fixit | | | |C-c r G|rtags-guess-function-at-point | | | |C-c r I|rtags-imenu | | | |C-c r K|rtags-make-member | | | |C-c r L|rtags-copy-and-print-current-location |現在カーソルがある位置のファイルのパス、行番号、カラム数をミニバッファに表示 | | |C-c r M|rtags-symbol-info |カーソル位置のシンボルのサイズ(sizeof())、アライメントなどの情報を表示 | | |C-c r O|rtags-goto-offset | | | |C-c r P|rtags-dependency-tree-all | | | |C-c r R|rtags-rename-symbol | | | |C-c r S|rtags-display-summary | | | |C-c r T|rtags-taglist |タグの一覧を表示 | | |C-c r U|rtags-display-summary-as-message | | | |C-c r V|rtags-print-enum-value-at-point |enum 値の定義位置にカーソルを置いた状態で実行すると、その enum 定義値の値を表示する |enum 値の参照先では機能しない | |C-c r X|rtags-fix-fixit-at-point | | | |C-c r Y|rtags-cycle-through-diagnostics | | | |C-c r Z|rtags-location-stack-visualize | | | |C-c r [|rtags-location-stack-back |一つ前の検索履歴に戻る | | |C-c r ]|rtags-location-stack-forward |一つ先の検索履歴に進む |rtags-location-stack-back で一つ以上検索履歴を戻った状態であることが前提 | |C-c r _|rtags-asm-file | | | |C-c r a|rtags-expand-auto | | | |C-c r e|rtags-reparse-file | | | |C-c r h|rtags-print-class-hierarchy |クラス階層を表示 | | |C-c r l|rtags-list-results | | | |C-c r p|rtags-dependency-tree |ソース・ヘッダの依存関係を表示 | | |C-c r t|rtags-references-tree |参照ツリー(指定したシンボルが関数であれば、その callstack に相当する情報)を表示 |実行した際、画面上何も起こってないように見えるときは、*RTags* バッファを手動で表示する。&br;*RTags* バッファで [Tab] キーを押すと、カーソル位置の行の呼び出し階層表示が1階層ずつ展開される。 | |C-c r v|rtags-find-virtuals-at-point | | | //============================================================================== ** 機能(一部のみ) [#saa05fe7] - 数多く定義されている API のうち、比較的使う機会の多い一部機能のみ記載する //------------------------------------------------------------------------------ *** rtags-find-symbol-at-point : カーソルが置かれたシンボルの定義を表示する [#w004a611] |~カーソルが指しているもの |~ジャンプ先 |~備考 | |実体やポインタ変数 |定義位置 | | |型名 |型の定義位置 | | //------------------------------------------------------------------------------ *** rtags-print-class-hierarchy : クラス階層構造の表示 [#jdb15cdc] - クラスの型名にカーソルを置いて実行すると、そのクラスの階層構造を表示する - 例 Superclasses: class TestDataB c++/polymorphism/test_data_b.h:6:7: class TestDataB : public TestDataIF class TestDataIF c++/polymorphism/test_data_if.h:4:7: class TestDataIF //------------------------------------------------------------------------------ *** rtags-find-all-references-at-point : 参照元(=呼び出し箇所)を全て表示する [#z198ace6] - xcscope の cscope-find-this-symbol と大体同じ。 //------------------------------------------------------------------------------ *** 検索履歴の移動 [#q15cfd46] - rtags-location-stack-back -- 検索する前の位置に戻る -- 前回検索後からカーソルを移動していた場合、前回検索したときに rtags でジャンプした位置まで戻る。 - rtags-location-stack-forward -- rtags-location-stack-back で1回以上履歴を戻った後、再びその後の検索結果にジャンプする。 -- 当然ながら、一度も rtags-location-stack-back を実行していない場合は動作しない。 //------------------------------------------------------------------------------ *** rtags-taglist [#o67e241d] - 全てのシンボルに関する tag の一覧を表示する /////////////////////////////////////////////////////////////////////////////// * Makefile に rtags 用 tag 生成の target を仕込む(おまけ) [#r52d7a6e] - 下記を Makefile の target として仕込み、 $ make rtags とすれば、tag 生成までの一通りの処理が実行される(但し、 clean ターゲットは別途用意されている前提となる): # for rtags: RTAGS_CMD_RC := /usr/bin/rtags-rc RTAGS_CMD_RDM := /usr/bin/rtags-rdm BEAR_CMD := /usr/bin/bear COMPILE_DB_FILE := compile_commands.json IS_RTAGS_RDM_STARTED := $(shell ls -1 /run/user/$(shell id -u)/rdm.socket 2>/dev/null| wc -l) rtags : rtags-kill-daemon rtags-delete-compile-db clean rtags-start-daemon rtags-create-compile-db rtags-load-compile-db rtags-kill-daemon : ifeq ($(IS_RTAGS_RDM_STARTED),1) pgrep rtags-rdm | xargs kill -KILL; endif rtags-delete-compile-db : $(RMF) $(COMPILE_DB_FILE) rtags-start-daemon : $(RTAGS_CMD_RDM) --daemon; rtags-create-compile-db : $(BEAR_CMD) -- make; rtags-load-compile-db : $(RTAGS_CMD_RC) -J .; /////////////////////////////////////////////////////////////////////////////// * トラブルシューティング [#mb3e0b08] //============================================================================= ** daemon 起動が SIGABRT (=6) で失敗する [#dcc02d36] - 失敗時 $ rtags-rdm --daemon rtags-rdm: ./src/Location.h:275: static void Location::set(const Path&, uint32_t): Assertion `!refId || refId == fileId' failed. Caught signal 6 /usr/bin/rtags-rdm(+0x72762)[0x5587b57d3762] /lib/x86_64-linux-gnu/libc.so.6(+0x38d60)[0x7fea6277cd60] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x141)[0x7fea6277cce1] /lib/x86_64-linux-gnu/libc.so.6(abort+0x123)[0x7fea62766537] /lib/x86_64-linux-gnu/libc.so.6(+0x2240f)[0x7fea6276640f] /lib/x86_64-linux-gnu/libc.so.6(+0x31662)[0x7fea62775662] /usr/bin/rtags-rdm(_ZN8Location3setERK4Pathj+0x1cb)[0x5587b5850beb] /usr/bin/rtags-rdm(_ZN7Project11readSourcesERK4PathR14IndexParseDataP6String+0x3b2)[0x5587b58f1b62] /usr/bin/rtags-rdm(_ZN7Project4initEv+0x23a)[0x5587b58f200a] /usr/bin/rtags-rdm(_ZN6Server10addProjectERK4Path+0x102)[0x5587b5803e92] /usr/bin/rtags-rdm(_ZN6Server4loadEv+0x107a)[0x5587b580651a] /usr/bin/rtags-rdm(_ZN6Server4initERKNS_7OptionsE+0x10d7)[0x5587b5809037] /usr/bin/rtags-rdm(main+0x2734)[0x5587b57d1424] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea)[0x7fea62767d0a] /usr/bin/rtags-rdm(_start+0x2a)[0x5587b57d364a] - 対処法: --clean-slate (または -C) オプションを使って実行してから、再度起動する $ rtags-rdm -C $ rtags-rdm --daemon /////////////////////////////////////////////////////////////////////////////// * バージョン組み合わせメモ [#v824a60e] - 動作が確認出来た組み合わせは以下の通り: |>|>|~version |~distribution |~remark | |~rtags |~rtags.el |~emacs |~|~| |2.38-3 |2.41.133 |29.1 |Debian 11 (bullseye) |emacs は自前ビルドしたもの | |2.38-3 |2.41.133 |28.2 |Debian 11 (bullseye) |emacs は自前ビルドしたもの | |2.38-3 |2.38.130 |27.1 |Debian 11 (bullseye) |いずれも Debian11 公式リリース版 | |2.37-1 |2.37.130 |26.3 |Ubuntu 20.04 (focal) |emacs は Ubuntu20.04 公式リリース版 | /////////////////////////////////////////////////////////////////////////////// * linux kernel に使えるか? [#febdfd95] - 対象:linux-6.1.1 - compile_command.json 生成 -- bear コマンドを使ったところ、ビルド開始から json 生成完了までおよそ24時間ほど掛かった。実行環境は下記(参考までに): |~CPU |i7-1165G7 | |~Memory |32GB | |~Storage |MZVLB1T0HBLR-000L7 (Samsung) | -- 指定したオプションでコンパイル対象となっていないファイルは compile_command.json にも記載されない為、rtags の検索対象からも外れる。 /////////////////////////////////////////////////////////////////////////////// * compile_commands.json の生成方法 [#create_compile_commands_json] - compile_commands.json の生成方法には、以下の方法がある //============================================================================= ** bear を使った compile_commands.json の生成 [#w48bd344] - &color(red){注:下記の make で呼ばれる Makefile で clang を使っていると、後述のコマンド '''"rc -J . "''' を実行したときに失敗することがある模様。その為、Makefile でコンパイラの指定は clang ではなく gcc を使うと良い。}; + bear コマンドがインストールされていない場合は、インストールする # apt-get install bear + bear コマンドの実行(環境によっては "--" が不要な場合があるので注意。) $ bear -- make -- 既に compile_command.json があり、且つクリーンビルドでない場合は、 bear に --append オプションが必要(まだ試してはない) -- ※ Ubuntu20.x の bear コマンドでは、コマンド名と make の間に引数 "--" を付けてはならない模様。 //============================================================================= ** compiledb を使った compile_commands.json の生成 [#kdb6c47b] + インストール -- compiledb は python で書かれており、 pip でもインストールすることが出来る $ pip3 install compiledb + 実行 -- コンパイルしながら生成する場合 $ compiledb make -- コンパイルせずに生成する場合 $ compiledb -n make //============================================================================= ** cmake を使ったプロジェクトでの compile_commands.json の生成 [#h796cfa9] $ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON <ソースコードディレクトリへの[相対]パス> /////////////////////////////////////////////////////////////////////////////// * 参考リンク [#ib49a8ea] - [[Home · Andersbakken/rtags Wiki · GitHub(開発元 github の wiki)>https://github.com/Andersbakken/rtags/wiki]] - [[最強のC/C++インデクサー "Rtags" を本気で使う>https://qiita.com/kota65535/items/39aa4d6e8adf6ab5f98c]] - [[Rtags で BitVisor の開発を楽になるか?>https://qiita.com/deep_tkkn/items/eb24cb2f0713c7fc4162]]