前へ | 次へ | 目次 | 英語原版(gnu.org)

11 makeでアーカイブファイルを更新する

 アーカイブファイルとは、メンバーと呼ばれる名前付きのサブファイルをまとめて格納したファイルです。アーカイブファイルは ar というプログラムで管理され、おもにリンク用のサブルーチンライブラリとして使われます。

11.1 アーカイブメンバーをターゲットにする

 アーカイブファイルの中の個々のメンバーは、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)’ のようになります。

11.2 アーカイブメンバーターゲットの暗黙のルール

 a(m) のような形をしたターゲットは、アーカイブファイル a の中の m という名前のメンバーを表す、ということを思い出してください。

 make がこのようなターゲットに対して暗黙のルールを探すとき、特別な仕掛けとして、実際のターゲット a(m) にマッチするルールだけでなく、(m) にマッチする暗黙のルールも対象に加えます。

 このおかげで、ターゲットが (%) である特別なルールが一つマッチします。このルールは、ファイル m をアーカイブの中にコピーすることで、ターゲット a(m) を更新します。例えば、ファイル bar.o をアーカイブ foo.a の中に bar.o という名前のメンバーとしてコピーすることで、アーカイブメンバーターゲット foo.a(bar.o) を更新します。

 このルールが他のルールと連鎖すると、とても強力になります。そのため、bar.c というファイルがあれば、makefile が一切なくても、‘make "foo.a(bar.o)"’(クォートは、‘(’ と ‘)’ がシェルに特別な意味で解釈されるのを防ぐために必要です)と打つだけで、次のレシピが実行されます:

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

これは、ファイル dir/file.ofile.o という名前のメンバーにコピーする、という効果を持ちます。こうした使い方に関連して、自動変数 %D%F が役に立つことがあります。

11.2.1 アーカイブのシンボルディレクトリを更新する

 ライブラリとして使われるアーカイブファイルは、ふつう __.SYMDEF という名前の特別なメンバーを含んでいます。これは、他のすべてのメンバーが定義している外部シンボル名の目録(ディレクトリ)を保持しています。他のメンバーを更新したら、その変更が __.SYMDEF に正しく反映されるよう、__.SYMDEF も更新する必要があります。これは、ranlib プログラムを実行することで行います:

ranlib archivefile

 通常は、このコマンドをアーカイブファイルのルールに記述し、アーカイブファイルのメンバーすべてをそのルールの前提条件にします。例えば、以下のように書きます:

libfoo.a: libfoo.a(x.o y.o …)
        ranlib libfoo.a

 これによって、アーカイブメンバー x.oy.o などが更新され、続いて ranlib の実行によってシンボルディレクトリのメンバー __.SYMDEF が更新されます。メンバーを更新するためのルールはここには示していません。おそらく、それらは省略してしまい、前の節で説明したファイルをアーカイブにコピーする暗黙のルールに任せてしまってよいでしょう。

 なお、GNU の ar プログラムを使う場合は、これは必要ありません。GNU の ar__.SYMDEF メンバーを自動的に更新するからです。

11.3 アーカイブを使うときの危険

 アーカイブを更新するための組み込みルールは、並列ビルドと相性がよくありません。これらのルール(POSIX 標準が要求しているものです)は、各オブジェクトファイルがコンパイルされるたびに、それをアーカイブに追加します。並列ビルドを有効にしていると、これによって複数の ar コマンドが同じアーカイブを同時に更新しようとすることになりますが、これはサポートされていません。

 アーカイブで並列ビルドを使いたい場合は、次の行を makefile に追加することで、デフォルトのルールをオーバーライドできます:

(%) : % ;
%.a : ; $(AR) $(ARFLAGS) $@ $?

 1 行目は、アーカイブ内の個々のオブジェクトを更新するルールを、何もしないように変更します。2 行目は、アーカイブをビルドするデフォルトのルールを、古くなったオブジェクト($?)すべてを 1 つのコマンドで更新するように変更します。

 もちろん、ライブラリの前提条件はやはりアーカイブ構文を使って宣言する必要があります:

libfoo.a: libfoo.a(x.o y.o …)

 明示的なルールを書きたい場合は、次のように書けます:

libfoo.a: libfoo.a(x.o y.o …)
        $(AR) $(ARFLAGS) $@ $?

11.4 アーカイブファイルのサフィックスルール

 アーカイブファイルを扱うための、特別な種類のサフィックスルールを書くこともできます。サフィックスルールの完全な説明については、昔ながらのサフィックスルールを参照してください。アーカイブのサフィックスルールは 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

 実際、make は ‘.a’ をターゲットのサフィックスとするサフィックスルールを見つけると、まさにこのとおりのことを行います。‘.x.a’ という形のダブルサフィックスルールはすべて、ターゲットパターンが ‘(%.o)’、前提条件パターンが ‘%.x’ のパターンルールに変換されます。

 ‘.a’ を別の種類のファイルのサフィックスとして使いたい場合もあるでしょうから、make はアーカイブのサフィックスルールを通常どおりのパターンルールにも変換します(昔ながらのサフィックスルールを参照してください)。したがって、ダブルサフィックスルール ‘.x.a’ は、‘(%.o): %.x’ と ‘%.a: %.x’ という 2 つのパターンルールを生成します。


前へ | 次へ | 目次 | 英語原版(gnu.org)