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

依存関係の検査 : make とシェルスクリプト

単純な処理の場合には、ソフトウェアの構築にシェルスクリプトを使用して整合性を保つことができますが、ソフトウェアプロジェクトの構築では多くの場合スクリプトは適していません。プログラムまたはオブジェクトモジュールのうちの 1 つだけが変更されている場合に、単純なスクリプトを使用してすべてのプログラムまたはオブジェクトモジュールをコンパイルするのは効率がよくありません。また、スクリプトを繰り返し編集しているうちに、整合性を保つことができない場合があります。再コンパイルが必要なモジュールだけを再コンパイルするスクリプトを記述することはできますが、それには make を使用する方が適しています。

make を使用すると、構築するファイルとその構築方法を簡潔かつ構造的に記述することができます。make は、依存関係の検査という仕組みを使用して、各モジュールとその派生元のソースファイルまたは中間ファイルを比較します。make は、モジュールが最後に構築された後にこれらの派生元のファイル (依存ファイルと呼びます) が変更されている場合にのみ、モジュールを再構築します。

派生したファイルがソースファイルよりも古いものかどうかを確認するため、make は (既存の) モジュールおよびその依存ファイルが修正された時間を比較します。モジュールがない、あるいはモジュールが依存ファイルよりも古い場合は、make はそのモジュールが最新でないとみなし、再構築に必要なコマンドを発行します。再構築に使用されたコマンドが変更されている場合に、モジュールが最新でないとみなされることがあります。

make は依存関係を完全に検査するため、1 つのソースファイルへの変更が任意の数の中間ファイルまたは処理過程に一貫して反映されます。このため、上位から下位へという階層で処理を指定することができます。

make は、メークファイルを読み取り、実行する必要のある処理を特定し、モジュールを完成させるために必要な処理のみを実行します。構築する各ファイルや実行するそれぞれの処理 (手順) をターゲットと呼びます。メークファイル中に記述するターゲットのエントリには、ターゲットの名前、そのターゲットが依存するターゲットのリスト、ターゲットを構築するためのコマンドのリストが記述されています。

コマンドのリストを規則と呼びます。make は、依存関係を必須ターゲットとして扱い、依存関係を必要に応じて更新してから現在のターゲットを処理します。ターゲットの規則によって生成されたファイルをターゲットファイルと呼びます。ターゲットの名前は、生成されるターゲットファイルの名前と対応付けられています。ターゲットの規則がファイルを生成しない場合もあります。ターゲットの派生元のファイル (ターゲットが依存しているファイルなど) を依存ファイルと呼びます。

ターゲットの規則がそのターゲットの名前のファイルを生成しない場合は、make は規則を実行し、それ以降の make の実行ではターゲットが最新のものであるとみなします。

make は、現在の実行で処理されているファイルに対しては、make だけが変更を行うことを前提としています。make の実行中に他の処理がソースファイルを変更すると、make が生成するファイルが不整合になる場合があります。

簡単なメークファイルの記述

メークファイルのターゲットのエントリの基本的な書式は、以下のとおりです。

表 4-1 メークファイルのターゲットのエントリ形式
target .  .  .  : [ dependency .  .  .  ] 
            [ command ]
             . . .

最初の行では、ターゲット名のリストの後にコロンを付けます。依存関係がある場合にはコロンの後にそのリストを記述します。複数のターゲットが記述されている場合は、指定された規則を使用して各ターゲットが独立して構築されます。

タブで始まる次の行に示されているように、行はターゲットの規則を示すコマンド行になります。タブの代わりに空白文字を使用することはできません。

# で始まる行は、次の (エスケープされていない) 復帰改行 (NEWLINE) までがコメントとして扱われ、ターゲットのエントリとして処理されません。次にタブ# 以外の文字で始まる空白でない行の直前まで、あるいはファイルの最後までが、ターゲットのエントリとみなされます。

