lctags†
環境構築†
- コードの取得
$ git clone https://github.com/ifritJP/lctags.git
- 追加パッケージのインストール
- swig (ビルドに必要)
- liblua50-dev
- lua5.3
- luajit
- liblua5.3-dev
- libssl-dev
- 他モジュールのコードを取得・展開
$ cd lctags/external
$ curl http://lua.sqlite.org/index.cgi/zip/lsqlite3_fsl09x.zip?uuid=fsl_9x -o luasqlite3.zip
$ unzip luasqlite3.zip
$ cp -Rfdp lsqlite3_fsl09x/ luasqlite3/
$ curl https://www.lua.org/ftp/lua-5.3.4.tar.gz -o lua/lua-5.3.4/src/lua.tar.gz
$ tar -xvzf lua.tar.gz
$ mv lua-5.3.4 lua/
- ビルド
- src/makefile の修正
diff --git a/src/makefile b/src/makefile
index d3dde80..9a92a49 100644
--- a/src/makefile
+++ b/src/makefile
@@ -1,128 +1,152 @@
NDIR=$(shell pwd)
-INST_DIR=/usr/local/bin
+INST_DIR := /usr/local/bin
-PROXY=
+PROXY :=
-SWIG=swig
+SWIG := swig
INSTALL=/usr/bin/install -c
-SO=so
-## cygwin
-#SO=dll
+LUA_VER := 5.3
+# LUA_VER := 5.2
+# LUA_VER := 5.1
-####### customize Lua environment ######
+LUAJIT_VER := 2.0.4
+# LUAJIT_VER := $(shell luajit -v | awk '{print $2;}')
+
+CLANG_VER := 7
+# CLANG_VER=3.8
+
+UNAME := $(shell uname -a)
+ifeq ($(filter Darwin,$(UNAME)),Darwin)
+OS := mac
+else
+ifeq ($(filter Linux,$(UNAME)),Linux)
+OS := linux
+else
+ifeq ($(filter MINGW,$(UNAME)),Cygwin)
+OS := cygwin
+else
+$(info Your platform $(UNAME) is not supported.)
+endif
+endif
+endif
+ifeq ($(OS),cygwin)
## cygwin
-# LUA_COMMAND=lua
-# LUA_INC=/usr/include
-# LUA_LDFLAGS=
-# LUA_SO=-llua
+SO := dll
+else
+SO := so
+endif
-# LUA_COMMAND=lua5.1
-# LUA_INC=/usr/include/lua5.1
-# LUA_LDFLAGS=
-# LUA_SO=-llua5.1
+####### customize Lua environment ######
+ifeq ($(OS),cygwin)
+## cygwin
+LUA_COMMAND := lua
+LUA_INC := /usr/include
+LUA_LDFLAGS :=
+LUA_SO := -llua
-LUA_COMMAND=lua5.3
-LUA_INC=/usr/include/lua5.3
-LUA_LDFLAGS=
-LUA_SO=-llua5.3
+else
+LUA_COMMAND := lua$(LUA_VER)
+LUA_INC := /usr/include/lua$(LUA_VER)
+LUA_LDFLAGS :=
+LUA_SO := -llua$(LUA_VER)
+endif
-# LUA_COMMAND=luajit
-# LUA_INC=/usr/include/luajit-2.0
-# LUA_LDFLAGS=
-# LUA_SO=-lluajit-5.1
+# LUA_COMMAND := luajit
+# LUA_INC := /usr/include/luajit-2.0
+# LUA_LDFLAGS :=
+# LUA_SO := -lluajit-5.1
-# LUA_COMMAND=./clanglua
-# LUA_CFLAGS=-fPIC -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -I$(NDIR)/$(LUA_DIR)
-# LUA_DIR=../external/lua/lua-5.3.4/src
-# LUA_INC=$(NDIR)/$(LUA_DIR)
-# LUA_LIB=$(LUA_DIR)/liblua.a
-# LUA_INST_DIR=/usr/local/bin
-# LUA_LIB_DIR=/usr/local/lib/lua/5.3
-# LUA_LDFLAGS=-lncursesw
+# LUA_COMMAND := ./clanglua
+# LUA_CFLAGS := -fPIC -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -I$(NDIR)/$(LUA_DIR)
+# LUA_DIR := ../external/lua/lua-5.3.4/src
+# LUA_INC := $(NDIR)/$(LUA_DIR)
+# LUA_LIB := $(LUA_DIR)/liblua.a
+# LUA_INST_DIR := /usr/local/bin
+# LUA_LIB_DIR := /usr/local/lib/lua/5.3
+# LUA_LDFLAGS := -lncursesw
-TEST_LUA_DIR=../external/lua/lua-5.3.4/src
+TEST_LUA_DIR := ../external/lua/lua-5.3.4/src
-LUA_URL="https://www.lua.org/ftp/lua-5.3.4.tar.gz"
+LUA_URL := "https://www.lua.org/ftp/lua-5.3.4.tar.gz"
-LUA_COMMAND_FULL:=$(shell python -c 'import os; print( os.path.abspath( "$(shell which $(LUA_COMMAND))" ) );' )
+LUA_COMMAND_FULL := $(shell python -c 'import os; print( os.path.abspath( "$(shell which $(LUA_COMMAND))" ) );' )
####### customize libclang environment ######
+ifeq ($(OS),cygwin)
## cygwin
-# LIBCLANG_INC=/usr/include
-# LIBCLANG_LIB=/lib
-# LIBCLANG_STD_INC=/lib/clang/5.0.1/include
-
-
-CLANG_VER=3.8
-LIBCLANG_INC=/usr/lib/llvm-$(CLANG_VER)/include
-LIBCLANG_LIB=/usr/lib/llvm-$(CLANG_VER)/lib
-LIBCLANG_STD_INC=$(shell find /usr/lib/llvm-$(CLANG_VER)/lib/clang/ -maxdepth 1 -mindepth 1 | head -n 1)
+LIBCLANG_INC := /usr/include
+LIBCLANG_LIB := /lib
+LIBCLANG_STD_INC := /lib/clang/5.0.1/include
-# LIBCLANG_DIR=/proj/next/clang/r34-final
-# LIBCLANG_INC=../external/clang/r390/llvm/tools/clang/include
-# LIBCLANG_STD_INC=../external/clang/r390/build/lib/clang/3.9.0/include
-# LIBCLANG_LIB=/usr/lib/llvm-$(CLANG_VER)/lib
+else
+LIBCLANG_INC := /usr/lib/llvm-$(CLANG_VER)/include
+LIBCLANG_LIB := /usr/lib/llvm-$(CLANG_VER)/lib
+LIBCLANG_STD_INC := $(shell find /usr/lib/llvm-$(CLANG_VER)/lib/clang/ -maxdepth 1 -mindepth 1 | head -n 1)
-# LIBCLANG_SO=-lclang
+# LIBCLANG_DIR := /proj/next/clang/r34-final
+# LIBCLANG_INC := ../external/clang/r390/llvm/tools/clang/include
+# LIBCLANG_STD_INC := ../external/clang/r390/build/lib/clang/3.9.0/include
+# LIBCLANG_LIB := /usr/lib/llvm-$(CLANG_VER)/lib
+endif
-LIBCLANG_SO=-lclang
+LIBCLANG_SO := -lclang
####### customize luasqlite3 environment ######
# If you don't have luasqlite3, you must customize this setting.
# http://lua.sqlite.org/index.cgi/index
-LUASQLITE3_WORKDIR=../external/luasqlite3
-LUASQLITE3_DIR=$(LUASQLITE3_WORKDIR)/lsqlite3_fsl09x
-#USE_BDB_SQLITE=y
+LUASQLITE3_WORKDIR := ../external/luasqlite3
+LUASQLITE3_DIR := $(LUASQLITE3_WORKDIR)/lsqlite3_fsl09x
+#USE_BDB_SQLITE := y
-LUASQLITE3_URL="http://lua.sqlite.org/index.cgi/zip/lsqlite3_fsl09x.zip?uuid=fsl_9x"
+LUASQLITE3_URL := "http://lua.sqlite.org/index.cgi/zip/lsqlite3_fsl09x.zip?uuid=fsl_9x"
####### make rules ######
-LUA_LIB_DIR=$(shell echo $(LUA_DIR_LIB) | $(LUA_COMMAND) )
-LUA_MOD_DIR=$(shell echo $(LUA_DIR_SCRIPT) | $(LUA_COMMAND) )
+LUA_LIB_DIR := $(shell echo $(LUA_DIR_LIB) | $(LUA_COMMAND) )
+LUA_MOD_DIR := $(shell echo $(LUA_DIR_SCRIPT) | $(LUA_COMMAND) )
-LCTAGS_LOG=4
-JOBS=3
+LCTAGS_LOG := 4
+JOBS := 3
ifdef LCTAGS_PROF
-LCTAGS_PROF_OP = --lctags-prof
+LCTAGS_PROF_OP := --lctags-prof
endif
-LCTAGS_LOCKLOG=y
+LCTAGS_LOCKLOG := y
ifdef LCTAGS_LOCKLOG
-LOCKLOG = --lctags-lockLog
+LOCKLOG := --lctags-lockLog
endif
ifdef LCTAGS_SERVER_ON
-LCTAGS_SERVER=--lctags-srv
+LCTAGS_SERVER := --lctags-srv
endif
-LUA_LIB:=$(addprefix $(NDIR)/,$(LUA_LIB))
+LUA_LIB := $(addprefix $(NDIR)/,$(LUA_LIB))
-LCTAGS_LUA=lctags/lctags.lua
+LCTAGS_LUA := lctags/lctags.lua
-#OPT_OP = -O3
+#OPT_OP := -O3
-IF_LUA = libclanglua/if.lua
-IFC_LUA = libclanglua/ifc.lua
-COREBASE_SO = libclanglua/coreBase.$(SO)
-CORE_SO = libclanglua/core.$(SO)
+IF_LUA := libclanglua/if.lua
+IFC_LUA := libclanglua/ifc.lua
+COREBASE_SO := libclanglua/coreBase.$(SO)
+CORE_SO := libclanglua/core.$(SO)
-LUA_DIR_SCRIPT='for path in string.gmatch( package.path, "[^;]+" ) do if path:find( ".*lua.*%?%.lua" ) then print( (path:gsub( "/%?%.lua", "" )) ); break end end'
-LUA_DIR_LIB="for path in string.gmatch( package.cpath, '[^;]+' ) do if path:find( \".*lua.*%?%.$(SO)\" ) then print( (path:gsub( \"/%?%.$(SO)\", '' ))); break end end"
+LUA_DIR_SCRIPT := 'for path in string.gmatch( package.path, "[^;]+" ) do if path:find( ".*lua.*%?%.lua" ) then print( (path:gsub( "/%?%.lua", "" )) ); break end end'
+LUA_DIR_LIB := "for path in string.gmatch( package.cpath, '[^;]+' ) do if path:find( \".*lua.*%?%.$(SO)\" ) then print( (path:gsub( \"/%?%.$(SO)\", '' ))); break end end"
ifneq ($(LUA_DIR),)
-TARGET_LUA = $(LUA_COMMAND)
+TARGET_LUA := $(LUA_COMMAND)
endif
all:
@@ -254,11 +278,11 @@ test-simple:
ifdef BATCH
-BATCH_OP=--lctags-only-reg
+BATCH_OP := --lctags-only-reg
endif
ifeq ($(INDIV),y)
-INDIV_OP=--lctags-indiv
+INDIV_OP := --lctags-indiv
endif
- ビルド(lctags のトップディレクトリに戻ってから)
$ make build
成功すると、以下のファイルが出来る
src/lsqlite3.so
src/lctags/Helper
src/lctags/Helper.so
src/lctags/core.so
src/lctags/coreBase.so
実行ファイルに PATH を通す†
- make で生成された実行ファイルと共有ライブラリを、1箇所に集めて環境変数 PATH と LD_LIBRARY_PATH に追加する。
- 或いは、パッケージ管理システムで構築されている環境では、これらをパッケージ化してインストールする。
emacs から使う†
- lctags を emacs から使う為の lisp は、lctags のリポジトリ内に同梱されているので、これを load 出来るようにする。
- リポジトリ内の src/lisp を、emacs が load 出来る場所にコピーするか、 load-path に追加する。
(add-to-list 'load-path "hoge/lctags/src/lisp") t)
- src/lisp/lctags.el を load する。
(require 'lctags)
- これらを使えるようにするために、 helm と gtags.el も使えるようにする必要がある。
参考リンク†
Rtags†
環境構築†
# apt-get install clang libclang-dev cmake
$ 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
参考リンク†
cscope†
- debian では、 cscope は cscope パッケージに入っている
- ソースコードは Linux ディストリビューションなどが配布しているもの、若しくは開発元の git repository から取得出来る
tag の生成†
- コンソールから
$ cscope-indexer -r
- cscope-indexer のオプション
option | description |
-f <database-file> | 出力先データベースのファイル名を指定する(default: cscope.out) |
-i <list-file> | リストファイル(ファイルのインデックスを記録したファイル)の名前を指定する(default: cscope.files) |
-l | データベースファイルの生成・更新を抑制する。 但し、リストファイルが生成済みであること |
-r | 再帰的にディレクトリを走査する。 このオプションがない場合、走査対象はカレントディレクトリに限定される。 |
-v | 冗長モード |
cscope で SymLink になっているファイルが扱えない問題について†
- ソースコード・ヘッダが SymLink になっている場合、cscope では正しく DB 化出来ない。これは、cscope が DB 作成処理の際、 SymLink を対象外とするように動作する実装になっているためである。
- SymLink も DB 化の対象にしたい場合は、ソースパッケージを取ってきて、以下のように修正する。
- cscope-indexer で SymLink をリスト対象とするように変更する
diff --git a/cscope-15.8a/contrib/xcscope/cscope-indexer b/cscope-15.8a/contrib/xcscope/cscope-indexer
index 13c0ae2..31e3956 100644
--- a/cscope-15.8a/contrib/xcscope/cscope-indexer
+++ b/cscope-15.8a/contrib/xcscope/cscope-indexer
@@ -134,7 +134,7 @@ fi
echo "$DIR/$f"
done
else
- find $DIR \( -type f -o -type l \)
+ find -L $DIR \( -xtype f -o -xtype l \)
fi
) | \
egrep -i '\.([chly](xx|pp)*|cc|hh)$' | \
また、cscope-indexer は内部で環境変数 PATH を独自に設定している(起動したshell の環境変数変数PATHは引き継がれない)ため、下記で修正する cscope の配置先が cscope-indexer から見える場所にあるかどうかを確認しておくこと。
- cscope の中で使われている lstat() を stat() に置き換える
- ソース上の lstat() を全て置き換えてもいいが、configure を走らせる前に config.h.in を1行修正する方がスマート。 HAVE_LSTAT が定義されないようにすれば良い(下記)。
diff --git a/cscope-15.8a/config.h.in b/cscope-15.8a/config.h.in
index 2219be7..b0fff54 100644
--- a/cscope-15.8a/config.h.in
+++ b/cscope-15.8a/config.h.in
@@ -53,7 +53,7 @@
#undef HAVE_LONG_LONG_INT
/* Define to 1 if you have the `lstat' function. */
-#undef HAVE_LSTAT
+// #undef HAVE_LSTAT
/* Define to 1 if you have the `memcpy' function. */
#undef HAVE_MEMCPY
但し、global.h も手直しが必要。
diff --git a/cscope-15.8a/src/global.h b/cscope-15.8a/src/global.h
index cda29aa..1919277 100644
--- a/cscope-15.8a/src/global.h
+++ b/cscope-15.8a/src/global.h
@@ -189,6 +189,7 @@ int rpl_asprintf(char **, const char *, ...);
/* This can happen on only vaguely Unix-ish platforms... */
#ifndef HAVE_LSTAT
+#include <sys/stat.h>
# define lstat(file,buf) stat(file,buf)
#endif
- 修正後、ビルドする
$ configure
$ make
- 実行ファイルをパスの通った所へ配置する。
- パッケージをインストールしている場合は、念の為削除しておいた方が良いだろう。
xcscope.el†
- emacs 上の xcscope.el から tag ファイルを生成する
C-c s L
シンボルを探す†
key | description | remark |
C-c s s | シンボルを指定して探す(定義・呼び出し箇所等の一覧をリストアップする) | |
C-c s C | 指定したシンボルの呼び出し箇所をリストアップ | |
C-c s G | 指定したシンボルの定義(宣言ではなく)、またはそれに関する定義をリストアップする | |
C-c s n | 次のシンボルへ Jump | |
C-c s p | 前のシンボルへ Jump | |
xcscope のキーバインド一覧(xcscope.el ver.1.0)†
;; * Keybindings:
;;
;; All keybindings use the "C-c s" prefix, but are usable only while
;; editing a source file, or in the cscope results buffer:
;;
;; C-c s s Find symbol.
;; C-c s = Find assignments to this symbol
;; C-c s d Find global definition.
;; C-c s g Find global definition (alternate binding).
;; C-c s G Find global definition without prompting.
;; C-c s c Find functions calling a function.
;; C-c s C Find called functions (list functions called
;; from a function).
;; C-c s t Find text string.
;; C-c s e Find egrep pattern.
;; C-c s f Find a file.
;; C-c s i Find files #including a file.
;;
;; These pertain to navigation through the search results:
;;
;; C-c s b Display *cscope* buffer.
;; C-c s B Auto display *cscope* buffer toggle.
;; C-c s n Next symbol.
;; C-c s N Next file.
;; C-c s p Previous symbol.
;; C-c s P Previous file.
;; C-c s u Pop mark.
;;
;; These pertain to setting and unsetting the variable,
;; `cscope-initial-directory', (location searched for the cscope database
;; directory):
;;
;; C-c s a Set initial directory.
;; C-c s A Unset initial directory.
;;
;; These pertain to cscope database maintenance:
;;
;; C-c s L Create list of files to index.
;; C-c s I Create list and index.
;; C-c s E Edit list of files to index.
;; C-c s W Locate this buffer's cscope directory
;; ("W" --> "where").
;; C-c s S Locate this buffer's cscope directory.
;; (alternate binding: "S" --> "show").
;; C-c s T Locate this buffer's cscope directory.
;; (alternate binding: "T" --> "tell").
;; C-c s D Dired this buffer's directory.
;;
xcscope のキーバインドが正しく動作しない場合†
参考リンク†
acscope.el†
- ascope.el は cscope の emacs 用 I/F の一つ。
- xcscope.el と比べて
- 機能は少ない
- xcscope.el と違って毎回検索を行わない分、
- 結果表示までの時間は早い
- 対象のソースコードに変更があった場合、検索結果に正しく反映されない場合がある
- debian では、 cscope は cscope パッケージに入っている
- この他、 emacs で使用するのに acscope.el を使う。debian8 にはパッケージはない。
- debian8 のようにディストリビューションからパッケージが提供されていない場合は、GitHub または EmacsWiki などから Download して組み込む。
但し EmacsWiki に掲載されているものは、 GitHub の最新版より大分古いようなので注意が必要。
- キーバインドを設定する
- ascope.el ではキーバインドが設定されてない一方、関数名が xcscope.el と同じなので、xcscope.el から流用して設定する。
#ただ、xcscope.el にあって ascope.el にないものが多い。
(setq load-path (cons (expand-file-name "~/.emacs.d/site-lisp/ascope") load-path))
(load-library "~/.emacs.d/site-lisp/ascope/ascope.el")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Original is from xcscope.el
(defvar cscope-minor-mode-keymap
(let ((map (make-sparse-keymap)))
;; xemacs has various issues with (cscope-mouse-popup-menu-or-search), so I
;; don't use that function for xemacs. Its popup menu support won't be as
;; good (cscope will still prompt for the search term)
;(if cscope-running-in-xemacs
; (progn
; (define-key map [(shift button3)] 'cscope-mouse-search-again))
; (define-key map [mouse-3] 'cscope-mouse-popup-menu-or-search)
; (define-key map [S-mouse-3] 'cscope-mouse-search-again))
;; The following line corresponds to be beginning of the "Cscope" menu.
(define-key map "\C-css" 'cscope-find-this-symbol)
(define-key map "\C-csd" 'cscope-find-global-definition)
(define-key map "\C-csg" 'cscope-find-global-definition)
; (define-key map "\C-csG" 'cscope-find-global-definition-no-prompting)
; (define-key map "\C-cs=" 'cscope-find-assignments-to-this-symbol)
(define-key map "\C-csc" 'cscope-find-functions-calling-this-function)
(define-key map "\C-csC" 'cscope-find-called-functions)
(define-key map "\C-cst" 'cscope-find-this-text-string)
; (define-key map "\C-cse" 'cscope-find-egrep-pattern)
(define-key map "\C-csf" 'cscope-find-this-file)
(define-key map "\C-csi" 'cscope-find-files-including-file)
;; --- (The '---' indicates that this line corresponds to a menu separator.)
; (define-key map "\C-csb" 'cscope-display-buffer)
; (define-key map "\C-csB" 'cscope-display-buffer-toggle)
; (define-key map "\C-csn" 'cscope-history-forward-line-current-result)
; (define-key map "\C-csN" 'cscope-history-forward-file-current-result)
; (define-key map "\C-csp" 'cscope-history-backward-line-current-result)
; (define-key map "\C-csP" 'cscope-history-backward-file-current-result)
; (define-key map "\C-csu" 'cscope-pop-mark)
;; ---
; (define-key map "\C-csa" 'cscope-set-initial-directory)
; (define-key map "\C-csA" 'cscope-unset-initial-directory)
;; ---
; (define-key map "\C-csL" 'cscope-create-list-of-files-to-index)
; (define-key map "\C-csI" 'cscope-index-files)
; (define-key map "\C-csE" 'cscope-edit-list-of-files-to-index)
; (define-key map "\C-csW" 'cscope-tell-user-about-directory)
; (define-key map "\C-csS" 'cscope-tell-user-about-directory)
; (define-key map "\C-csT" 'cscope-tell-user-about-directory)
; (define-key map "\C-csD" 'cscope-dired-directory)
;; The previous line corresponds to be end of the "Cscope" menu.
;; (START Add) --------------------------------------
;; ここは xcscope.el にないものを追加
(define-key map "\C-csa" 'cscope-setup)
;; (END Add) --------------------------------------
map)
"The global cscope keymap")
(require 'ascope)
tagの生成†
参考リンク†
参考リンク†
id-utils†
- debian の場合は、以下のパッケージをインストールする
id-utils elscreen
- emacs
emacs の設定†
DB の生成†
symbol の検索†
gtags / global の利用†
- タグシステムの一つ
- debian では、 global パッケージに入っている
tag の生成†
$ gtags [options] [path]
$ gtags -f <files>
$ gtags -v
- gtags には、etags と違って append mode が存在しないため、xargs でマルチスレッド化して実行するのは不可かもしれない。
- -f <file> を指定しない場合、gtags はカレント以下のディレクトリを走査してタグ情報を生成する。
- tag の生成処理が終わると、実行したディレクトリ配下に、下記4つのファイルが作られる:
GPATH GTAGS GRTAGS GSYMS
emacs の設定†
vi での設定†
- vimのプラグインを ~/.vim/plugin にコピー
$ mkdir ${HOME}/.vim/plugin
$ cp /usr/share/doc/global/examples/gtags.vim.gz ${HOME}/.vim/plugin
$ cd ${HOME}/.vim/plugin
$ gunzip gtags.vim.gz
/.vimrc にgtagsの設定を追加
map <C-h> :Gtags -f %<CR>
map <C-j> :GtagsCursor<CR>
map <C-n> :cn<CR>
map <C-p> :cp<CR>
binding | description |
C-h | そのソースの関数を表示 |
C-n | リストのカーソルを下に移動 |
C-p | リストのカーソルを上に移動 |
C-j | 現在の関数の中にジャンプ |
C-o | ジャンプする前の位置に戻る |
参考リンク†
etags (ctags for Emacs)の利用†
tag の生成†
- まずは、 Tag file を生成する。emacs パッケージには etags.emacs** なコマンドが付属している場合があるので、それがあればそちらを使う。
- Tag file は TAGS というファイル名で生成される。
$ etags.emacs23 `find | grep -i "\.c$\|\.cc\|\.cpp$\|\.cxx$\|\.h$"
- ただ、ファイル数が多い場合にはコマンドラインバッファの上限を超えてしまい、全てのファイルを処理できないことが予想される。この問題は xargs を使って解消することが出来る。
以下に、そのためのスクリプトを示す。
下記の例では、 xargs の -P オプションも併用し、マルチスレッドで動作するようにしている。 THREAD_NUM は CPUの数もしくは Core 数に合わせる。
#!/bin/bash
TAGS_FILE=TAGS
CMD_ETAGS=etags.emacs23
THREAD_NUM=4
rm -f ${TAGS_FILE};
find | grep -i "\.c$\|\.cc\|\.cpp$\|\.cxx$\|\.h$" | xargs -P ${THREAD_NUM} -I {} ${CMD_ETAGS} -a {} # 対象となるソース・ヘッダを etags に引数で渡す
- 全てのファイルを渡すのにコマンドバッファが足りなくなってしまう場合(=ファイル数が多い場合や個々のパス名が長い場合など)でも全てのファイルを渡せるよう、xargs を使って etags にファイル名を渡すようにしている。
- コマンドバファが足りなくなった場合、 xargs は複数回 etags を呼ぶ。この場合、 etags が append モードで動作しないと etags は呼ばれる度に TAGS ファイルを上書きしてしまうので注意すること(そのため上記では append モードにするため "-a" を付けて etags を呼んでいる)。
emacs に TAGS ファイルを読みこませる†
M-x: tags-reset-tags-tables 一旦リセットする
M-x: visit-tags-table 明示的に TAGS ファイルを読み込む
- emcs から操作する(下記)
Key binding | command | description |
M-. | find-tag | クラスや関数を探す |
C-u M-. | | 次の検索結果候補を表示する |
C-u – M-. | | 前の検索結果候補を表示する |
M-* | | 元の場所に戻る |
C-x 4 . | find-tag-other-window | タグ(名前)の定義箇所を探し別ウィンドウに表示 |
C-x 5 . | find-tag-other-frame | タグ(名前)の定義箇所を探し別フレームに表示 |
ctags-exuberant†
- 正しくは、Exuberant ctags という。このページ名は、Debian のパッケージ名に合わせている。
- ctags の派生プログラムである。
- install 後、実行ファイルは /usr/bin/ctags-exuberant に配置される。システムによっては /usr/bin/ctags に symlink されることもある。
debian 8 にはパッケージが存在しない。 → exuberant-ctags というパッケージになっている。
TAGS file の生成†
$ ctags-exuberant -e -R [path]
- これにより、 'TAGS' という名前のファイルが生成される。
- emacs からの使い方は、etags と基本的に同じ
emacs から TAGS の生成を行えるようにする†
参考リンク†
ebrowse (ebrowse for Emacs)の利用†
Links†
SilentBob†
tag の生成†
$ bob --make-ctags
$ bob --cfiles
$ bob -L cfiles --call-tags
参考リンク†
各システムでの解析速度†
- 各タグシステムで同一コードツリーを走査して、 DB を作り終わるまでの時間を計測した。
- 結果(2)
- 計測条件
- 対象:linux-4.0.1
- CPU:Core i7-7700HQ @ 2.8GHz (8Core)
- Disk I/O:なし(tmpfs 上で計測)
- 結果(1)
TagSystem | command | elapsed time [sec] | remark |
cscope | cscope-indexer -r | 20.19 | |
id-utils | mkid | 19.23 | |
gtags-global | gtags | 25.24 | |
etags | find | grep -i "\.h$\|\.c$|\.cc$|\.cxx$|\.cpp" | xargs -P ${THREAD_NUM} -I {} etags -a {} | 35.69 | THREAD_NUM=4 |
ctags-exuberant | ctags-exuberant -e -R <path> | 16.36 | |
Silent Bob | bob --make-ctags bob --cfiles bob -L cfiles --call-tags | 22.79 | |
- 計測条件
- 対象:linux-3.16.36
- CPU:Core i7-3520M @ 2.90GHz (4Core)
- Disk I/O:あり(HDD 上で計測)