プログラミングユーティリティ

.KEEP_STATE と隠れた依存関係

ヘッダーを挿入するための #include 指令が C のソースファイルに記述されている場合は、ターゲットはヘッダーファイルとソースファイルの両方に依存します。このようなヘッダーファイルは、コンパイルのコマンド行ではソースとして明示的に表示される場合があるため、これらの関係を隠れた依存関係と呼びます。.KEEP_STATE が有効の場合は、さまざまなコンパイラおよびコンパイルのプリプロセッサは、どの隠れた依存ファイルがどのターゲットに対応しているかを make に通知します。

.KEEP_STATE は、この情報を状態ファイルの依存関係のリストに追加します。以降の実行では、これらの追加された依存関係は通常の依存関係と同様に処理されます。この機能により、各ターゲットの隠れた依存関係のリストが常に正確で最新の状態で自動的に保持されます。また、完全な依存関係のリストを生成するために、旧バージョンのメークファイルでのように複雑なスキームを使用する必要がなくなります。

隠れた依存関係を持つターゲットを make が最初に処理する際には、状態ファイルにはまだそれらの記録がないため、若干不便な場合があります。ヘッダーがなく、make がその記録を持っていない場合は、ターゲットのコンパイル前に SCCS からヘッダーファイルを取り出す必要があることを make は認識できません。

SCCS の履歴ファイルがある場合でも、依存関係のリストや状態ファイルに履歴ファイルはまだ含まれていないため、現在のバージョンは取り出されません。C のプリプロセッサがヘッダーを挿入する際にはヘッダーが見つからないでのコンパイルは失敗します。

hidden.h というヘッダーを挿入する #include 指令が functions.c に追加されて、それ以降に何らかの理由で make を実行する前にファイル hidden.h が削除された場合は、make の実行結果は以下のようになります。

$ rm -f hidden.h 
$ make functions 
cc -O -o functions functions.c 
functions.c: 2: Can't find include file hidden.h 
make: Fatal error: Command failed for target `functions'

これを回避するには、新しいヘッダーが存在することを確認してから make を実行してください。またコンパイルが失敗する場合でも、SCCS がヘッダーを管理していれば、SCCS から手動でヘッダーを取り出すことができます。

$ sccs get hidden.h 
1.1 
10 lines 
$ make functions 
cc -O -o functions functions.c

2 回目以降に make を実行する際には隠れた依存関係として状態ファイルに記述されているため、make は構築を実行またはヘッダーを取り出すことができます。

隠れた依存関係の検査では、$? マクロは隠れた依存関係の依存ファイル名をインクルードします。このため、$? を使用する既存のメークファイルで予期しない動作が生じる場合があります。

.INIT と隠れた依存関係

前述のどちらの方法でも、他の (インクルード) ディレクトリの状態が一定でないために、ローカルディレクトリで最初に実行する make が失敗する場合があるという問題があります。このため、最初に行う構築をだれかが監視する必要があります。これを回避するには、.INIT ターゲットを使用して、既知の隠れた依存ファイルを SCCS から取り出します。.INIT は、make の実行開始時に依存関係とともに構築される特殊ターゲットです。hidden.h が必ず存在するようにするには、以下の行をメークファイルに追加します。

.INIT:     hidden.h