メークファイルは、以下の例のように 1 つのターゲットだけで構成される簡単なものもあります。

表 4-2 簡単なメークファイル
test: 
     ls test 
     touch test

引数を指定せずに make を実行すると、make はまず makefile という名前のファイルを検索し、見つからない場合は Makefile という名前のファイルを検索します。いずれかの名前のメークファイルが SCCS 管理されている場合、make は SCCS の履歴ファイルを調べ、メークファイルが最新でない場合は、最新のバージョンを抽出します。

次に、makeメークファイル内の最初のターゲットのエントリについて依存関係の検査を開始します。メークファイルがない場合は、構築するターゲットのリストをコマンド行で引数として指定する必要があります。ターゲットの構築中には、make が実行中のコマンドが表示されます。

$ make 
ls test
test not found
touch test
ls test
test

この例では、test というファイルが存在しない (つまり最新の状態でない) ため、make はターゲットのエントリに指定されている規則を実行しています。make をもう一度実行すると、ターゲットは最新になっているというメッセージが表示され、規則は実行されません。

$ make 
`test' is up to date.

注 -

セミコロン (;)、切り替え記号 (<>>>|)、置換記号 (*?[]$=)、引用符、エスケープ文字、コメント ("'`¥# など、:) などの、シェルのメタキャラクタがコマンド行に含まれている場合は、make は Bourne シェルを起動してコマンド行を処理します。シェルによるコマンド行の構文解析が必要ない場合は、make はコマンドを直接実行します。


各コマンド行は独立したプロセスまたはシェルによって実行されるため、規則内での行の区切りには重要な意味があります。

以下の規則を例にして説明します。

test: 
       cd /tmp 
       pwd

この規則の実行結果は、以下のようになります。

$ make test
cd /tmp 
pwd
/usr/tutorial/waite/arcana/minor/pentangles 

一連のコマンドをセミコロンで区切って指定すると、シェルを 1 回呼び出すだけですべてのコマンドが実行されます。

test: 
    cd /tmp ; pwd

また、復帰改行をバックスラッシュ (¥) でエスケープすると、2 行に渡って記述された入力コマンドが、1 行で続けて記述された場合と同等に扱われます。make は、エスケープされた復帰改行を空白文字として処理します。

バックスラッシュは、行の最後に記述する必要があります。バックスラッシュの前には、シェルが処理するためのセミコロンが必要です。

test: 
       cd /tmp ; ¥ 
       pwd 

暗黙の規則の基本的な用途

ターゲットに規則が指定されていない場合は、make暗黙の規則を使用してターゲットを構築します。ターゲットが属するファイルのクラスに対する規則が make によって検出された場合は、暗黙の規則のターゲットエントリで定義されている規則が適用されます。

make は、ユーザーが指定したメークファイルの他に、デフォルトのメークファイル (/usr/share/lib/make/make.rules) も読み取ります。このデフォルトのメークファイルには、多数の暗黙の規則のためのターゲットエントリなどの情報が記述されています。


注 -

System V make では、暗黙の規則は make プログラム中に定義 (ハードコード) されています。


暗黙の規則には、接尾辞の規則パターンマッチングの規則の 2 種類があります。接尾辞の規則は、ある接尾辞を持つファイルを、ベース名は同じで接尾辞が異なる別のファイルから構築するためのコマンドを指定します。パターンマッチングの規則は、ワイルドカードのパターンに一致するターゲットおよび依存関係に基づいて規則を選択します。デフォルトの暗黙の規則は、接尾辞の規則です。

接尾辞の規則を使用すると、メークファイルを記述する必要がなくなる場合があります。たとえば、以下のように make コマンドを実行して、functions.c という 1 つの C ソースファイルから functions.o という名前のオブジェクトファイルを構築することができます。

$ make functions.o
cc -c functions.c -o functions.o 

makeは、nonesuch.c というソースファイルから nonesuch.o というオブジェクトファイルを構築する場合でも同様に機能します。

