Up: Sources


8.4.1 ビルドされているべきソースの例

インストールに依存していて,配布には依存していないbindir.hをイ ンクルードしているfoo.cを仮定します.それはビルドで要求されます. ここで,bindir.hは,(configureから継承される) make変数bindirの値をもつプリプロセッサマクロ bindirを定義しています,

我々は以下の実装を提案します.ビルドされているソースを処理するすべての 方法のリストを網羅していませんが,この問題に遭遇した場合,ちょっとした アイデアにはなるでしょう.

最初の試み

最初の実装は,前のセクションのブートストラップの問題を説明します (see Sources).

以下は,試験的なMakefile.amです.

     # This won't work.
     bin_PROGRAMS = foo
     foo_SOURCES = foo.c
     nodist_foo_SOURCES = bindir.h
     CLEANFILES = bindir.h
     bindir.h: Makefile
             echo '#define bindir "$(bindir)"' >$@

Automakeは,foo.cbindir.hをインクルードすることを知ら ないので,この設定では動作しません.自動的な依存性の追跡はコンパイルの 副作用として動作するので,foo.oの依存性は,foo.oがコンパ イルされた後になって判明すること(see Dependencies)を覚えておいて下 さい.症状は以下のようになります.

     % make
     source='foo.c' object='foo.o' libtool=no \
     depfile='.deps/foo.Po' tmpdepfile='.deps/foo.TPo' \
     depmode=gcc /bin/sh ./depcomp \
     gcc -I. -I. -g -O2 -c `test -f 'foo.c' || echo './'`foo.c
     foo.c:2: bindir.h: No such file or directory
     make: *** [foo.o] Error 1

この例では,bindir.hは,配布もインストールもされず,一度もビル ドされません.nodist_foo_SOURCES = bindir.h行が全く利用されてい ないことを不思議に思うかもしれません.このbindir.hfoo のソースだという単純な行は,例えば,tagを生成している間に検査されるべ きなので存在します(see Tags).言い替えると,ここでの問題には役に立 たず,それが無くても同じようにビルドは失敗します.

BUILT_SOURCESの使用

解決方法は,他のものをビルドする前にbindir.hをビルドすることを 要求することです.これこそが,BUILT_SOURCESが意味することです (see Sources).

     bin_PROGRAMS = foo
     foo_SOURCES = foo.c
     nodist_foo_SOURCES = bindir.h
     BUILT_SOURCES = bindir.h
     CLEANFILES = bindir.h
     bindir.h: Makefile
             echo '#define bindir "$(bindir)"' >$@

bindir.hが最初にビルドされる様子を見て下さい.

     % make
     echo '#define bindir "/usr/local/bin"' >bindir.h
     make  all-am
     make[1]: Entering directory `/home/adl/tmp'
     source='foo.c' object='foo.o' libtool=no \
     depfile='.deps/foo.Po' tmpdepfile='.deps/foo.TPo' \
     depmode=gcc /bin/sh ./depcomp \
     gcc -I. -I. -g -O2 -c `test -f 'foo.c' || echo './'`foo.c
     gcc  -g -O2   -o foo  foo.o
     make[1]: Leaving directory `/home/adl/tmp'

しかし,以前にいったように,BUILT_SOURCESallcheck,そしてinstallターゲットだけにしか適用されません. これでは,make fooを明示的に実行すると失敗します.

     % make clean
     test -z "bindir.h" || rm -f bindir.h
     test -z "foo" || rm -f foo
     rm -f *.o
     % : > .deps/foo.Po # Suppress previously recorded dependencies
     % make foo
     source='foo.c' object='foo.o' libtool=no \
     depfile='.deps/foo.Po' tmpdepfile='.deps/foo.TPo' \
     depmode=gcc /bin/sh ./depcomp \
     gcc -I. -I. -g -O2 -c `test -f 'foo.c' || echo './'`foo.c
     foo.c:2: bindir.h: No such file or directory
     make: *** [foo.o] Error 1

依存性の手動保存

通常,make allの前にmake fooにようにターゲットをビルドす ることはないので,前回の例のようにBUILT_SOURCESで十分幸せになれ ます.しかし,これで問題がある場合,BUILT_SOURCESを避け, Makefile.amに明示的にそのような依存性を記録することが可能です.

     bin_PROGRAMS = foo
     foo_SOURCES = foo.c
     nodist_foo_SOURCES = bindir.h
     foo.$(OBJEXT): bindir.h
     CLEANFILES = bindir.h
     bindir.h: Makefile
             echo '#define bindir "$(bindir)"' >$@

foo.oすべての依存性をリストアップする必要はなく,ビル ドに必要なものだけをリストアップします.依存性が既に存在する場合,最初 のコンパイルは邪魔をせず,通常の依存性の追跡コードが記録されます.(こ の最初のコンパイルの後の依存性の追跡コードも,foo.obindir.hの間に記録されることに注意して下さい.そのため,明示的 な依存性は最初のビルドだけで実際に役に立ちます.)

このような明示的な依存性を追加することで,十分に注意しておかないとちょっ と危険なことになります.これはAutomakeがルールを上書きしようとしないこ とに由来します(おそらく,より良いものを知っているでしょう). foo.$(OBJEXT): bindir.hで,foo.$(OBJEXT)をビルドするため に出力しようとするAutomakeのルールを置き換えます.この状況では, Automakeはfoo.$(OBJEXT):ターゲットを出力する必要がないので偶然 動作します.それは,代わりにサフィックスルールに関連します(すなわち .c.$(OBJEXT):).こうする場合は,常に生成される Makefile.inを調査して下さい.

configureからbindir.hをビルド

プリプロセッサマクロをconfigureから, config.h(see Defining Directories),またはAC_CONFIG_FILESを使用し てbindir.h.inで(see Configuration Actions)定義することも可能です.

この時点で,configureからbindir.hがビルドされることが明 確になり,この例はうまく動作します.bindir.hはターゲットをビル ドする前に存在しているので,依存性の問題は生じません.

Makefileは以下のように短くなります.bindir.hを記述する必要さえ ありません.

     bin_PROGRAMS = foo
     foo_SOURCES = foo.c

しかし,configureからソースをビルドすることが常に可能だというわ けではなく,特に,これらのソースが最初にビルドされるツールから生成され るときがそうなります...

bindir.hではなくbindir.cをビルド

もう一つの魅力的な考えは,bindirbindir.oからエクスポー トする変数や関数として定義し,bindir.hの代わりにbindir.c をビルドする方法です.

     noinst_PROGRAMS = foo
     foo_SOURCES = foo.c bindir.h
     nodist_foo_SOURCES = bindir.c
     CLEANFILES = bindir.c
     bindir.c: Makefile
             echo 'const char bindir[] = "$(bindir)";' >$

bindir.hには,宣言された変数だけが含まれていて,ビルドする必要 がないため,問題になることはありません.bindir.oは,常に bindir.cに依存するので,bindir.cは最初にビルドされます.

最善の方法は?

もちろん万能薬はありません.それぞれの解決方法には長所と短所があります.

クリーンなツリーでmake fooを実行する能力が重要な場合, BUILT_SOURCESを使用することは不可能です.

Automakeのルールを間違ってオーバーライドしないように用心している場合, 明示的に依存性を追加しないでしょう.

./configureからファイルをビルドしたり,.hファイルを .cファイルに変換することは,常に可能だというわけではありません.