Developer's Blog

【Emacs で Objective-C】flymake で文法チェック

こんにちは。Objective-C は Emacs で書く宮本です。

Emacs で Objective-C のコードを書くなら以下のサイトがまとまっていてオススメです。
Emacs で iPhone アプリ開発を快適にするための設定

この中に flymake を使った文法チェックが紹介されているのですが、私が Objective-C を書き始めた頃のマシンでは快適でなかったので使ってませんでした。
しかし、もう昔に比べてマシンも良くなったので、もしかしたら快適に使えるのではないかと思って導入してみることにしました。

Xcode のデフォルトコンパイラが LLVM なので、gcc ではなく clang を使います。 なるべく Xcode が出力するエラーや警告と同じになるように xcodebuild のオプションを参考にしています。 プロジェクトの設定によって違う可能性があるので、必要があれば変更してください。

今は、Sleipnir Mobile for iPhone / iPad と Sleipnir for Mac 両方の開発をしていて、それぞれビルド設定が違うので、Emacs Lisp に設定を書いていると切り替えが面倒です。
flymake では Makefile を使った文法チェックもできるようなので、それぞれ Makefile を書くことにしました。 flymake のターゲットのソースファイルがカレントディレクトリになるので、同じディレクトリに置くのがいいでしょう。

SDK, OS_VER_MIN, INCLUDES, FRAMEWORKS あたりをプロジェクトに合わせて設定すれば動くと思います。 ライブラリなどが他のディレクトリにある場合は、INCLUDES や FRAMEWORKS に追加してください。

■ Makefile (Mac)
CLANG	    = /usr/bin/clang
ARCH	    = -arch i386
SDK	    = -isysroot /Developer/SDKs/MacOSX10.7.sdk
OS_VER_MIN  = -mmacosx-version-min=10.6
OPTIONS     = -fsyntax-only -x objective-c -std=gnu99
WARNINGS    = -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value
INCLUDES    = -I.
FRAMEWORKS  = -F../

check-syntax:
	$(CLANG) $(OPTIONS) $(ARCH) $(WARNINGS) $(SDK) $(OS_VER_MIN) $(INCLUDES) $(FRAMEWORKS) ${CHK_SOURCES}
■ Makefile (iOS)
CLANG	    = /usr/bin/clang
ARCH	    = -arch armv7
SDK	    = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk
OS_VER_MIN  = -miphoneos-version-min=4.3
OPTIONS     = -fsyntax-only -x objective-c -std=gnu99
WARNINGS    = -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value
INCLUDES    = -I.
FRAMEWORKS  = -F../

check-syntax:
	$(CLANG) $(OPTIONS) $(ARCH) $(WARNINGS) $(SDK) $(OS_VER_MIN) $(INCLUDES) $(FRAMEWORKS) ${CHK_SOURCES}
■ Emacs Lisp (flymake 用の設定)
(require 'flymake)

(defun flymake-display-err-minibuffer ()
  (interactive)
  (let* ((line-no (flymake-current-line-no))
         (line-err-info-list 
           (nth 0 (flymake-find-err-info flymake-err-info line-no)))
         (count (length line-err-info-list)))
    (while (> count 0)
      (when line-err-info-list
        (let* ((file (flymake-ler-file (nth (1- count) line-err-info-list)))
               (full-file (flymake-ler-full-file 
                            (nth (1- count) line-err-info-list)))
               (text (flymake-ler-text (nth (1- count) line-err-info-list)))
               (line (flymake-ler-line (nth (1- count) line-err-info-list))))
          (message "[%s] %s" line text)))
      (setq count (1- count)))))

(defun flymake-display-err-minibuffer-safe () 
  (ignore-errors flymake-display-err-minibuffer))

;; エラーが起きた時にflymakeを止める
(defadvice flymake-post-syntax-check (before flymake-force-check-was-interrupted)
  (setq flymake-check-was-interrupted t))
(ad-activate 'flymake-post-syntax-check)

;; もともとのパターンにマッチしなかったので追加
(setq flymake-err-line-patterns
 (cons
  '("\\(.+\\):\\([0-9]+\\):\\([0-9]+\\): \\(.+\\)" 1 2 3 4)
  flymake-err-line-patterns))

;; flymake の色
(set-face-background 'flymake-warnline "dark orange")
(set-face-foreground 'flymake-warnline "black")
(set-face-background 'flymake-errline "orange red")
(set-face-foreground 'flymake-errline "black")

(add-hook 'objc-mode-hook
         (lambda ()
           (push '("\\.m$" flymake-simple-make-init) flymake-allowed-file-name-masks)
           (push '("\\.h$" flymake-simple-make-init) flymake-allowed-file-name-masks)
           (define-key objc-mode-map "\C-cd" 'flymake-display-err-minibuf)))
           (flymake-mode t)
         ))

まあまあ軽快に動くのですが、Xcode4 の自動ビルドのほうがたぶん快適です。
でも、もう他のエディタは使えません!どんどん Emacs に便利な機能を追加して、負けないようにしたいですね。

Copyright © 2019 Fenrir Inc. All rights reserved.