functions.c から functions という名前の (接尾辞なし) 実行可能ファイルを構築するには、以下のように make コマンドを実行します。

$ make functions
cc -o functions functions.c

.c ファイルから .o という接尾辞のファイルを構築する際の規則を、.c.o 接尾辞の規則と呼びます。.c ファイルから実行可能プログラムを構築する際の規則を、.c 規則と呼びます。デフォルトの接尾辞のすべての規則は表 4-8 を参照してください。

依存関係の処理

make の開始後、make は最初の依存関係を検査し、ターゲットが検出されるとそのターゲットが処理されます。以下のメークファイルを例として説明します。

batch: a b 
     touch batch 
b: 
     touch b 
a: 
     touch a 
c: 
     echo "you won't see me"

make は、batch というターゲットから処理を開始します。batch には検査されていない依存関係、つまり ab があるため、makeab の依存関係の検査が終了するまで batch を実行しません。

Graphic

a には依存関係がないため、makea を処理します。ファイルがない場合は、make はターゲットのエントリの規則を実行します。

$ make 
touch a 
...

次に、make は親のターゲットである batch に戻ります。まだ検査されていない依存関係 b があるため、makeb に移って検査を行います。

Graphic

b にも依存関係がないため、make はその規則を実行します。

...
touch b 
...

これで batch のすべての依存関係が検査され (必要であれば) 構築されたため、最後に makebatch を検査します。

Graphic

makebatch の依存関係のうち少なくとも 1 つを再構築したため、makebatch が最新ではないものとみなして再構築します。つまり make はタイムスタンプを比較する検査を行うので、a または b が、この make の実行では構築されていないが、ディレクトリ内には存在していて batch より新しい場合にも、 batch が再構築されます。

...
touch batch

依存関係の検査で検出されないターゲットのエントリは処理されません。c のターゲットエントリがメークファイル中にありますが、batch の依存関係の検査において c のエントリは検出されていないため、c の規則は実行されません。make コマンドの引数として入力すると、c を開始ターゲットとして指定することができます。

次の例では、batch のターゲットはファイルを生成せず、複数のターゲットを 1 つのグループとして示すラベルとして使用されます。

batch: a b c
a: a1 a2 
      touch a
b: 
      touch b 
c: 
      touch c
a1: 
      touch a1
a2: 
      touch a2

この場合は、下図のようにターゲットが検査および処理されます。

Graphic

要約すると、make は以下のような処理を実行します。

  1. batch の依存関係を検査して依存関係を 3 つ検出するので、batch の処理はまだ実行しません。

  2. 最初の依存関係である a を検査します。依存関係を 2 つ検出します。同様に、make は次の処理を実行します。

    1. a1 を検査し、必要であればそれを再構築します。

    2. a2 を検査し、必要であればそれを再構築します。

  3. a を再構築するかどうかを決定します。

  4. b を検査し、必要であればそれを再構築します。

  5. c を検査し、必要であれば それを再構築します。

  6. make は、依存関係のツリー構造をすべて処理した後に、最上位のターゲットである batch の検査および処理を行います。batch に規則が含まれている場合は、make はその規則を実行します。この例では、batch には規則が含まれていないため、make は規則を実行せずにその batch を再構築します。batch に依存するすべてのターゲットも再構築されます。

空の (NULL) 規則

ターゲットに規則が含まれていない場合は、make は暗黙の規則を選択してターゲットを構築します。適切な暗黙の規則を make が検出できず、規則を取り出すための SCCS 履歴がない場合は、make はターゲットに対応するファイルがないものとし、規則が空であるとみなします。


注 -

規則が空である依存関係を使用して、ターゲットの規則を強制的に実行することができます。たとえば、FORCE という規則は空のターゲットを定義します。


以下のメークファイルを例として説明します。

haste: FORCE
        echo "haste makes waste"
FORCE:

make は、haste という名前のファイルが最新である場合でも、haste を作成するための規則を実行します。

