CoffeeScript用のMakefile雛形4つ(GNU Make専用)

いやまあ普通は「Cakefile使えよ」となるのだろうけど……それでもメジャーでポピュラーなビルドツールといえばmake(1)で、数あるmake(1)の実装の中で一番人気なのはGNU Makeだと思うわけです。

大概のLinuxディストリやMac OS Xのmakeの実体はGNU Makeだ。FreeBSDの標準のmake(1)はpmake(NetBSD make)だが、ちゃんとPortsGNU Makeが含まれている。WindowsでもCygwinやMSYSやGnuWin32のGNU Makeが使える。その意味では、GNU Makeはそこそこポータブルに使えるツールだといえなくもない。*1

一般的には「C言語C++のビルド用」なイメージが強い気がするmake(1)だが、実はFortranObjective-CといったGCCの対応言語や、lex・yaccTeXなどのUnix環境由来のツール向けの暗黙のルールがあらかじめ組み込まれている。またルールの変更や追加が容易なので、新たな言語でも手軽にビルドできるようにするのは比較的楽だ。何しろ私が初めてmake(1)の存在を知った時のネタは「make(1)でJavaのソースをビルドする」だった。

古臭いし取っ付きにくいし色々とアレだけどなかなか捨てられない――そんなGNU MakeでCoffeeScriptコンパイルする為の雛形を用意することで更に捨てられないようにしてしまおう、なんて少しも考えていません。そもそもaltJS界隈は混戦状態でCoffeeScriptが廃る可能性だって(ry *2

前提条件

  • コンパイルする為のコマンドcoffeeへのPATHが通っている。
  • CoffeeScriptのソースファイルの拡張子:.coffee
    • この拡張子、一般的だよね?

特定のファイルのみコンパイルしたい場合

OBJSにコンパイルによって生成されるはずのファイル名をパス付きで書く。ソースファイルの拡張子を.jsに変更した名前ですな。複数のファイルをコンパイルしたい場合はOBJSに対象ファイルをスペース区切りで書く。

OBJS   := hello.js

.PHONY: all
all: $(OBJS)

.PHONY: clean
clean:
	$(RM) $(OBJS)

%.js: %.coffee
	coffee -c $<

この例だと「make」か「make all」でカレントディレクトリのhello.coffeeがコンパイルされてhello.jsが生成される。「make clean」でhello.jsが削除される。

マクロOBJSの名前が微妙すぎるけど、代替の良い名前が思い浮かばない……。

カレントディレクトリの全ソースをコンパイルしたい場合

こんな感じでOK。カレントディレクトリの全ソースファイルを列挙して、拡張子を.jsに変更してOBJSに設定している。

OBJS   := $(patsubst %.coffee,%.js,$(wildcard *.coffee))

.PHONY: all
all: $(OBJS)

.PHONY: clean
clean:
	$(RM) $(OBJS)

%.js: %.coffee
	coffee -c $<

このMakefileは調整不要。このままカレントディレクトリに置いてmakeすればOK。

複数ディレクトリの全ソースをコンパイルしたい場合

カレントディレクトリ以外の任意のディレクトリも検索対象としてGNU Makeに指定する為にVPATHを使用する。VPATHにカレントディレクトリを含む対象ディレクトリを記述する。

そうすると頑張って全ソースファイルを列挙して(中略)OBJSに設定する。

VPATH  := . ./aaa ./bbb
OBJS   := $(patsubst %.coffee,%.js,$(wildcard $(addsuffix /*.coffee,$(VPATH))))

.PHONY: all
all: $(OBJS)

.PHONY: clean
clean:
	$(RM) $(OBJS)

%.js: %.coffee
	coffee -c $<

この例ではカレントディレクトリとその配下の./aaa、./bbb直下のソースファイルがコンパイルされる。

VPATHにカレントディレクトリを含めるのは、カレントディレクトリのソースファイルと同じ名前のファイルが他のディレクトリに存在した場合に、カレントの当該ファイルがコンパイルされるようにする為だ。

まあOBJSに(相対パスとはいえ)パス付きでソースファイル名を格納している時点でVPATHを使う意味があるのか無いのか微妙な所かもしれない。

カレントディレクトリ以下の全ソースを再帰的にコンパイルしたい場合

カレント以下を再帰的に――とかやりたい場合は、組み込み関数shellを使ってfind(1)でディレクトリを列挙してVPATHに設定すれば何とかなる。

VPATH  := $(shell find . -type d)
OBJS   := $(patsubst %.coffee,%.js,$(wildcard $(addsuffix /*.coffee,$(VPATH))))

.PHONY: all
all: $(OBJS)

.PHONY: clean
clean:
	$(RM) $(OBJS)

%.js: %.coffee
	coffee -c $<

このMakefileも調整不要。再帰のトップディレクトリに置いてmakeすればOK。

組み込み関数shellは強力だが、最後の手段だと思っている。各ルールの実行コマンド部もそうだが、手元のshell環境の影響を大きく受ける。つまり、シェルスクリプトの移植性の問題と付き合わなくてはならない。

まとめ

そもそもWebフロントエンド分野は門外漢なので、ビルドツールに何を使うのが鉄板なのか、よく分からん。

*1:ただしシェルコマンド絡みの移植性を除く。WindowsGNU Makeを使おうとすると、最低限のUnixユーザランドのツールも欲しくなり、結局はCygwinやMSYSをインストールすることになる――という程度にはシェルコマンドを使用するからなあ。

*2:いや、マジで今のaltJS乱戦がどう転ぶのか分からん。門外漢だもの。