make 改訂版(4章)

コマンド行の注意点

各コマンド行は独立したシェルで実行される

以下のようなことをすると、rmコマンドで悲しい結果を生み出してしまう。

clean:
	cd hoge
	rm *.sh

cd, rm ともそれぞれ新しいシェルを起動し実行されてしまう。
そのため、hogeと同一階層にあるスクリプトファイルがみんな消えてしまう。
端末上で実行しているように、一連の処理として実行したい場合は、『; \』 を使って1行のコマンドとして実行する

clean:
	cd hoge; \
	rm *.rm

strace make clean ってやると、
前者の場合は2回execve()が実行されているが、後者の場合は1回だけexecve()が実行される。

また、if/for/whileなどの制御文を使う時も1行のコマンドとして実行させないとエラーを吐いてしまう。

改行を含んだ実行文を一連の処理として行いたい場合は、『; \』で1行として認識させるようにしないといけない

シェル変数にアクセスするには$$

通常の感覚で$一個でアクセスしようとすると、マクロだと解釈されて展開が実行されてしまう。
以下のようにすると、"hogehoge"ではなく"oge"と出力されてしまう。

test:
	hoge="hogehoge"; \
	echo $hoge

$があるとmakeはマクロを展開しようとするが、$hなんてマクロは定義されていないからこんなことに。
マクロを展開した結果「oge」がechoに渡されてしまう。
あと、echo ${hoge}とやると、hogeをマクロ名だと解釈してしまうので、何も表示されなくなってしまう。

makeには$$というマクロに「$」が定義されているから、

test:
	hoge="hogehoge"; \
	echo $$hoge

とすると思い通りに実行してくれる。

でも、$*とか$?とか定義済みのマクロ一覧ってどうやったら参照できるんだろうか。
make -p -f/dev/null ってやっても表示されないし。。。

エラーハンドリング

無視してしまうか、条件判定で処理するか

無視する
  1. コマンド行の先頭に-をつける
  2. 実行時に-iオプションを指定する
  3. 疑似ターゲット.IGNOREを定義する

GNU make日本語訳(Coop編) コマンド内エラーによると、2, 3のやり方はおすすめしないみたい

条件判定

ちゃんとエラーハンドリングしたい!って場合は各コマンドの復帰値を拾って対処