gcc などの出力に色をつけるプログラム

コマンドラインgcc などのコンパイラを実行したり複数のファイルを make によってビルドするときなどに、ついついコンパイラからの出力メッセージを目視してしまう私のような情弱は、ある程度規模が大きなプログラムになると警告やエラーメッセージが他の正常な出力に埋もれて見つけにくくなってしまいます。
EmacsVim から直接コマンドを起動して出力をエディタの中でゴニョゴニョしているというスーパーハカーなあなたはこの記事を読まなくてもよいかもしれません)


膨大な出力メッセージがあってもエラーが発生した場合は最終的にビルドが止まりますので気づくことができますが、警告は見逃してしまいがちです。

そこで colorgcc 他、いろいろとコンパイラの出力に色をつける系のプログラムが世の中にはあります。

しかし以下のような理由で、既存のプログラムではなかなか私のような用途には対応しづらそうな感じがしました。

  1. 複数のバージョンのコンパイラやクロスコンパイラを使っていると、colorgcc 他各種ツールのような「コンパイラ置換えアプローチ」は使いづらい
  2. 人から送られてきたビルドログや CI サーバに残っているビルドログをあとから簡単に色付けして見たいけど、それをやってくれるプログラムはなさそう

これらのことを簡単に実現するには、コンパイラの出力をパイプで受け取り色づけして出力するようなフィルタプログラムがあれば良いのではないかと思って探して見ましたがなかなか見つかりません。

仕方が無いので作ってみたのですが、どうしてそういうフィルタプログラムが存在しないのか、作ってみてわかった気がします。

  1. コンパイラ等はたいていエラーメッセージを stderr に出力します。しかしフィルタプログラムが stderr をパイプ経由で渡してもらうにはひと手間必要です(2>&1 のような余計なものをユーザに書いてもらう必要が生じ、普段使いには敷居が高いです)
  2. フィルタプログラム側からは、コンパイラの終了コードを簡単には取得できません。しかしながらコンパイラの終了コードを透過的にフィルタプログラムの終了コードとしてあげないと、コンパイルの成功・失敗に応じて処理を分ける場合にそのフィルタプログラムが使えなくなります。
  3. コンパイラを置き換えると既存のビルドスクリプト等に全く手を加えなくても色付けできますが、フィルタアプローチの場合はビルドスクリプトを書き換えないと色付けすることができない場合があるかもしれません。ただ、何らかの事情によりビルドスクリプトを変更できない場合でも、そのビルドスクリプト自体からの出力を受け取って色付けすれば良さそうなのでそれほど問題ないかもしれません。(個人的には、ビルド環境のコンパイラを置き換えるよりはビルドスクリプトを書き換えるほうがマシな気はしますが)

おそらくこのあたりの理由で、既存のプログラムはコンパイラそのものを置き換える仕組みになっているのではないかと思います。(全然違うかもしれませんが)

今回、シェルスクリプトと組み合わせることによってそれらの問題をある程度解決することができた気がするので GitHub に上げてみました。
https://github.com/bearmini/crror

crror という名前は color + error から来ています。(カラー、もしくはクラーとでも発音しましょうかね)

使い方は至って簡単で、既存のコンパイルのコマンドの先頭に crror とつけていただくだけです。
たとえば、

$ crror make clean all

という感じです。これで、make clean all の出力に色がつきます。
終了コードも make コマンドの終了コードを透過的に使用します。

また、build.log というファイルがあって、その内容を色付けして見たい場合は

$ crror build.log | less -R

という感じでイケます。

現時点ではいろいろ制約があります。たとえば起動スクリプトbash のみサポートですし、stderr を拾うために結局フィルタではなくコマンドっぽく使わないといけない感じになってしまいました。すなわち、make | crror という感じで使いたかったのですが、crror make というふうに使わないといけなくなりました。
(内部的にはフィルタで実装してしまったので、stderr と stdout が統合されてしまっているのが欠点といえば欠点かもしれません)

clang (LLVM) はデフォルトで色付きの出力をサポートしているようですし、gcc も 4.9 からは色つき出力をサポートするようですので、このプログラムもそれが一般的になるまでのつなぎ程度でしかないですが、また、私の気づいていない他の欠点もあるとは思いますが、よろしければ使ってみてください。