Up: 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ファイルに変換することは,常に可能だというわけではありません.