C 言語のコンパイル

久し振りの更新となってしまいました。

id:higepon さんのところで、


開発時にM-x compileを常用しているのですが以下2点が不満でした。

という話が。
;; どうも higepon さんのエントリに反応してしまうことが多い気がします……

session.el の方はコメントが既にあり、不満も解消されている様なので、compile command について少しだけ。
こちらも higepon さんご自身により既に対処されていて、不満は解消されているものとは思いますが、どうせならば、単に compile-command 等を変更するだけでなく、もう少し工夫しておくと更に便利かも、ということで。

先ず一点目は、command の切り替え。
私は、結構、確認のためだけのコードを書くことが多いので、Makefile など用意せずに compile することが多いです。そのため、make コマンドだけでは物足りません。
また、Cygwin, Linux, Solaris といった環境によって compile command の内容に相違があるため、それらも使い分けられると良いということで、こんな具合にコマンドを生成しています。

(defun set-compile-command-for-c ()
  (interactive)
  (let* ((filename (file-name-nondirectory buffer-file-name))
         (index (string-match "\\.c$" filename))
         (filename-no-suffix (substring filename 0 index)))
    (setq compile-command-local
          (cond
           ;; Cygwin or Linux
           ((string-match "cygwin\\|linux" system-configuration)
            "gcc -g -ansi -pedantic -Wall -I../inc ")
           ;; Solaris
           ((string-match "solaris" system-configuration)
            "cc -Xa -xtransition -g -xs -I../inc ")))

    (setq compile-command
          (cond
           ;; Cygwin 用の Makefile があればそれを指定。
           ((or (file-exists-p "Makefile.cygwin"))
            "make -k -f Makefile.cygwin")
           ;; Makefile があれば "make -k"
           ((or (file-exists-p "Makefile")
                (file-exists-p "makefile"))
            "make -k")
           ;; それ以外
           (t
            (concat compile-command-local "-o "
                    filename-no-suffix " " filename))))))

プラットフォームごとに compile-command-local を設定した上で、そのバッファに表示されているソースに適合する compile-command を組み立てています。
Makefile があれば make コマンドを、無ければ直接 gcc で、というだけですけど。
;; コマンドのオプションはお好みで。

そして、もう一点、ここで生成された gcc のコマンドはファイル名まで指定しているので、当然の如くそのバッファでしか有効ではありません。
なので、compile-command(-local) 変数は、バッファローカルでなければなりません。

(add-hook 'c-mode-common-hook
 '(lambda ()
    ;; コンパイルコマンドの設定
    (make-local-variable 'compile-command)
    (make-local-variable 'compile-command-local)
    (set-compile-command-for-c)))

これでソースを開いているバッファごとに、その状況に応じたコンパイルが行なえる様になりますので、結構便利です。
;; 実は compile-command-local の方は local variable にしなくても良さそうですが。

ここでは判断した結果としてコマンドを一つだけ決定している訳ですが、higepon さんの様に、compile-history に複数設定しておく、というのは良いアイディアですね。
私も使わせて頂こうかと思います。