上: Sources
インストールに依存していて,配布には依存していない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.cがbindir.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.hがfoo
のソースだという単純な行は,例えば,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_SOURCESはall,
check,そして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.oと
bindir.hの間に記録されることに注意して下さい.そのため,明示的
な依存性は最初のビルドだけで実際に役に立ちます.)
このような明示的な依存性を追加することで,十分に注意しておかないとちょっ
と危険なことになります.これはAutomakeがルールを上書きしようとしないこ
とに由来します(おそらく,より良いものを知っているでしょう).
foo.$(OBJEXT): bindir.hで,foo.$(OBJEXT)をビルドするため
に出力しようとするAutomakeのルールを置き換えます.この状況では,
Automakeはfoo.$(OBJEXT):ターゲットを出力する必要がないので偶然
動作します.それは,代わりにサフィックスルールに関連します(すなわち
.c.$(OBJEXT):).こうする場合は,常に生成される
Makefile.inを調査して下さい.
プリプロセッサマクロを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をbindir.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ファイルに変換することは,常に可能だというわけではありません.