ちょっと仕事がらみのネタを紹介。
一応ソフト屋さんなんでソフト開発をするんやけど、プログラムを書くのはもちろんEmacsで色々な機能を使って書きます。これで結構手抜きができるんで助かるんやけど問題はデバッグの時やね。Windowsのアプリ開発時はVisutalStudio、Linuxではgdb、組み込みではgdbのリモートデバッグやったりEclipseやったり、専用の開発ツールやったりするわけです。毎回環境が変わるんも不便やし効率悪いし、エディタとデバッガの環境が違うのも使いにくいよなぁ。そういう意味でもEmacsでデバッグができればと思うわけです。
EmacsにはGUDというgdbのフロントエンドがあって、これを使うとgdbのコマンド操作をEmacs上から行う事ができるわけです。特にステップ実行やらスタック情報表示、ウォッチ式の編集とかできるんで結構便利。もちろんベースがgdbなので専用のソフト程は、簡単ではないのやけど、それでも環境が統一できるし最近じゃLinuxでもWindowsでもこの環境でデバッグしとるんですわ。
←デバッグ中の画面はこんな感じ[E:happy01]
左上: GUDバッファ、右上: ローカル式表示
中央: ソースコード
左下: コールトレース、右下: ブレークポイント情報
環境としてはその辺のIDE並の充実具合です。
特にステップ実行は秀逸で現在実行行のソースにマークが出るので分かりやすいですなぁ。
←ステップ実行中のマーカー
さてさてGUDの使い方です。
設定編
GUD自体は標準設定のまま使えるのやけど、上記のような色んな情報を表示するには.emacsに以下の設定を記述します。あと、c-mode-common-hookにGUDを起動するためのキーをローカルマップしておくと便利やね。以下に僕の環境の例をあげておきます。compileやcomment-regionなんかも定義してますだ。
(setq gdb-many-windows t)
(add-hook ‘c-mode-common-hook
‘(lambda ()
;; 色々な設定
(define-key c-mode-base-map "C-cC-c" ‘comment-region)
(define-key c-mode-base-map "C-cM-c" ‘uncomment-region)
(define-key c-mode-base-map "C-cg" ‘gdb)
(define-key c-mode-base-map "C-cc" ‘make)
(define-key c-mode-base-map "C-ce" ‘c-macro-expand)
(define-key c-mode-base-map "C-ct" ‘toggle-source)
))
僕の環境では C-cg にgdbを割り当ててます。一応自分のルールではローカルマップキーはC-cをプレフィックスにするようにしとるんですわ。
さて、GUDのmany-windows環境は残念ながらECBと共存できないので[E:crying]gdb-mode-hookでECBを無効化します。
(add-hook ‘gdb-mode-hook
(lambda ()
(if ecb-minor-mode
(ecb-deactivate)
)))
これでgdb-modeに入る時にECBが有効だったら無効化します。
gdbから通常のcc-modeに戻った時にECBを有効にするにはちょっと面倒なんでやってまへん。というか、このGUDを使うために必要な時だけECBを起動するようにしてたりして・・・[E:sweat02]
操作編
プログラムを編集しているバッファから
C-c g (gdb)
とするとミニバッファに
Run gdb (like this): gdb –annotate=3 (実行ファイル)
と表示されます。実行ファイルが表示されなかったら自分で入力しましょう。一旦入力した値は記憶してくれるので、次からは C-cg だけで表示されます。(下線がユーザ入力部分)
(gdb-many-windows)がnon-nilの場合、上記のIDEのようなウィンドウ構成に自動的に切り替わります。この時に元のウィンドウ構成を破棄してしまうので、GUDを抜けた時に元に戻したければ予めウィンドウ構成をレジスタに記憶させておくと良いでしょう。僕はいつもレジスタ d に記録してます。
C-x r w (window-configuration-to-register)
この後、レジスタ名(任意のアルファベット1文字)を入力すればそのレジスタに現状のウィンドウ構成が記録されます。後で戻したい時は
C-x r j (jump-to-register)
で先ほどウィンドウ構成を記録したレジスタ名を指定すればバッファ、カーソル位置等を戻してくれます。
さて、GUDの画面に入ったらあとはgdbの使い方と同じやねんけど、まぁ大体以下のような流れかなぁ…。
- 任意の位置にブレークポイントを設定
- runコマンドで実行
- ブレークポイントで停止したら、ステップ実行&ローカル変数値確認
- 必要に応じて広域変数をウォッチ式に追加
GUDバッファで使うキー
gdbのコマンドをそのまま打てるけど、emacsユーザならCtrlキーの組み合わせで使いたいっすね。いくつか基本的なものを。
C-c C-n (next step) 関数内に入らない
C-c C-s (step) 関数内に入る
C-c C-b 現在行にブレークポイントを設定
C-c C-d 現在行のブレークポイントを削除
こんな感じで C-c から始まるキーが定義されています。
あと任意の位置にブレークポイントを設定するにはソースバッファで
C-x C-a C-b
C-x C-[Space]
どちらでも良いです。ちなみにソースバッファでは C-x C-a をプレフィックスとする事でGUDバッファのコマンドと同じものが使えます。つまりソースコードで現在ポインタのある行のブレークポイントを削除するには
C-x C-a C-d
とすれば消せるわけです。
ブレークポイントの削除にはもうひとつ方法があって、右下のブレークポイントバッファで削除したいブレークポイントにポインタを合わせて D(大文字) でも消せます。
これくらいのキーでも、そこそこデバッグできるので便利でしょ〜[E:note]
特にローカル変数バッファは良くできてて、変数値の自動更新や配列の表示やら構造体のメンバ表示もしてくれるので良いですわ。
我が家ではコンパイラはgcc、エディタはEmacs、デバッガがgdbという事で、このGUDのお陰ですっかりプログラム開発環境が整いました。個人的にはEclipseよりも便利だと思う。まぁ、gdbの良し悪しはあるのやけど・・・