$ touch haste 
$ make haste 
echo "haste makes waste"
haste makes waste

特殊ターゲット

make には、特別な機能を実行するための特殊ターゲットが組み込まれています。たとえば、.PRECIOUS という特殊ターゲットは、make が割り込まれたときにライブラリファイルを保存するように make に指示します。

特殊ターゲットには、以下のような特徴があります。

表 4-3 に、特殊ターゲットの一覧を示しています。

不明なターゲット

ターゲットの名前がコマンド行またはメークファイル中の依存関係リストで指定されており、かつ以下のいずれかに該当する場合には、make は処理を停止してエラーメッセージを表示します。

$ make believe
make: Fatal error: Don't know how to make target `believe'.

注 -

ただし、-k オプションが有効である場合は、make はエラーが発生したターゲットに依存しない他のターゲットに対して処理を続行します。


重複するターゲット

メークファイル中で同じ名前のターゲットを複数回記述することができます。次に例を示します。

foo:  dep_1
foo:  dep_2
foo:
     touch foo

上記の例は、次の例と同じ結果になります。

foo:  dep_1 dep_2
      touch foo

ただし通常は、メークファイルをわかりやすくするために、ターゲットは 1 回だけ記述することをお勧めします。

make の予約語

以下の表に示す語は、make によって予約されています。

表 4-3 make の予約語

.BUILT_LAST_MAKE_RUN

.DEFAULT

.DERIVED_SRC

.DONE

.IGNORE

.INIT

.KEEP_STATE

.MAKE_VERSION

.NO_PARALLEL

.PRECIOUS

.RECURSIVE

.SCCS_GET

.SILENT

.SUFFIXES

.WAIT

FORCE

HOST_ARCH

HOST_MACH

KEEP_STATE

MAKE

MAKEFLAGS

MFLAGS

TARGET_ARCH

TARGET_MACH

VERSION_1.0

VIRTUAL_ROOT

VPATH

コマンドを表示せずに実行する

規則内のコマンド行の最初に @ を挿入すると、実行中にその行を表示しないようにできます。次に例を示します。

quiet: 
       	@echo you only see me once 

結果は、以下のようになります。

$ make quiet 
         you only see me once

make の実行時にコマンドを表示しないように指定する場合は、-s オプションを使用します。すべての実行でコマンド行の表示を禁止する場合は、.SILENT という特殊ターゲットをメークファイルに追加します。

.SILENT:
quiet:
         echo you only see me once

特殊な機能を持つターゲットは、名前の最初がドット (.) になっています。ドットで始まるターゲット名は、コマンド行の引数として明示的に指定した場合を除き、開始ターゲットとしては使用されません。コマンドがゼロ以外の終了コードを返した場合は、make は通常はエラーメッセージを出力して停止します。たとえば、次のようなターゲットがある場合を考えます。

rmxyz: 
     rm xyz 

この例で、xyz という名前のファイルがない場合は、makerm が終了ステータスを返した後に停止します。

