2021-08-04

WindowsでflycheckがNULというファイルを作ってしまう問題

以前flycheckを試したときにNULというファイルが出来て消すのが大変だったのでflymakeでいいやーと思ったことがあったのですが、最近また調べたところ対処法を書いているサイトを見つけました。

Emacs Flycheck

下記の記述だと、Windowsで、gcc によっては、同じディレクトリに "NUL" というファイルが生成されることがある。

:command ("gcc" "-c" "-I../../inc" "-I." "-O1" "-Wall" source "-o" null-device)

その場合、下記のように temporary-file-name を指定すると回避できる

:command ("gcc" "-c" "-I../../inc" "-I." "-O1" "-Wall" source "-o" temporary-file-name)

checker定義内の 'null-device は同名の変数null-deviceの値で置き換えられて、Windowsだと "NUL" になります。これをCygwinやMSYS2/MinGWのgccが受け取るとコンパイルが成功したときにそのままNULというファイルを出力してしまうのが原因のようです。

同じようにcheckerを再定義すれば良いのかなと思ったのですが、flycheck.elを見てみると沢山のcheckerが定義されていてその中でnull-deviceも沢山使われていました。

そもそもcheckerを再定義するのも面倒ですし、かといってnull-deviceの値を書き替えるのも(他にどこで使われているのか分からないので)怖いですし、手っ取り早くadviceでnull-deviceをtemporary-file-nameに置き換えてしまうことにしました。

;;; Windowsでnull-deviceを使わないようにする。
;; null-deviceはNULなので、CygwinやMinGWだとNULというファイルを作ってしまう。
;; flycheck-command-wrapper-function でNULを置き換えても良いのだが
;; flycheck-substitute-argument でやった方が確実だし簡単。
(when (locate-library "flycheck")
  (with-eval-after-load 'flycheck
    (defun my-flycheck-substitute-argument (old-func arg checker &optional rest)
      (when (eq arg 'null-device)
        (setq arg 'temporary-file-name))

      (apply old-func arg checker rest))
    (advice-add 'flycheck-substitute-argument :around 'my-flycheck-substitute-argument)))

最近はLSPの方でエラー箇所を検出してしまうので必要ないのかもしれませんけどまたNULファイルが出来ると面倒なので念のため。