とある事情で使い続けていた emacs23.4 (2012/1) を、 先日 emacs26.2 (2019/4) にアップデートした。

このとき gdb 周りの設定を変更する必要があったので、備忘録としてまとめておく。

2019-06-12: my-gud-stop, my-gud-mode-func を追加

2019-08-26: dedicate の抑制追加

なお、M-x gud-gdb で起動すれば従来形式のインタフェースが利用できるが、 ブレークポイントが表示されない等の不具合があるので M-x gdb を利用する。

それにしても、新しい M-x gdb のインタフェースは emacs っぽくないと思うんだけど、 オレがおっさんだからそう思うんだろうか?

emacs の gdb 設定

;; gud-overlay-arrow-position が nil だとエラーするので。。
(setq gud-tooltip-display
      '((and gud-overlay-arrow-position
	     (eq (tooltip-event-buffer gud-tooltip-event)
		 (marker-buffer gud-overlay-arrow-position)))))

;; gdb バッファの C-c C-c で、プログラムを停止させる。
(setq gdb-gud-control-all-threads nil)

;; input/output バッファが勝手に表示されるのはウザいので、抑制
(setq gdb-display-io-nopopup t)

;; input/output バッファが dedicate されるのはウザいので、抑制
(defadvice gdb-display-buffer (around gdb-display-buffer)
  (let (window)
    (setq window ad-do-it)
    (set-window-dedicated-p window nil)
    window
  ))
(ad-activate 'gdb-display-buffer)


;; gdb バッファの C-c C-c ではプログラムが停止しなかったので、修正
(defun my-gud-stop ()
  (interactive)
  (comint-interrupt-subjob)
  (gud-stop-subjob)
  )

;; 上記 my-gud-stop 関数を C-cC-c に登録する関数
(defun my-gud-mode-func ()
  (define-key (current-local-map) "\C-c\C-c" 'my-gud-stop)
  )
;; フックに登録
(add-hook 'gud-mode-hook 'my-gud-mode-func)

以降で、上記の設定について説明する。

gud-tooltip-display

1 つ目は、単純に gud.el の不具合のような気がするが、 tooltip を表示する処理を修正している。

gud-tooltip-display は、 gud で tooltip を表示する処理のようだが、 この処理で (make-buffer gud-overlay-arrow-position) を実行している。

この処理は、 gud-overlay-arrow-position が nil の時にも実行されるケースがあるようで、 その時にエラーにならないように and を追加している。

gdb-gud-control-all-threads

gdb-gud-control-all-threads は、 gud の制御を全スレッドに対して反映させるかどうかのフラグで、 emacs 23 ではデフォルト nil だった。

新しい gdb では、 gdb-gud-control-all-threads がデフォルト t になっている。

gdb-gud-control-all-threads が t だと、 どうにもこうにも意図したデバッグ制御にならなかったので nil とした。

なお、 C-c C-c でデバッグ対象プログラムを停止できるが、正常に動作しない場合がある。

その場合 M-x gud-stop-subjob してから C-c C-c すると、停止する。

gdb-display-io-nopopup

emacs23.4 の gdb は、 デバッグ対象プログラムの stdin/out と gdb の制御コマンドを、 一つのバッファで管理していた。

しかし、 新しい gdb は stdin/out と、gdb の制御コマンドを別々のバッファで管理している。

gdb-display-io-nopopup は、 stdin/out に変化があった際のポップアップ制御を抑制するかどうかのフラグ。

デフォルトだと t だが、 これだとソース編集中やステップ実行中に、 stdin/out のバッファが突然表示されてウザいので nil とした。

なお、gdb-display-io-nopopup を t とすると、 M-x gdb 実行時にも stdin/out のバッファが表示されないため、 stdin/out にアクセスする場合は 自分で C-x b 等で切り替える必要がある。

ちなみに stdin/out バッファの名前は *input/output of ...* 。 ここで … には、デバッグ対象のファイル名が入る。

my-gud-stop

emacs23.4 だと C-cC-c でプログラムを停止して (gdb) プロンプトが表示されたのだが、 emacs26.2 だと C-cC-c でプログラムを停止できない。

そこで、プログラムを停止する関数を作成している。

my-gud-mode-func

上記関数を C-cC-c に登録するための関数。

gud-mode 時にキーバインドを登録するように gud-mode-hook に追加。

dedicate

普通に使うと、 gud の input/output バッファの window が dedicate される。

dedicate されると、 C-x b などでバッファを切り替えられなくなる。

個人的にこれは使い勝手が悪いので、 dedicate されないように gdb-display-buffer の処理をかえる。

以上。