$ ls xyz 
xyz not found
$ make rmxyz 
rm xyz
rm: xyz: No such file or directory
*** Error code 1
make: Fatal error: Command failed for target `rmxyz' 

注 -

-@ の両方を組み合わせて記述することも可能です。


コマンドの終了コードに関係なく処理を続行するには、タブの後に記述する最初の文字としてハイフン (-) を使用します。

rmxyz:
        -rm xyz

この例では、make が受け取った終了コードを示す警告メッセージが表示されます。

$ make rmxyz 
rm xyz 
rm: xyz: No such file or directory 
*** Error code 1 (ignored)

注 -

メークファイルをテストしている場合を除き、通常はゼロ以外のエラーコードをすべて無視することは避けてください。


-i オプションを使用すると、make がすべてのエラーコードを無視するように指定できます。ただし、通常はこのオプションは使用しないでください。また、.IGNORE という特殊ターゲットを記述すると、メークファイルの処理時に make が終了コードを無視するように指定できます。このオプションも、通常は使用しないでください。

ターゲットのリストを処理している際にゼロ以外のリターンコードが返されたときに、処理全体を停止するのではなく後に make が次のターゲットを続けて処理するように指定するには、-k オプションを使用します。

SCCS ファイルの自動取り出し

依存関係リスト中にソースファイルの名前が指定されている場合は、make はそのソースファイルを他のターゲットと同様に処理します。この場合は、ソースファイルはディレクトリ内にあることが前提になっているため、ソースファイルのエントリをメークファイルに追加する必要はありません。

ターゲットに依存関係がなく、ターゲットがディレクトリ内にある場合は、make はファイルを最新のものとみなします。ただしソースファイルが SCCS 管理されている場合は、make はさらにいくつかの検査を行い、ソースファイルが最新であることを確認します。ファイルがないあるいは履歴ファイルの方が新しい場合は、make は自動的に以下のコマンドを実行して、最新のバージョンを取り出します。

sccs get -s filename -Gfilename

注 -

他のバージョンの make では、SCCS ファイルの自動取り出しは特定の暗黙の規則だけで使用できる機能です。また旧バージョンとは異なり、このバージョンの make は履歴ファイルを sccs ディレクトリ内でのみ検索します。作業中のディレクトリ内の履歴ファイルは無視されます。


ただしソースファイルが書き込み可能な場合は、make は新しいバージョンを取り出しません。

$ ls SCCS/* 
SCCS/s.functions.c
$ rm -f functions.c 
$ make functions 
sccs get -s functions.c -Gfunctions.c 
cc -o functions functions.c 

make は、取り出したバージョンのタイムスタンプと履歴ファイルのタイムスタンプを調べます。ディレクトリ内のバージョンが最後にチェックインされた最新バージョンかどうかは調べません。したがって、他のユーザーが日付を指定してファイルを取り出した (sccs get -c) 場合でも、make はそれが最新のバージョンであるかどうかを調べないので、最新でないバージョンのプログラムまたはオブジェクトファイルが構築されることがあります。確実に最新バージョンを構築するには、sccs get SCCS または sccs clean のいずれかのコマンドを実行してから make を実行します。

SCCS ファイル取り出しの抑止

SCCS ファイルの取り出しコマンドは、デフォルトのメークファイル (/usr/share/lib/make/make.rule) の .SCCS_GET という特殊ターゲット用の規則で指定されています。SCCS ファイルの自動取り出しを抑止するには、メークファイルでこのターゲットのエントリに空の規則を指定します。

# Suppress sccs retrieval. 
.SCCS_GET:

パラメータの引き渡し : make の簡単なマクロ

make のマクロ置換は、メークファイル内でパラメータをコマンド行に渡す際に便利です。cc -O オプションを使用して、program という最適化されたプログラムを、コンパイルする場合を例に挙げます。メークファイルに以下の例のようなマクロ参照functions のターゲットに追加して、パラメータをコマンド行に渡すことができます。

functions: functions.c 
         cc $(CFLAGS) -o functions functions.c

マクロ参照は、メークファイル内あるいは make コマンドの引数でユーザーが定義した値に対応する可変部分として機能します。makeCFLAGS マクロの値を定義すると、make はマクロ参照を指定された値に置換します。

$ rm functions
$ make functions "CFLAGS= -O"
cc -O -o functions functions.c

注 -

CFLAGS マクロへの参照は、.c.c.o の両方の暗黙の規則に含まれています。



注 -

コマンド行で指定できる引数は 1 つだけです。この例では、二重引用符で囲んである部分が引数定義を示しています。


マクロが未定義の場合は、make はマクロの参照先を空白の文字列とみなします。

メークファイル中にマクロを定義することもできます。デフォルトで最適化されたオブジェクトコードを make が生成するように、CFLAGS-O に設定するなどの用途があります。

CFLAGS= -O 
functions: functions.c 
         cc $(CFLAGS) -o functions functions.c

make のコマンド行の引数として指定されたマクロ定義は、条件付きマクロ定義を除き、メークファイル内の他の定義よりも優先されます。

たとえば、dbx または dbxtool を使用してデバッグするために functions をコンパイルするには、コマンド行で CFLAGS の値を -g として定義します。

$ rm functions 
$ make CFLAGS=-g 
cc -g -o functions functions.c

gprof を使用してプロファイル用に functions をコンパイルするには、-O および -pg の両方を CFLAGS の値として指定します。

マクロ参照は、マクロ名が 2 文字以上の長さの場合は、括弧で囲む必要があります。マクロ名が 1 文字だけの場合は、括弧を省略できます。括弧の代わりに中括弧 { と } を使用することもできます。たとえば、'$X'、'$(X)'、'${X}' はすべて同じ意味です。

.KEEP_STATE とコマンドの依存関係の検査

通常の依存関係の検査に加えて、特殊ターゲットの .KEEP_STATE を使用してコマンドの依存関係を検査することができます。この検査を実行すると、make は各ターゲットファイルと依存ファイルとを検査するだけでなく、規則中の各コマンド行と、ターゲットを最後に構築したときに実行したコマンド行の比較も行います。比較の結果は、現在のディレクトリの .make.state ファイルに保存されます (「状態ファイル」を参照してください)。

以下のメークファイルを例として説明します。

CFLAGS= -O 
.KEEP_STATE:

functions: functions.c 
        	cc -o functions functions.c

以下に、上記のメークファイルで make コマンドを実行した結果を示します。

$ make 
cc -O -o functions functions.c
$ make CFLAGS=-g 
cc -g -o functions functions.c 
$ make "CFLAGS= -O -pg" 
cc -O -pg -o functions functions.c

プログラムのコンパイル時には、ユーザーが指定したオプションが優先されて使用されます。

.KEEP_STATE を有効にしてから最初に make を実行したときには、必要な情報を収集して記録するため、すべてのターゲットが再コンパイルされます。KEEP_STATE 変数は、環境変数から取り込んだ場合には、.KEEP_STATE ターゲットと同様に機能します。

選択した行に対してコマンドの依存関係の検査を強制または抑止する

指定したコマンド行のコマンドの依存関係の検査を抑止するには、タブの後の最初の文字として疑問符を挿入します。

動的なマクロである $? を含む行では、コマンドの依存関係の検査が自動的に抑止されます。このマクロは、現在のターゲットよりも新しい依存関係のリストです。このリストの内容は、make の実行ごとに異なる場合があります。

このマクロを含む行に対してコマンドの依存関係の検査を強制的に実行するには、そのコマンド行の (タブの後) の最初の文字として、! を挿入します。

状態ファイル

.KEEP_STATE が有効な場合は、make.make.state という名前の状態ファイルを現在のディレクトリに生成します。このファイルには、.KEEP_STATE が有効になっている間に処理されたすべてのターゲットおよびそのターゲットを構築する規則が、メークファイルの書式で記述されます。この状態ファイルの整合性を保つために、.KEEP_STATEメークファイルに追加した後は、内容を変更しないでください。


注 -

このターゲットは旧バージョンの make では無視されるため、互換性の問題は生じません。このターゲットは、依存するターゲットがなく、規則が空 (NULL) で、それ自身の依存関係がないので、旧バージョンでは余分なターゲットとして処理されます。名前の先頭にドットがあるため、開始ターゲットして使用されません。


.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

make の実行に関する情報を表示する

-n オプションを使用して make を実行すると、make が実行するコマンドを実際には実行せずに表示だけを行います。このオプションは、メークファイルのマクロが意図しているとおりに展開されているかどうかを確認する際に便利です。以下のメークファイルを例に示します。

CFLAGS= -O 

.KEEP_STATE:

functions: main.o data.o 
         $(LINK.c) -o functions main.o data.o

make -n を実行すると、以下のように表示されます。

$ make -n 
cc -O -c main.c 
cc -O -c data.c 
cc -O -o functions main.o data.o

注 -

ただし、1 つ例外があります。MAKE マクロへの参照 ($(MAKE)${MAKE} など) を含むコマンド行は、make-n オプションを付けた場合にも実行されます。以下のような行をメークファイルに記述することは避けてください。

$(MAKE) ; rm -f *



注 -

MAKEFLAGS という環境変数を設定すると、その値が make オプションのリストに追加されるため、処理が複雑になる場合があります。混乱を防ぐために、この変数を設定することは避けてください。


make には、make の動作やその理由を確認できるオプションが他にもいくつかあります。

-d

ターゲットが最新でないと make が決定する条件を表示します。-n オプションとは異なり、以下の例のようにターゲットの処理は実行します。このオプションは、環境変数 (デフォルトでは NULL) から取り込んだ MAKEFLAGS マクロの値も表示します。MAKEFLAGS マクロについての詳細は、後述の節で説明しています。

$ make -d 
MAKEFLAGS value: 
    Building main.o using suffix rule for .c.o because 
it is out of date relative to main.c 
cc -O -c main.c 
    Building functions because it is out of date 
relative to main.o 
    Building data.o using suffix rule for .c.o because 
it is out of date relative to data.c 
cc -O -c data.c 
    Building functions because it is out of date 
relative to data.o 
cc -O -o functions main.o data.o
-dd

make が検査する、すべての依存関係 (隠れた依存関係も含む) を詳細に表示します。

-D

メークファイルのテキストをメークファイル読み取り時に表示します。

-DD

メークファイル、デフォルトのメークファイル、状態ファイル、実行中の make における隠れた依存関係を表示します。

-f makefile

make が (makefile または Makefile ではなく) makefile に指定した名前のメークファイルを使用します。


注 -

複数のメークファイルを指定するには、-f オプションをその数だけ指定します。指定したメークファイルは連結されて処理されます。


-K makestatefile

makestatefile がディレクトリの場合は、make はそのディレクトリ内の .make.state ファイルに KEEP_STATE の情報を書き込みます。makestatefile がファイルの場合は、makeKEEP_STATE 情報を makestatefile に書き込みます。

-p

すべてのマクロ定義およびターゲットのエントリを表示します。

-P

デフォルトのターゲットまたは指定したターゲットのすべての依存関係のツリーを表示します。

-t オプションを使用すると、make の処理を省略できます。-t を使用して make を実行すると、make はターゲットを構築する規則を実行しません。その代わりに touch を使用して、依存関係の検査で検出した各ターゲットの変更時間を更新します。また、構築したターゲットに応じて状態ファイルを更新します。ターゲットのエントリに対応するファイルがない場合は、touch によってファイルが作成されます。


注 -

副作用が生じる場合があるため、make-t (touch) オプションは通常は使用しないでください。


make -t を使用しない例を以下に示します。make によって作成されたターゲットファイルを削除してディレクトリ内を掃除する clean というターゲットがあるとします。

clean: 
         rm functions main.o data.o

注 -

clean は、派生ファイルを削除するターゲットを示す慣用名です。clean は、新しく最初から構築を行う場合に便利です。


ここで、以下のような無意味なコマンドを実行したとします。

$ make -t clean
touch clean 
$ make clean 
`clean' is up to date

この場合、ディレクトリ内を掃除するターゲットを再度機能させるには、clean というファイルを削除する必要があります。

-q

ターゲットファイルが最新かどうかに応じて、ゼロまたはゼロ以外の終了ステータスを返します。

-r

デフォルトのメークファイル (/usr/share/lib/make/make.rules) の読み取りを抑止します。

-S

ゼロ以外の終了ステータスをコマンドが返したときに、処理を停止して -K オプションの効果を取り消します。