make
を利用する
アーカイブファイルとはメンバーと呼ばれるサブファイルにより構成されるファイルのことで、主な用途はリンク用のサブルーチンライブラリとしての利用でar
というプログラムによって管理されます。
あるアーカイブの個々のメンバをmake
のターゲットや依存関係とする事が可能です。archive という名前のアーカイブファイルの中にあるmember という名前のメンバーを指定したい場合、次のようにします。
archive(member)
こういう構成はコマンドではできません、あくまでターゲットと依存関係においてのみ有効です! コマンドで使うほとんどのプログラムではこの構文をサポートしていませんし、アーカイブメンバーに直接作用する事もできません。ar
やその他アーカイブ操作用に設計されたプログラムのみがこれを利用できます。そのためアーカイブメンバターゲットを更新する有効なコマンドでは必ずar
を使わなければならなくなるでしょう。たとえば次のルールでは`hack.o'というファイルをコピーして`foolib'というアーカイブ内に`hack.o'というメンバーを作成させます。
foolib(hack.o) : hack.o ar cr foolib hack.o
実際にはほとんど全部のアーカイブメンバーターゲットが全くこれと同様に更新します。だから代わりにこれを行ってくれる暗黙のルールがあります。
注意:アーカイブがまだ存在していなければar
に`c'フラグが渡す事になります。
同じアーカイブに複数のメンバーを指定するには括弧の中に全部のメンバー名称を書き込みます。たとえば、
foolib(hack.o kludge.o)
…とするのは以下と同等です。
foolib(hack.o) foolib(kludge.o)
アーカイブメンバの参照ではシェル形式のワイルドカードも使えます。 これについてはファイル名にワイルドカードを利用するの項を見てください。例えば、`foolib(*.o)'とすれば`foolib'アーカイブに現存し、`.o'で終わる名前の全メンバーを展開します。多分ここでは`foolib(hack.o) foolib(kludge.o)'となるでしょう。
aというアーカイブファイルにあるmという名前のメンバーを示す`a(m)'というようなターゲットを思い出してください。
make
がこういうターゲットのために暗黙のルールを探す際は、特別に`(m)'に一致する暗黙のルールを探してそれを`a(m)'という実際のターゲットに一致したのと同様に考えます。
これは`(%)'というターゲットを持つ一つの特別なルールが一致することで機能します。このルールは`a(m)'というターゲットをmというファイルをアーカイブ内部にコピーして更新させるルールです。例えば、`foo.a(bar.o)'というアーカイブメンバーターゲットは`bar.o'というファイルを`bar.o'という名前のメンバーとしてコピーして更新されます。
このルールが他のルールと連鎖するとすごくすばらしい結果になってくれます。つまり`make "foo.a(bar.o)"'(`('と`)'がシェルで変に解釈されないためにクォーテーションが必要です)とすれば、`bar.c'というファイルがあるだけでmakefileなんてなくても次のコマンドが実行されるのです。
cc -c bar.c -o bar.o ar r foo.a bar.o rm -f bar.o
make
はここでは`bar.o'というファイルは中間ファイルだと想定しています。これについては暗黙ルールの連鎖の項を見て下さい。
このような暗黙のルールは`$%'という自動変数を使って書かれています。これについては自動変数の項を見て下さい。
アーカイブ内のアーカイブメンバー名称にはディレクトリを含めることはできませんが、makefileでそういうような真似事をするのは便利な事でしょう。`foo.a(dir/file.o)'というアーカイブメンバーターゲットを書いた場合、自動的にmake
は次のコマンドを更新に使います。
ar r foo.a dir/file.o
…これは、`file.o'という名前のメンバーを`dir/file.o'というファイルをコピーする効果があります。この慣習に関しては%D
と%F
という自動変数が便利かと思います。
ライブラリとして利用されるアーカイブファイルは普通、すべてのメンバーで定義される外部シンボル名のディレクトリを格納する`__.SYMDEF'という名前の特別なメンバーが含まれています。他のメンバーを更新した後はメンバー全部が適切に要約されるように`__.SYMDEF'を更新する必要があります。
ranlib アーカイブファイル
通常はアーカイブファイルに対するルールでこのコマンドを入力して、アーカイブメンバーがそのルールの全依存関係になるようにします。 例えば、
libfoo.a: libfoo.a(x.o) libfoo.a(y.o) ... ranlib libfoo.a
これは`x.o', `y.o'などのアーカイブメンバーを更新させる効果があり、ranlib
を実行して`__.SYMDEF'というシンボルディレクトリメンバーを更新する効果があります。メンバーを更新するルールはここでは見当たりませんが、前の項で述べたようにほとんどの場合は省略すれば暗黙のルールがファイルをコピーしてアーカイブに格納してくれます。
GNU ar
プログラムでは`__.SYMDEF'メンバーを自動的に更新してくれるため、これは不要です。
並列実行(-j
スイッチ;並列実行の項を参照)とアーカイブを併用するときは注意が必要です。ar
が複数起動して同じアーカイブに同時に作動すると、プログラム同士で相手が何をしているのかを知らないためにそのファイルをだめにしてしまう可能性があります。
make
の後発のバージョンではひょっとしたらこの問題を回避するのにアーカイブファイルを操作するコマンドでは全部を直列化する、というメカニズムを提供しているかもしれませんが、その時が来ないうちはこの問題を避けるのにmakefileで別の方法を講じるか、-j
を使わないかのどちらかにしなければなりません。
アーカイブファイルを扱わせる特殊なサフィックスルールを書く事も可能です。サフィックスルールの詳細説明については古いタイプのサフィクスルール(Suffix Rules)の項を見てください。GNU make
ではアーカイブに型ルールを使うほうがより一般的なメカニズム(アーカイブメンバーターゲットに対する暗黙のルールの項を参照)になるため、アーカイブサフィックスルールは古いものとなりましたが、別のmake
プログラムとの互換性のために維持しています。
アーカイブに対してサフィックスルールを書くにはただ単に(アーカイブファイルの慣習的なサフィックスである)`.a'というターゲットサフィックスを使ってサフィックスルールを書くだけで結構です。例えば次に示すのはCソースファイルからライブラリアーカイブを更新してくれる古いタイプのサフィックスルールです。
.c.a: $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o $(AR) r $@ $*.o $(RM) $*.o
これは次の型ルールを記述したのと全く同様に動作します。
(%.o): %.c $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o $(AR) r $@ $*.o $(RM) $*.o
`.a'をターゲットサフィックスするサフィックスルールを見た時にmake
が行う動作というのは実のところ、これなのです。`.x.a'という二重サフィックスのルールはどれも`(%.o)'というターゲット型と`%.x'という依存関係の型を持つ型ルールに変換されます。
別の種類のファイルのサフィックスとして`.a'を使いたい場合もあると思うので、make
は普通の方法でのアーカイブサフィックスルールから型ルールへの変換も行ってくれます(古いタイプのサフィクスルールの項を参照)。だから、`.x.a'という二重サフィックスルールは`(%.o): %.x'と`%.a: %.x'という二つの型ルールを生成します。