[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
この章では,メーリングリストによく上がる質問をカバーします.
26.1 CVSと生成されるファイル | CVS and generated files | |
26.2 missing とAM_MAINTAINER_MODE | missing and AM_MAINTAINER_MODE | |
26.3 なぜAutomakeはワイルドカードをサポートしないのですか? | Why doesn't Automake support wildcards? | |
26.4 distclean後にビルドディレクトリに残っているファイル | Files left in build directory after distclean | |
26.5 なぜオブジェクトファイルの名前を変更することがあるのですか? | Why are object files sometimes renamed? |
AutoconfとAutomakeを用いて作成したパッケージは,`configure'や `Makefile.in'といった生成されるファイルとともに配布されます.これ らのファイルは開発者のホストで生成され,それらをビルドするためにエンド ユーザが管理用のツールをインストールする必要が無いように配布されます. Lexスキャナー,Yaccパーサ,またInfoドキュメントのような,それ以外に生 成されるファイルは,同じ理由で通常配布されます.
AutomakeはMakefileにこれらのファイルをリビルドするルールを出力します.
例えば,`configure.ac'が変更されたときは`configure'をリビル
ドするためにautoconf
を実行します.`configure'が対応する
`configure.ac'より古くないように,開発者が確実に行なえます.
パッケージで配布されている,生成されたファイルは最新で,tar
でタイムスタンプを保存しているので,これらのリビルドのルールはユーザが
パッケージを展開しビルドするときも開始されません.
CVSキーワードを使用していない限り(この状況ではコミット時にファイルを更
新する必要があります),cvs commit
とcvs import -d
の処理中
にCVSが保持しているタイムスタンプは保持されます.
cvs checkout
を使用してファイルをチェックアウトしたとき,そのタ
イムスタンプは,チェックアウトしたリビジョンで設定されたタイムスタンプ
になります.
しかし,cvs update
したとき,ファイルの日付が更新されますが,
オリジナルのタイムスタンプはこのリビジョンになります.これは,
make
でソースファイルが更新されたことに確実に気付くことを意味
します.
このタイムスタンプの変更は,ソースと生成されたファイルの両方をCVSに保
持しているときは面倒です.CVSはアルファベット順にファイルを処理するの
で,cvs update
で両方のファイルを更新した後は,チェックイン時
に`configure.ac'より`configure'のほうが新しい場合でも,
`configure'より`configure.ac'が古いものとして表されます.
make
を呼び出すと,間違って`configure'のリビルドが開始され
ます.
基本的に二種類の管理者がいます.生成されるファイルを含め,すべての配布 されるファイルをCVSの元に保持している人,そして,生成されたファイルを CVSの外部に保持している人です.
cvs checkout
する代わりに,
コピーを更新するためにcvs update
を使用する場合,タイムスタン
プは不正確になります.autoconf
やautomake
のような管
理者用のツールを,実行を開始したり試みたりするリビルドルールもあります.
実際,そのようなツールの呼び出しは,後で議論するmissing
スク
リプトで呼び出しにすべてラップされています(see section 26.2 missing
とAM_MAINTAINER_MODE
).
missing
は,これらのツールがインストールされていないとき,ビ
ルドが続けられるように,タイムスタンプを修正します.
AM_MAINTAINER_MODE
を使用します.これは,
26.2 missing
とAM_MAINTAINER_MODE
で更に議論していきます.
例えば,開発者が編集された`Makefile.am'とリビルドされた `Makefile.in'を所有していて,両方のファイルを調査する直前に `Makefile.am'の変更を決定したと仮定します(変更に対応する `Makefile.in'をリビルドする前です).
この最後の`Makefile.am'の変更で,`Makefile.in'のコピーは古い
ものになっています.CVSはファイルをアルファベット順に処理するので,他
の開発者がツリー上でcvs update
するとき,`Makefile.in'が
`Makefile.am'より新しくなってしまいます.この開発者は,
`Makefile.in'が古いことが分からないでしょう.
CVSとmake
を平和に動作させる一つの方法は,生成されるファイルを
CVSに保存しないことで,すなわち,Makefile
のターゲット(派
生ファイルとも呼ばれます)をCVSの制御下におかないことです.
この方法では,開発者は生成されるファイルの変更で悩むことはありません. 全員が異なるバージョンを所有している場合は問題になります(もちろん互換 性があると仮定してもです).結局,タイムスタンプは失われ,ソースファイ ルへの変更は,これまでに議論してきた `Makefile.am'/`Makefile.in'の例のように失われてしまうはずで す.
欠点は,配布されるものの正確なコピーがCVSリポジトリに無いことと,チェッ クアウトしたものをビルド可能にする前に,様々な開発ツール(バージョンが 指定されるかもしれません)をユーザがインストールする必要があるというこ とです.しかし,結局は,CVSの仕事はバージョン管理であり,配布ではあり ません.
開発者が異なるバージョンのツールの使用を可能にすると,配布された開発物 のバグを隠すことにもなります.事実,開発者は,実際のリリースで生成され るファイルの代わりに,(テストであっても)自分が生成したファイルを使用し ます.tarballを準備している開発者は,使用しているツールのバージョンが 間違った出力を生成するものを使用している可能性があり(例えば,移植性の ないCファイル),他の開発者が,独自のバージョンのこのツールを使用してい ない場合,注意されることになるでしょう.
(タイムスタンプの問題が無いので)ここでは議論しませんが,それ以外に分類
されるファイルとして,パッケージとともに配布されるけれども,どこでも管
理されていないファイルがあります.例えば,gettextize
と
autopoint
(Gettext由来)や,libtoolize
(Libtool由来)
のようなツールは,パッケージにファイルをインストールしたり更新したりし
ます.
これらのファイルは,CVSに保持しようが保持しまいが,開発者のツール間の バージョンの違いについて,似たようなことが生じます.Gettextのマニュア ルにはこれに関するセクションがあります.section `Integrating with CVS' in GNU gettext toolsを参照して下さい.
missing
とAM_MAINTAINER_MODE
missing
missing
スクリプトは,いくつかの管理用ツールのラッパーで,要
求される管理用ツールを持っていないユーザのために設計されています.通常,
管理用ツールとは,autoconf
,automake
,
bison
等です.これらのツールで生成されるファイルは,パッケー
ジのその他のファイルとともに配布されるので,ユーザがビルドしたり,それ
らがconfigureで調査されている間は,これらのツールは要求されません.
しかし,理由があってリビルドのルールが開始され,足りないツールが呼び出
される場合,missing
はユーザに警告します.ツールが無いとき,
警告はされますが,ビルドの継続を可能にする方向で,missing
は
タイムスタンプを修正を試みます.例えば,autoconf
がインストー
ルされていない場合,missing
は`configure'を
touch
します.配布されるすべてのファイルがCVSに保持されている
場合,missing
のこの機能で,ユーザは管理用ツールが無く
ても,cvs update
で暗黙に指定されたタイムスタンプを回避して,
CVSからのパッケージをビルドすることが可能になります.
要求されるツールがインストールされている場合,missing
はそれ
を実行し,異常終了した後は継続しようとしません.これは開発時には正しい
もので,開発者は異常終了を修正したいものです.しかし,管理用ツールの違
うバージョンを持っているユーザは,リビルドルールが間違って開始されると
き,ビルドが終了しエラーになるかもしれません.ビルドの継続による異常終
了は,AM_MAINTAINER_MODE
で主張している論点の一つです.
AM_MAINTAINER_MODE
AM_MAINTAINER_MODE
は,"リビルドのルール"の呼び出しをデフォルト
で利用不可能にします.`configure.ac'にAM_MAINTAINER_MODE
が
あって,./configure && make
を実行する場合,make
は
`configure',`Makefile.in',LexやYaccの出力などのリビルドを*
決して*試みません.すなわち,一般的に配布されるが,通常ユーザが更新す
る必要が無いファイルに対するビルドルールを利用不可能にします.
./configure --enable-maintainer-mode
を実行する場合,これらのリ
ビルドルールが利用されるようになります.
ユーザ(や自分自身が)が失われたタイムスタンプ(see section 26.1 CVSと生成されるファイル)でうんざりし
たくないからとか,単純に,リビルドルールを使わないようにして管理用ツー
ルを明示的に実行したいから,といった理由でAM_MAINTAINER_MODE
を
使用します.
AM_MAINTAINER_MODE
では,条件的なカスタムビルドのルールも利用不
可能にすることが可能になります.ユーザが利用不可能なおそれのある外部ツー
ルのルールを利用不可能にするため,この機能を使用する管理者もいます.
数年前,François PinardはAM_MAINTAINER_MODE
にいくつかの引数
を付けるよう指示しました.それらのほとんどは不安定になり得ます.依存性
を削除することで,非依存のビルドにすることができます.ソースファイルを
変更することで,生成されるファイルに影響がなくなり,このことで,注意さ
れないときでも非常に混乱するはずです.彼は,安定は管理者に限定すべきで
はなく(--enable-maintainer-mode
で提案されたもの),反対だと付け
加えました.ユーザが`Makefile.am'を編集すると,`Makefile.in'
を更新する,または警告を出力すべきですが(これがAutomakeで
missing
を使用する理由です),最終的に望むことは,何も起こらず,
ユーザは注意もされないことです(これは,AM_MAINTAINER_MODE
でリビ
ルドのルールを利用不可能にすることです).
AM_MAINTAINER_MODE
マクロを開発したJim Meyeringは,François
との議論に動揺し,パッケージからAM_MAINTAINER_MODE
を取り除きま
した.
すべてのファイルをCVSに保持しているプロジェクトで作業する手助けとなり,
違うバージョンのツールを所有している場合はmissing
が十分では
ないので,今でも,AM_MAINTAINER_MODE
を使用し続けている人はたく
さんいます.
開発者は怠けものです.ファイルの追加,削除,または名前の変更のたびに, `Makefile.am'の更新を忘れないようにする必要がないよう, `Makefile.am'でワイルドカードを使用したいときもよくあります.
これにはいくつかの欠点があります.
cvs add
やcvs
rm
を実行する必要があることを,とにかく覚えておく必要があります.とい
うわけで,`Makefile.am'も反射的にすぐ行なうようになります.
逆に,アプリケーションが完全ではない場合,`Makefile.am'にファイル
を追加する必要があるので,それをcvs add
することを覚えておく手助
けになります.
make dist
で文句を言わ
れます.さらに,リストアップしている以上のファイルを配布することもあり
ません.
それらすべてを却下するほとワイルドカードに十分な価値があるという反対意 見があるかもしれませんが,まだ哲学的な欠点もあります.Automakeにワイル ドカードを伝えるためのパッチを書き始める前に,主な技術的な問題を見てい きましょう.それは移植性です.
$(wildcard ...)
はGNU make
で動作しますが,他の
make
の実装では移植性がありません.
Automakeで$(wildcard ...)
をサポートする唯一の方法は,
automake
の実行時に$(wildcard ...)
を展開することで
す.結果として得られる`Makefile.in'には,$(wildcard ...)
が
使用されておらず,すべてのファイルをリストアップしているので移植性があ
ります.しかしそれは,ファイルを追加,削除,または名前の変更をするたび
に,開発者がautomake
を実行する必要があるということを意味します.
`Makefile.am'を編集するより,実際は若干勝っています.確かに,
emacs Makefile.am; make
と入力するよりautomake; make
と入
力する方が簡単で速いでしょう.しかし,この構文のサポートを追加するのに
十分なパッチを書くことを邪魔する人はいません.`Makefile.am'や個別
の`Makefile'の断片にファイルリストを生成するスクリプトを使う人も
います.
移植性に気を付けていなくても,GNU Makeだけをターゲットにしていて,なん
とかして$(wildcard ...)
を使用したい場合でも,処理されるファイル
をAutomakeが正確に知っている必要がある場所がたくさんあることを知ってお
くべきです.Automakeは$(wildcard ...)
を展開する方法を知らないの
で,これらの場所で使用することは不可能です.$(wildcard ...)
は,
Automakeが尊重するAC_SUBST
されている変数と比べてブラックボック
スになります.
-Wportability
フラグを使用すると,$(wildcard ...)
の構成物
は警告されるはずです.
これは(Files left in build directory after distclean),make
distcheck
時に遭遇する可能性がある診断結果です.
14. 配布物に含まれるもので説明したように,make distcheck
では,このようなエラー
に対し,パッケージのビルドと調査を試みます.
make distcheck
は,パッケージのVPATH
のビルドを実行し,
make distclean
を呼び出します.make distclean
が実行された
後で,ビルドディレクトリに残っているファイルは,このエラーの後でリスト
アップされます.
この診断結果は,実際には二種類のエラーをカバーしています.
残っている前者のファイルは配布されないので,クリーンするよう (see section 13. クリーンされるもの)印が付いているものを修正します.これは明白で,文句を言 われても仕方がありません.
後者のバグは,理解し修正するのが常に容易だというわけではないので,例を
用いて説明します.パッケージにhelp2man
を使用してmanページを
ビルドしたいプログラムが含まれていると仮定します.GNU
help2man
は,コマンドの--help
と--version
の出力
から簡単なマニュアルページを生成します(see section `Overview' in The Help2man Manual).help2man
のインストールをユー
ザに強制したくないので,以下のような設定を使用して生成されたmanページ
を配布するように決めました.
# This Makefile.am is bogus. bin_PROGRAMS = foo foo_SOURCES = foo.c dist_man_MANS = foo.1 foo.1: foo$(EXEEXT) help2man --output=foo.1 ./foo$(EXEEXT) |
これで,manページを効果的に配布します.しかし,make distcheck
は
以下のように異常終了するでしょう.
ERROR: files left in build directory after distclean: ./foo.1 |
なぜ`foo.1'がリビルドされたのでしょうか?その理由は,配布はされな いものの,`foo.1'は配布されないファイル`foo$(EXEEXT)'に依存 しているためです.`foo$(EXEEXT)'はユーザがビルドするので,それは 配布されている`foo.1'より常に新しいものになります.
make distcheck
はパッケージ内の矛盾をとらえます.ユーザが
help2man
をインストールする必要が無いように,`foo.1'を配
布するのが目的でしたが,このルールで今ではファイルが常にリビルドされ,
ユーザはどうしてもhelp2man
が必要になります.
`foo.1'がユーザにリビルドされないことを確実にする,または
`foo.1'の配布を諦めるかのいずれかにすべきです.
より一般的には,配布されるファイルのルールには,配布されないビルドされ るファイルに決して依存しないようにすべきです.生成されたものを配布する 場合,そのソースを配布してください.
上記の例を修正する一つの方法として,配布される`foo.1'が
`foo$(EXEEXT)'に依存しないようにします.例えば,foo
--version
とfoo --help
が,`foo.c'や`configure.ac'
が変更されない限り変更されない状況では,以下のような`Makefile.am'
を書くことが可能です.
bin_PROGRAMS = foo foo_SOURCES = foo.c dist_man_MANS = foo.1 foo.1: foo.c $(top_srcdir)/configure.ac $(MAKE) $(AM_MAKEFLAGS) foo$(EXEEXT) help2man --output=foo.1 ./foo$(EXEEXT) |
この方法では,`foo.1'は`foo$(EXEEXT)'が変更されるたびにリビ
ルドされません.make
はhelp2man
の前に
`foo$(EXEEXT)'を確実に更新します.これを確実にするもう一つの方法
は,バイナリとmanページに対して別のディレクトリを使用し,
SUBDIRS
をmanページがビルドされる前にバイナリがビルドされるよう
に設定することです.
`foo.1'を配布しないように決定することも可能です.この状況では, `foo.1'が`foo$(EXEEXT)'に依存するようにすると両方ともリビル ドされるので優れています.しかし,`foo.1'のビルドで `foo$(EXEEXT)'を実行するので,クロスコンパイルでパッケージ をリビルドすることは不可能です.
そのようなエラーがあるもう一つの状況は,配布されるファイルがパッケージ でビル度されるツールを用いてビルドされるときです.パターンは似ています.
distributed-file: built-tools distributed-sources build-command |
以下のように変更すべきです.
distributed-file: distributed-sources $(MAKE) $(AM_MAKEFLAGS) built-tools build-command |
または,クロスコンパイルで問題になる場合は`distributed-file'を配 布しないように選択することも可能です.
これらの例に意味がある状況をまとめます.
絶望的な状況では,14. 配布物に含まれるもので説明したように,
distcleancheck_listfiles
を設定することで,この調査を利用不可能
にすることが可能です.こうする前に,make distcheck
が文句を言う
理由を必ず理解して下さい.distcleancheck_listfiles
はエラー
を隠す方法で,それを修正するものではありません.良いようにして下さい.
これは,ターゲットごとにコンパイルフラグが使用されているとき発生します. オブジェクトファイルは,同じソースから異なるフラグを用いてコンパイルさ れるオブジェクトが互いに壊されないように,名前を変更する必要があります. 以下の例を考えて下さい.
bin_PROGRAMS = true false true_SOURCES = generic.c true_CPPFLAGS = -DEXIT_CODE=0 false_SOURCES = generic.c false_CPPFLAGS = -DEXIT_CODE=1 |
-DEXIT_CODE=0
と-DEXIT_CODE=1
の両方を用いてコンパ
イルすることが不可能だからです.このため,automake
は二つの異
なるオブジェクト,`true-generic.o'と`false-generic.o'をビル
ドするルールを出力します.
automake
は,オブジェクトファイルの名前を変更する必要があるか
どうかを決定するため,実際にはソースファイルが共有されているかどうかを
見ていません.ターゲットごとのコンパイルフラグを使用していることが判明
したときに,すべてのターゲットのオブジェクトの名前を変更するだけです.
ターゲットごとのコンパイルフラグが使用されていないときは,オブジェクト ファイルを共有しても問題ありません.例えば以下の例のように, `true'と`false'が両方とも`version.o'を使用しているとき です.
AM_CPPFLAGS = -DVERSION=1.0 bin_PROGRAMS = true false true_SOURCES = true.c version.c false_SOURCES = false.c version.c |
オブジェクトファイルの名前の変更は,_SHORTNAME
変数にも影響され
ることに注意して下さい(see section 8.4 プログラムとライブラリの変数).
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |