シェルスクリプトは、テストの実行や、対話式の (ユーザー入力が必要な) 処理あるいは make による依存関係の検査が不要な定型作業を行う際に便利です。特にテストでは、プログラムに対して端末から特定の入力を繰り返し行う必要があります。
ライブラリの場合は、さまざまな機能を実行するプログラムのセットを C で記述し、スクリプトからの特定の入力に応じて特定の順序で実行することができます。ユーティリティプログラムの場合は、機能を実行してその速度を測定するベンチマークプログラムを作成できます。いずれの場合も、各テストを実行するコマンドをシェルスクリプトに組み込み、繰り返しユーザーが行う処理をなくしたり、管理を簡単にすることができます。
テスト用スクリプトを開発した後、そのスクリプトを実行するためのターゲットは簡単に記述できます。スクリプト内では make の依存関係の検査は不要な場合がありますが、依存関係の検査を実行すると、テスト前にプログラムまたはライブラリを更新することができます。
以下に示すテストを実行するためのターゲットエントリでは、test が lib.a に依存しています。ライブラリが最新でない場合は、make はライブラリを再構築してテストを実行します。これにより、常に最新のバージョンを使用してテストが実行されます。
# テスト中のライブラリ LIBRARY= lib.a test: $(LIBRARY) testscript set -x ; testscript > /tmp/test.¥$¥$ testscript: testscript.sh test_1 test_2 test_3 # ライブラリ構築規則 $(LIBRARY): @ echo Building $(LIBRARY) (library-building rules here) # test_1 ... test_3 で複数のライブラリ関数を検査する test_1 test_2 test_3: $$@.c $(LIBRARY) $(LINK.c) -o $@ $<
test は、testscript にも依存しています。testscript は、3 つのテストプログラムに依存しています。
これにより、テストプログラムが make がテスト処理を実行する前に更新されます。lib.a は、メークファイルに含まれるターゲットエントリに従って構築されます。testscript は、.sh の暗黙の規則を使用して構築されます。各テストプログラム用にそれぞれソースファイルが 1 つずつある場合に、最後のターゲットエントリの規則を使用してテストプログラムが構築されます (これらのプログラムは、.c ファイルのほかに、適切なライブラリにもリンクする必要があるため、.c の暗黙の規則は適用されません)。
テスト用の規則に含まれる ¥$¥$ という文字列は、make が $ 記号を解釈しないように指定しています。make は、2 つの $ 記号をそのままシェルに渡します。シェルは、$$ をシェルのプロセス ID に展開します。これよって、各テストごとに異なる名前の一時ファイルに書き込むことが可能になります。set -x コマンドは、シェルが端末上で実行するコマンドをシェルに表示させます。これにより、テスト結果が記録されているファイルの実際の名前を確認することができます。
以下の例のように、規則内でシェルコマンドの置換を指定できます。
do: @echo `cat Listfile`
マクロ中では、逆引用符で囲まれた式を指定することもできます。
DO= `cat Listfile` do: @echo $(DO)
ただし、この形式のコマンド置換は規則内でのみ使用できます。
シェルコマンドをマクロの定義として指定する例を以下に示します。
COMMAND= cat Listfile
コマンド置換マクロ参照を使用して、参照をマクロ値に含まれるコマンド出力に置換するように make に指示できます。このコマンド置換は、メークファイル中の任意の箇所に記述できます。
COMMAND= cat Listfile $(COMMAND:sh): $$(@:=.c)
この例は、他のファイルからターゲットのリストを取り込み、各ターゲットが対応する .c ファイルに依存することを示します。
シェルコマンド置換と同様に、コマンド置換参照が評価されると、コマンドの標準出力結果に置換されます。復帰改行文字は、空白文字に変換されます。コマンドは、参照が検出されると実行されます。コマンドの標準エラーは無視されます。ただし、コマンドがゼロ以外の終了ステータスを返した場合は、make はエラーを表示して停止します。
これを回避するには、コマンド行の末尾に true コマンドを追加します。
COMMAND = cat Listfile ; true
以下の形式のマクロ代入は、command の標準出力を cmd_macro に代入します。以下に例を示します。
cmd_macro:sh = command
COMMAND:sh = cat Listfile $(COMMAND): $$(@:=.c)
この例は、前述の例と同じ結果になります。ただし、この例ではコマンドは make の実行ごとに 1 回だけ実行されます。この場合も、標準出力だけが使用され、復帰改行文字は空白文字に変換されます。また、コマンドがゼロ以外の終了ステータスを返した場合は、make はエラーを表示して停止します。
コマンド置換マクロ代入は、以下の形式で記述することもできます。
macro:sh += command
macro の値にコマンドの出力を追加します。
target := macro:sh = command
target およびその依存関係を処理するときに、command の出力として条件付き macro を定義します。
target := macro:sh += command
target およびその依存関係を処理するときに、command の出力を条件付き macro の値に追加します。