makeがよくわからない日記
複数の*.jsを元にして、別のx.jsを作りたいとする。まあ例えば具体的には複数の*.jsをコンパイルして一つのJSファイルにするとかね。コンパイルの部分は本質ではないので「catで結合する」で代用することにしよう。
Q1
ソースコードのファイル名は未知とする。というわけでワイルドカードを使うことになるだろう。
x.js: *.js cat $? > x.js
いま、カレントディレクトリにa.jsとb.jsがあるとする。
$ cat > a.js a $ cat > b.js b
この状態でmake x.jsすると1回目は期待通りにa.jsとb.jsを結合したx.jsが作られる。しかし、もう一度実行するとx.js自体が依存ファイルの*.jsにマッチしてしまうためエラーになる。
$ make x.js cat a.js b.js > x.js $ make x.js make: Circular x.js <- x.js dependency dropped. make: `x.js' is up to date.
Q1: 「x.jsを依存から除外せよ」と宣言する方法はあるのか?
A1:「@n0kada: GNU makeなら deps.js: $(filter-out deps.js,$(wildcard *.js))」thanks!
Q2
やりかたがわからないので、とりあえずx.jsをカレントディレクトリではなくbuild以下に置くことにした。
build/x.js: *.js mkdir -p build cat $? > build/x.js
$ make mkdir -p build cat a.js b.js > build/x.js $ make make: `build/x.js' is up to date.
とりあえず期待通りに動いている。a.jsやb.jsがカレントディレクトリ以外にある場合はどうか?それが同一のディレクトリにあるなら特に難しくはない。
build/x.js: src/*.js mkdir -p build cat $? > build/x.js
じゃあsrcとlibの2つのディレクトリにあったら?もちろんsrc/*.js lib/*.jsと書けばできるが「ソースファイルがあるディレクトリ」はここにかぎらず他のターゲットでも必要になるので変数にまとめたい。vpathを使えば探索するディレクトリを指定できるのだと思った。しかしうまくいかない。
SRCDIR = src lib vpath %.js $(SRCDIR) build/x.js: *.js mkdir -p build cat $? > build/x.js
これは*.jsを作る方法が見つからない旨のエラーになる。
$ make make: *** No rule to make target `*.js', needed by `build/x.js'. Stop.
仮にカレントディレクトリにc.jsを置くとcだけが対象としてコンパイルされる。
$ cat > c.js c $ make mkdir -p build cat c.js > build/x.js
うーむ?vpathの使い方がおかしい??
しかたがないのでvpathを避けてpatsubstをしてみた。
SRCDIR = src lib build/x.js: $(patsubst %,%/*.js,$(SRCDIR)) mkdir -p build cat $? > build/x.js
これなら期待通りに動く。
$ make mkdir -p build cat src/a.js lib/b.js > build/x.js $ make make: `build/x.js' is up to date.
Q2: こんな力技に頼らない方法があるのではないか?