[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

6. テストを書く

既存の特徴テストでは必要なことができない場合,新しいものを書く必要があり ます.これらのマクロはブロックの組み立てです.他のマクロで様々な特徴が利 用可能かどうか調査し結果を報告するための方法を提供します.

この章には,提案と,既存のテストが書かれている方法の理由も含まれています. また,既存のものを見ることで,Autoconfテストの書き方について知ることが可 能です.Autoconfのテストの一つ以上がうまくいかない場合,この情報は背後で 行われていることの理解を助けるので,最善の問題解決法が分かるでしょう.

以下のマクロは,現在の言語のコンパイラシステムの出力を調査します (see section 言語の選択).それらは,キャッシュ変数名を生成するために調 査している情報を十分には知らないので,将来使用するためにテスト結果をキャッ シュしません(see section 結果のキャッシュ).同じ理由でメッセージも出力しませ ん.特定の種類の機能の調査では,これらのマクロを呼び出し,結果をキャッシュ し,そして調査していることに関するメッセージを出力します.

一つ以上のソフトウェアパッケージに適用可能な特徴テストを書いているとき, 新しいマクロに要約することがベストです.その方法は,See section Autoconfマクロを書く.


6.1 言語の選択

Autoconfが生成したconfigureスクリプトは,Cコンパイラとその特徴 をデフォルトで調査します.他のプログラム言語を使用するパッケージ(一つ以 上で,例えば,CとC++)は,それぞれの言語のコンパイラの特徴をテストする必 要があります.以下のマクロは`configure.ac'内のそれ以降のテストで使 用されるプログラミング言語のコンパイラを決定します.

Macro: AC_LANG (language)

languageで指定されている,コンパイラ,プリプロセッサ,そしてファイ ル拡張子をコンパイルテストで使用します.

サポートされている言語は以下のとおりです.

` C'

CCCPPを使用してコンパイルテストを行ない,テストプログラ ムでは`.c'の拡張子を使用します.コンパイルフラグを使用します. CPPではCPPFLAGSCCではCPPFLAGSCFLAGSの両方を使用します.

` C++'

CXXCXXCPPを使用してコンパイルテストを行ない,テストプロ グラムでは`.C'の拡張子を使用します.コンパイルフラグを使用します. CXXPPではCPPFLAGSCXXではCPPFLAGSCXXFLAGSの両方を使用します.

` Fortran 77'

F77を使用してコンパイルテストを行ない,テストプログラムでは `.f'の拡張子を使用します.コンパイルフラグを使用します. FFLAGSです.

` Fortran'

FCを使用してコンパイルテストを行ない,テストプログラムでは `.f'の拡張子(またはAC_FC_SRCEXTで設定されているもの)を使用し ます.コンパイルフラグを使用します.FCFLAGSです.

Macro: AC_LANG_PUSH (language)

現在の言語を(AC_LANGに設定するように)スタックに記録してから, languageを選択します.このマクロとAC_LANG_POPを,一時的に特 定の言語に切替える必要があるマクロで使用してください.

Macro: AC_LANG_POP ([language])

AC_LANG_PUSHで設定するように,スタックのトップに保存されている言 語に選択し,スタックからそれを削除します.

language与えられている場合,それは言語をそのまま指定します. 分かっているときは,Autoconfが間違いを検出するので(case…にすべきで すが),それを指定することは良い考えです.

 
AC_LANG_PUSH(Fortran 77)
# Perform some tests on Fortran 77.
# …
AC_LANG_POP(Fortran 77)
Macro: AC_LANG_ASSERT (language)

現在の言語がlanguageであることを十分に調査します.言語指定のマクロ で不適切な言語での呼び出しを避けるため使用すべきです.

このマクロは,autoconf時のみで実行され,configure時 に時間がかかることはありません.残念ながら,Autoconfは二つのレイヤーの言 語があるため(2),マクロのAC_LANG_PUSH/AC_LANG_POP は"最適化" されず,そのため,できるだけコードのラッパーを行なうために それらを使用することを避け,代わりに,ユーザがマクロを現在の言語で実行す ることを要求し,AC_LANG_ASSERTで調査するようにして下さい.いずれ にせよ,Fortran 77コンパイラの結果を期待している,ユーザが実行している Fortranマクロを理解する助けとなるでしょう....

Macro: AC_REQUIRE_CPP

現在のテストに使用されるプリプロセッサが見つかることを保証します.現在の 言語に依存して,AC_PROG_CPPまたはAC_PROG_CXXCPPのいずれか の引数を用いて,AC_REQUIRE(see section マクロの必要条件)を呼び出し てください.


6.2 テストプログラムを書く

Autoconfのテストの流れは,共通の手法です.いくつかの入力をいくつかのプロ グラムに与え,ほとんどの場合,ソースファイルをコンパイラに与えます.この セクションでは,これらのソースのサンプルを提供します.


6.2.1 テストプログラムのためのガイドライン

テストサンプルを書くときに従うべきもっとも重要な規則は以下のとおりです.

現実を見つめる.

このモットーは,テストサンプルが現実にかかれるプログラムと同じ厳密さで書 く必要があるということです.特に,"ショートカット"と単純にしたものは避 けるべきです.

コンパイルの準備をしたい場合,プリプロセッサだけで実行しないでください. 例えば,ヘッダが機能することを調査するためにcppを使用するだけ では,configureコンパイラのエラーを生じるヘッダを受け 入れるかもしれません.以前にインクルードした他のヘッダ,特に必要とされる ヘッダを用いたヘッダの調査をためらわないでください.

使用しているシンボルが,適切に定義されている,すなわち適切なヘッダをイン クルードする代わりに,自分で関数を単純に定義していないことを確かめてくだ さい.

テストプログラムは,標準出力に何かを書き出すべきではありません.コアダン プや他の異常終了と簡単に区別できるように,成功した場合は0,それ以外では ゼロ以外を返すべきです.セグメンテーション違反やその他の異常終了は,終了 ステータスでゼロ以外を生成します.main内のreturnの引数を無 視するシステム(少なくとも古いSun)もあるので,テストプログラムの mainではreturnではなくexitを使用するべきです.

既に実行されたテストで定義されたプリプロセッサの値を調査するため,テスト プログラムで#if#ifdefを使用することが可能です.例えば, AC_HEADER_STDCを呼び出す場合,`configure.ac'の後の方で,条件 付でANSI Cヘッダファイルをインクルードするテストプログラムを使用すること が可能です.

 
#if STDC_HEADERS
# include <stdlib.h>
#endif

テストプログラムでデータファイルを使用したり,作成したりする必要がある場 合, `conftest.data'のような,`conftest'で始まる名前を与えてく ださい.configureスクリプトは,テストプログラム終了後やスクリ プトが中断された場合,`rm -rf conftest*'を実行しクリーンアップしま す.


6.2.2 関数のテスト

テストプログラムでの関数宣言には,C++に対する条件付のプロトタイプを持た せるべきです.しかし,テストプログラムで引数をとる関数が必要になることは, 実際には滅多にありません.

 
#ifdef __cplusplus
foo (int i)
#else
foo (i) int i;
#endif

テストプログラムが宣言する関数には,`extern "C"'プロトタイプを要求 するC++に対する条件付けも行なうべきです.壊れたプロトタイプを含んでいる ヘッダファイルをインクルードしていないことを確かめてください.

 
#ifdef __cplusplus
extern "C" void *malloc (size_t);
#else
void *malloc ();
#endif

テストプログラムが(その存在の確認のためにだけ)無効なパラメータで関数を呼 び出す場合,その関数を決して呼び出さないことを保証するようにプログラムを 構成してください.決して呼び出されないそれ以外の他の関数から関数を呼び出 すことで,こうすることが可能です.GCCバージョン2は,exit は値を返 さず,同じブロックにあるそれ以降のコードを最適化で外してしまうことが知ら れているので,exitの呼び出し以降にそれを書き込まないでください.

ヘッダファイルをインクルードする場合は,たとえ引数が0だけであっても,プ ロトタイプで生じるコンパイルエラーを避けるため,正しい数の引数を適切にし て関数を呼び出していることを確認してください.GCCのバージョン2は,自動的 にインライン化される関数プロトタイプ,例えばmemcpyもあります.そ れらを調査しているときのエラーを避けるため,正しい数の引数を与えるか, (charのような)異なる戻り値で再定義してください.


6.2.3 ソースの生成

Autoconfは,テストソースファイルを生成するために使用することが可能なマク ロの組みを提供しています.それらは,一般的な言語で書かれていて,すなわち, それらは実際に現在の言語(see section 言語の選択)に依存して適切な出力 "フォーマット"になっています.

Macro: AC_LANG_CONFTEST (source)

現在のテストソースファイルにsourceのテキストを保存します. `conftest.extension'のextensionは現在の言語に依存します.

通常のAutoconfマクロ引数のように,sourceは一度だけ評価され,そのた め,(i)マクロ呼び出しに渡してもかまわず,(ii)そうでなければ,必要があれ ば二重に引用符で囲む必要があることに注意してください.

Macro: AC_LANG_SOURCE (source)

すべてのAC_DEFINEで実行されるこれまでの定義を用いて,source に展開します.

例えば,以下を実行します(二重の引用符を守ってください!).

 
AC_INIT(Autoconf Documentation, 2.59, bug-autoconf@gnu.org)
AC_DEFINE([HELLO_WORLD], ["Hello, World\n"])
AC_LANG_CONFTEST(
   [AC_LANG_SOURCE([[const char hw[] = "Hello, World\n";]])])
gcc -E -dD conftest.c -o -

結果は以下のようになります.

 
# 1 "conftest.c"
# 1169 "configure"

# 1 "confdefs.h" 1

#define PACKAGE_NAME "Autoconf Documentation"
#define PACKAGE_TARNAME "autoconf-documentation"
#define PACKAGE_VERSION "2.59"
#define PACKAGE_STRING "Autoconf Documentation 2.59"
#define PACKAGE_BUGREPORT "bug-autoconf@gnu.org"
#define HELLO_WORLD "Hello, World\n"
# 1170 "configure" 2

const char hw[] = "Hello, World\n";
Macro: AC_LANG_PROGRAM (prologue, body)

prologueの内容と,bodyをmain関数(例えばCのmain)として ソースファイルに展開します.それはAC_LANG_SOURCEを使用するので, 後者の機能は利用可能です.

例えば以下のようにします.

 
AC_INIT(Autoconf Documentation, 2.59, bug-autoconf@gnu.org)
AC_DEFINE([HELLO_WORLD], ["Hello, World\n"])
AC_LANG_CONFTEST(
[AC_LANG_PROGRAM([[const char hw[] = "Hello, World\n";]],
                 [[fputs (hw, stdout);]])])
gcc -E -dD conftest.c -o -

結果は以下のようになります.

 
# 1 "conftest.c"
# 1169 "configure"

# 1 "confdefs.h" 1

#define PACKAGE_NAME "Autoconf Documentation"
#define PACKAGE_TARNAME "autoconf-documentation"
#define PACKAGE_VERSION "2.59"
#define PACKAGE_STRING "Autoconf Documentation 2.59"
#define PACKAGE_BUGREPORT "bug-autoconf@gnu.org"
#define HELLO_WORLD "Hello, World\n"
# 1170 "configure" 2

const char hw[] = "Hello, World\n";
int
main ()
{
fputs (hw, stdout);
  ;
  return 0;
}
Macro: AC_LANG_CALL (prologue, function)

prologueの内容と,functionの呼び出しをmain関数(例えばCの main)の本体としてソースファイルに展開します.それは AC_LANG_SOURCEを使用するので,後者の機能は利用可能です.

この関数は,おそらく将来の引数指定が利用可能なバージョンで置換されます. このマクロは特定のシステムをひどく侵害するので,その使用は推奨しません.

Macro: AC_LANG_FUNC_LINK_TRY (function)

main関数(例えばCではmain)の本体として,偽のfunctionを使用し ている内容をソースファイルに展開します.単純な(関数ポインタの)割当です. それはAC_LANG_SOURCEを使用するので,後者の機能は利用可能です.

AC_LANG_CALLがあるので,このマクロは,補完の意味で説明しています. ひどく壊れていて,(適切な型の引数を用いた)実際の関数の呼び出しに将来は変 更しようと考えています.


6.3 プリプロセッサの実行

いくつかのソースファイルでプリプロセッサを実行する必要があるときもありま す.通常はプロジェクトをコンパイルする必要があり,プリプロセッサ を実行する必要があることは滅多に無いので,そうすることは,普通は悪 い考えです.そのため,きっとプリプロセッサではなくコンパイラを実行した いと思うでしょう.安易な道をたどる誘惑に逆らってください.

それにもかかわらず,プリプロセッサを実行する必要がある場合, AC_PREPROC_IFELSEを使用してください.

Macro: AC_PREPROC_IFELSE (input, [action-if-true], [action-if-false])

inputで現在の言語(see section 言語の選択)のプリプロセッサを実行し, 成功したらシェルコマンドaction-if-trueを実行し,そうでなければ action-if-falseを実行します.inputAC_LANG_PROGRAMと その仲間で作成することが可能です.

このマクロはCPPFLAGSを使用しますが,`-g',`-O'など は多くのCプリプロセッサで有効なオプションではないので,CFLAGS は 使用しません.

予期せぬ異常終了は,通常AC_MSG_FAILUREで報告します.

例えば以下のようにします.

 
AC_INIT(Autoconf Documentation, 2.59, bug-autoconf@gnu.org)
AC_DEFINE([HELLO_WORLD], ["Hello, World\n"])
AC_PREPROC_IFELSE(
   [AC_LANG_PROGRAM([[const char hw[] = "Hello, World\n";]],
                    [[fputs (hw, stdout);]])],
   [AC_MSG_RESULT([OK])],
   [AC_MSG_FAILURE([unexpected preprocessor failure])])

結果は以下のようになります.

 
checking for gcc... gcc
checking for C compiler default output... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking how to run the C preprocessor... gcc -E
OK

マクロAC_TRY_CPP(see section 時代遅れのマクロ)は, AC_PREPROC_IFELSEの役目を果たすために使用されていましたが,その引 数を二重の引用符で囲んでいるので,精巧なソースで使用することが不可能でし た.マクロAC_TRY_CPPAC_PREPROC_IFELSEをような古い使い方 を取り除くことも推奨しますが,最初にコンパイラではなくプリプロセッ サを実行する必要があるのかを確かめることを推奨します.

Macro: AC_EGREP_HEADER (pattern, header-file, action-if-found, [action-if-not-found])

システムヘッダファイルheader-fileでのプリプロセッサの実行での出力 が拡張正規表現のpatternにマッチする場合,シェルコマンド action-if-foundを実行し,それ以外ではaction-if-not-foundを実 行します.

Macro: AC_EGREP_CPP (pattern, program, [action-if-found], [action-if-not-found])

programがCやC++プログラムのテキストで,そのなかではシェル変数,バッ ククオート,そしてバックスラッシュの代入が実行されたものになっています. programでのプリプロセッサの実行での出力が拡張正規表現の patternにマッチする場合,シェルコマンドaction-if-foundを実行 し,それ以外ではaction-if-not-foundを実行します.


6.4 コンパイラの実行

特定のキーワードを認識するかどうかといった,現在の言語のコンパイラの構文 の特徴を調査するため,また,単純にいくつかのライブラリの特徴を試すため, それらの特徴を使用している小さなプログラムのコンパイルを試みる AC_COMPILE_IFELSEを使用してください.

Macro: AC_COMPILE_IFELSE (input, [action-if-found], [action-if-not-found])

現在の言語(see section 言語の選択)のコンパイラとコンパイラフラグを inputで実行し,成功したらシェルコマンドaction-if-trueを,そ れ以外ではaction-if-falseを実行します.inputAC_LANG_PROGRAMやその仲間で作成することが可能です.

慣習的に,予期せぬ異常終了はAC_MSG_FAILUREで報告します.このマク ロはリンクを試みません.そうする必要がある場合,AC_LINK_IFELSEを 使用してください(see section リンカの実行).


6.5 リンカの実行

ライブラリ,関数,またはグローバル変数を調査するため,Autoconfの configureスクリプトは,それを使用している小さなプログラムのコ ンパイルとリンクを試みます.これはMetaconfigとは異なり,それはデフォルト で,C ライブラリで関数が利用可能かどうか判定するためにnmarを使用します.オプションとnmarの出力の違いと, 標準ライブラリの位置の違いを処理することを避けるので,関数とのリンクを試 みることは,通常,より信頼性が高い方法になります.クロスコンパイルのコン フィグレーションや,必要な場合は関数の実行時の動作を調査も可能です.一方, 一度のライブラリスキャンより遅くなるはずですが,正確さは時間より重要です.

AC_LINK_IFELSEは,関数とグローバル変数に対するテストのため,テス トプログラムをコンパイルするために使用されます.ライブラリを調査する AC_CHECK_LIBでも,調査しているライブラリを一時的にLIBSに追 加したり,小さなプログラムのリンクを試みたりすることで,使用されています (see section ライブラリファイル).

Macro: AC_LINK_IFELSE (input, [action-if-found], [action-if-not-found])

現在の言語(see section 言語の選択)のコンパイラ(とコンパイラフラグ)とリ ンカをinputで実行し,成功したらシェルコマンドの action-if-trueを,それ以外ではaction-if-falseを実行します. inputAC_LANG_PROGRAMやその仲間で作成することが可能です.

リンク時には,現在のコンパイラフラグに加えて,LDFLAGSLIBSも使用されます.

慣習的に,予期せぬ異常終了はAC_MSG_FAILUREで報告します.このマク ロはリンクを試みません.そうする必要がある場合,AC_RUN_IFELSEを使 用してください(see section 実行時の動作の調査).


6.6 実行時の動作の調査

当該関数に特定の能力やバグがあるかどうかといった,実行時にシステムがどの ような動作をするか調べる必要があることもあります.可能であれば,コンフィ グレーション時ではなくプログラムを実行するときそのような調査をしてくださ い.マシンのエンディアンのようなものは,プログラムの初期化時に調査するこ とが可能です.

コンフィグレーション時に実行時の動作を調査する必要が本当にある場合,結果 を決定するテストプログラムを書き,コンパイルしてAC_RUN_IFELSE を 使用して実行することも可能です.これは,クロスコンパイルでパッケージをコ ンフィグレーションする人々の妨げになるので,可能であれば,テストプログラ ムの実行は避けてください.

Macro: AC_RUN_IFELSE (input, [action-if-found], [action-if-not-found], [action-if-cross-compiling])

programのコンパイルとリンクが正常終了し,実行時に0の終了ステータス が返る場合,シェルコマンドaction-if-trueを実行します.それ以外では, シェルコマンドaction-if-falseを実行します.

inputは,AC_LANG_PROGRAMとその仲間で作成することが可能です. 現在の言語(see section 言語の選択)のコンパイラフラグに加えて,リンク時 にはLDFLAGSLIBSも使用します.

使用されるコンパイラが,configureが実行されているシステムで実 行する実行形式を生成しない場合,テストプログラムは実行されません.オプショ ンのシェルコマンドaction-if-cross-compilingが与えられている場合, それらが変わりに実行されます.それ以外の場合,configureはエラー メッセージを出力し終了します.

action-if-falseセクションでは,プログラムの終了ステータスはシェル 変数`$?'で利用可能ですが,127未満の正の値に制限するよう十分注意して ください.大きな値は,programでファイルに保存すべきです.また,こ の終了ステータスがprogramで,またはそのコンパイルの異常終了で,生 成されることを保証されていないことに注意してください.言い替えると,苛め られるのが好きな人だけこの機能を使用してください.それは,Autoconfの管理 者が飽き飽きするほど"バグの報告"を受けとることになったので,元に戻しま した.

慣習的に,予期せぬ異常終了はAC_MSG_FAILUREで報告します.

クロスコンパイルで実行時のテストが不可能な時は,使用する悲観的なデフォル ト値を提供してみてください.オプションの最後の引数をAC_RUN_IFELSE に渡すことでこうします.autoconfは, action-if-cross-compiling引数無しでAC_RUN_IFELSEを呼び出す ごとに,configureを生成するときに警告メッセージを出力します. 警告を無視してもかまいませんが,ユーザはクロスコンパイルでパッケージのコ ンフィグレーションが不可能になります.Autoconfで配布されるマクロには,こ の警告メッセージを生成するものもあります.

クロスコンパイルでコンフィグレーションするため,これらのパラメータの値を 標準的なシステム名を基に選択することも可能です(see section 手動のコンフィグレーション).または,テスト結果のキャッシュファイルをホストシステム に対する正しい値で設定してください(see section 結果のキャッシュ).

Autoconfとともに含まれている他のマクロに埋め込まれている, AC_RUN_IFELSEの呼び出しに対するデフォルトを提供するため,シェル変 数cross_compilingが`yes'に設定されているかどうかを調査し,マ クロ呼び出しの代わりに結果を取得するため,代わりの手法を使用してください.


6.7 システム

このセクションは,ドキュメントへのシステムとポインタを紹介することを目的 としています.ユーザが報告する特定の問題を解決するとき役に立つでしょう.

Rosetta Stone for Unixには,様々な Unixの興味深い相互的な情報が大量にあります.

Darwin

DarwinはMac OS Xとしても知られています.ファイルシステムで大文字小文字の 違いを保存することが可能ですが,大文字小文字の区別をしないことに 注意してください.例えば,`INSTALL'ファイルがあるパッケージでインス トールを試みるとき,`make install'で「何もすることが無い!」のよう な結果が得られ,これは厄介な問題になります.

それは,ファイルシステムがUFS(大文字小文字を区別する)かHFS+(大文字小文字 の違いを保存する)かに依存します.デフォルトで,AppleはHFS+にOSをインストー ルして欲しがっています.残念ながら,本当にUFSでビルドする必要があるソフ トウェアもあります.DarwinをUFSとHFS+の両方で利用可能なように再構築して (そして/local/buildのツリーに配置して)欲しいと思います.

QNX 4.25

QNXは,小さな組み込みシステムから百個のプロセッサを持つスーパー コンピュータまで幅広く利用できる,Intelアーキテクチャでまで動作するリア ルタイムオペレーティングシステムです.それはPOSIXであることが 証明されていると主張しています.QNX home page で,より多くの情報が利用可能で,そこには, QNX man pagesもあります.

Tru64

documentation of several versions of Tru64では,様々な書式が利用可能で す.

Unix version 7

V7 Manualでドキュ メントが利用可能です.


6.8 複数のケース文

処理によっては,それぞれ異なるUNIXに依存して,考えられるいくつかの 方法で達成されるものもあります.それを本質的に調査するためには,"case 文"が必要です.Autoconfは直接それを提供していません.しかし,実行する処 理が見つかったかどうかの追跡を続けるため,シェル変数を使用することで簡単 にシミュレート可能です.

残っているcaseを調査する必要があるかどうかに関係なく追跡を続けるために, シェル変数fstypeを使用する例は,以下のようになります.

 
AC_MSG_CHECKING([how to get file system type])
fstype=no
# The order of these tests is important.
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/statvfs.h>
#include <sys/fstyp.h>]])],
                  [AC_DEFINE(FSTYPE_STATVFS) fstype=SVR4])
if test $fstype = no; then
  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/statfs.h>
#include <sys/fstyp.h>]])],
                  [AC_DEFINE(FSTYPE_USG_STATFS) fstype=SVR3])
fi
if test $fstype = no; then
  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/statfs.h>
#include <sys/vmount.h>]])]),
                  [AC_DEFINE(FSTYPE_AIX_STATFS) fstype=AIX])
fi
# (more cases omitted here)
AC_MSG_RESULT([$fstype])

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Akihiro Sagawa on June, 15 2005 using texi2html 1.70.