実は簡単だったんですね。
いや、全然知りませんでした。
いまどきの Emacs では常識ですか? これって。
古いシステムのトラブルで、久し振りに C 言語のシステムをデバッグしなければならず、とは言えホストマシンは新しくなっていて環境が余り整っていない…… という状況で作業しようとしてみたら。
Emacs 23 以降でないとダメなのかもしれませんが、TRAMP さえあれば、なんと素のままの Emacs でそのままリモートホストの GDB でデバッグできるんですね。
GDB が持つリモートデバッグ機能は、「通常の方法で GDB を実行させることのできないマシン上で実行中のプログラムをデバッグするためのもの」ですので、ここで言うリモートデバッグは、それとはちょっと意味合いが異なります。
ここでのリモートデバッグは、単純に自分のローカル環境から、リモートホスト上で実行する GDB に接続してのデバッグをそう呼んでいます。
リモートホストに Emacs と GDB があれば、別段、何も苦労することはありません。
しかし、昨今はどんな環境にも Emacs がインストールされているという時代ではない様です。いや、そもそも Emacs なんかどこにでもあるとは限らないって言われちゃいますかね、vi と違って。無ければ自分で入れれば良いって訳でもないですしね、仕事の環境ではそうそう勝手なことはできないですから。
しかも、最近の仕事は移り変わりが激しく、やれあっちのホストマシン、こっちのホストマシンと、あちらこちらでの作業が必要だったりします。
しかし、TRAMP があれば大抵のことはローカル環境から透過的に利用できますよね。
なにせ、`Transparent Remote (file) Access, Multiple Protocol' ですから。
それが本当に透過的だな、と思わされるのは、リモートホストにあるファイルを開いたバッファ上で何か行うと、それがリモートホスト上で動作して、結果を正しく伝えてくれるときですね。まあ、何でもかんでもそうではなくて、単純な一括編集や文字列を拾って Google で検索、なんてときにはローカルで処理された方が効率が良いし、インタフェースとしても正しい挙動でしょう。
しかし、flymake で syntax check したり、compile したり、バージョンコントロールシステムにアクセスしたり、デバッグしたり、ってのは、リモートホストで動作してくれないと意味がありません。それこそクロス開発環境が構築されてない限りは。
VC との透過的な統合は、TRAMP の売りの一つでもあるので、TRAMP のマニュアルでも紹介されていますが、GDB を使ったデバッグも、ちゃんとリモートホスト上で動作してくれるのですね、しかも、特別な設定は必要ありません。
設定が必要ないのは、M-x gud-gdb や、`gdb-many-windows' が有効でない M-x gdb の場合です。それであれば素のままで何の設定もなく、そのままリモート環境の GDB を利用したデバッグが実行できました。gud は TRAMP を想定している様ですし、comint 経由でプロセスにアクセスする (comint は magic file name に対応している `start-file-process' でプロセスを扱かっている) ことから、そもそも問題なくリモートホストのファイルが扱える様です。
;; 今の私の環境には、Emacs 23 しかないものですから、Emacs 22 以前だと素ではどうだか判りませんが。
gud-gdb で十分と言えば十分なのですが、折角ですから `gdb-many-windows' を有効にした状態でも動作させてみたいところ。実のところ、動作自体はするのです。ただ、`gdb-many-windows' を有効にした gdb-ui でデバッグを行うと、
の何れかの操作や動作を行うときに、該当するソースファイルを開いてソースバッファに表示しようとし、その動作が失敗してしまいます。
GDB からの要求でソースを開こうとするため、リモートホスト上でのパス表現のまま、ローカル環境で開こうとしてしまうからです。
なので、ここでのパスを「ローカル環境から見た TRAMP のパス」に変更してやれば良い筈です。
ということで、ちょっと強引ですが、quick hack...
;; gdb-many-windows が有効でも TRAMP 経由で remote debug できるように。 ;; (defadvice find-file-noselect (before ad-find-file-noselect) "指定されたファイルがローカル環境に存在するか確認し、無ければリモートホストの ものと判断して path を変更する。" (set 'filename (if (file-exists-p filename) (expand-file-name filename) (gud-file-name filename)))) (defadvice gdb-get-location (around ad-gdb-get-location activate) "TRAMP を利用して remote debug するために、`find-file-noselect' のアドバイスを 活性化する。" (let () (ad-activate 'find-file-noselect) ad-do-it (ad-deactivate 'find-file-noselect))) (defadvice gdb-info-breakpoints-custom (around ad-gdb-info-breakpoints-custom activate) "TRAMP を利用して remote debug するために、`find-file-noselect' のアドバイスを 活性化する。" (let () (ad-activate 'find-file-noselect) ad-do-it (ad-deactivate 'find-file-noselect))) (defadvice gdb-goto-breakpoint (around ad-gdb-goto-breakpoint activate) "TRAMP を利用して remote debug するために、`find-file-noselect' のアドバイスを 活性化する。" (let () (ad-activate 'find-file-noselect) ad-do-it (ad-deactivate 'find-file-noselect)))
と、`find-file-noselect' に渡すパスを変更してやるアドバイスと、それを適切な期間だけ活性化するアドバイスを定義しています。
これでローカル環境の Emacs 上では、リモートホストのファイルのパスが常に TRAMP の形式となることになるので、問題なく処理される様になりました。ただ、リモートホストのファイルであることの判定を、単純に「ローカル環境無かったらリモートホストのファイルである」としてしまっているので、同じパスとなるファイルがローカル環境に存在するとそれが利用されてしまいます。もう少しちゃんと判定した方が良いのでしょうね。
稚拙なハックなので副作用などあるかもしれませんが、今のところはこれで利用できています。
ただ、`gud-tooltip-mode' は無効化しておいた方が良いですね。絶えずリモートの GDB と通信する様になってしまって、流石に遅く感じます。これを無効にしてさえいれば、速度的にも体感的には殆んどストレスなく利用できています。まあ、私はベースが Cygwin 上の Emacs 23 なので、そもそも反応が遅いものに慣れてしまっているのというはありそうです。サクサク動作する環境で使うと、体感速度にも違いがでるのかもしれません。