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

5. Writing Tests

あなたの必要としている検査項目が既存のマクロで実現されていない場合、 自分であたらしいマクロを書かねばなりません。 以下のマクロは、マクロの基本部品です 以下のマクロは、他のマクロ内でOS/コンパイラの機能を検査したり、 結果を出力したりするのに使われています。

この章では、推奨されるマクロの書き方、 それから既存のマクロがどうして現在あるように記述されているのかについて 述べています。 既存のマクロがどのように書かれているのか見ることで、 どうやってAutoconfのマクロを記述すべきか学べるでしょう。 Autoconfのテストでなにかがうまくいかなかったら、 マクロがなにを仮定しているのか理解するのに この章の内容が役立つかもしれません。 マクロが仮定していることを理解すれば、 マクロの問題点をどう解くべきなのかを知るにも役立つでしょう (訳註: 相当意訳)。

以下のマクロは、Cコンパイラの出力を調べます。 以下のマクロは結果をキャッシュしません(see section 6.3 Caching Results)。 なぜなら、これらのマクロからは検査している内容がわからないし キャッシュ変数名も決められないからです。 Cコンパイラの特定の機能を調べるマクロは、結果をキャッシュしますし、 なにを調べているのかメッセージも出力されます。

複数のソフトウェアパッケージで利用できる検査を書いた場合、 新しいマクロを定義するのがよいでしょう。 どうやるかはSee section 7. Writing Macros参照。

5.1 Examining Declarations  Detecting header files and declarations.
5.2 Examining Syntax  Detecting language syntax features.
5.3 Examining Libraries  Detecting functions and global variables.
5.4 Checking Run Time Behavior  Testing for run-time features.
5.5 Portable Shell Programming  Shell script portability pitfalls.
5.6 Testing Values and Files  Checking strings and files.
5.7 Multiple Cases  Tests for several possible values.
5.8 Language Choice  Selecting which language to use for testing.


5.1 Examining Declarations

AC_TRY_CPPは特定のヘッダファイルが存在するか調べるためにあります。 ヘッダファイルひとつづつについて調べることもできますし、 ひとつの目的のために調べるのなら複数のヘッダファイルをまとめて 調べることもできます。

Macro: AC_TRY_CPP (includes, [action-if-true [, action-if-false]])
includesには CまたはC++の#include文(訳註: ほんとは文じゃないね)と 定義文(訳註: `#define'とか)を記述します。 他の文を記述しても構いませんが、多分意味ないでしょう。 includesのところにはshell変数、 backquote、backslashによる置換が働きます (訳註: 置換を避けたければ`['と`]'で囲め、ということです)。 プリプロセッサが処理中にエラーメッセージを出さなければ、 shellコマンドaction-if-trueが実行されます。 エラーがあればaction-if-falseが実行されます。

このマクロはCPPFLAGSを使いますが、CFLAGSは使いません。 `-g'とか`-O'は多くのCプリプロセッサで無効だからです。

次のマクロはヘッダファイルに特定の定義(typedef、構造体、構造体メンバ、 関数プロトタイプ)が入っているかどうか調べます。 ヘッダファイルを直接grepせずに、AC_EGREP_HEADERを使いましょう。 システムによっては、調べたいシンボルが、あなたがgrepしている ヘッダファイルから`#include'されている他のヘッダファイルで 定義されているかもしれません。

Macro: AC_EGREP_HEADER (pattern, header-file, action-if-found [, action-if-not-found])
header-fileをCプリプロセッサに通した結果がpatternと マッチすれば、action-if-foundを実行します。 マッチしなければ、action-if-not-foundを実行します。 patternegrepの正規表現です。

ヘッダファイルで定義されたり、Cプリプロセッサで前もって定義されている Cプリプロセッサシンボルを調べる場合、 AC_EGREP_CPPを使いましょう。 以下に例題があります:

 
AC_EGREP_CPP(yes,
[#ifdef _AIX
  yes
#endif
], is_aix=yes, is_aix=no)

Macro: AC_EGREP_CPP (pattern, program, [action-if-found [, action-if-not-found]])
programはCまたはC++のプログラムテキストです。 programのところにはshell変数、 backquote、backslashによる置換が働きます。 programをプリプロセッサに通した結果がpatternと マッチすれば、action-if-foundを実行します。 マッチしなければ、action-if-not-foundを実行します。 patternegrepの正規表現です。

このマクロは、もしまだ呼ばれていないなら、 AC_PROG_CPPまたはAC_PROG_CXXCPPを呼び出します。 どちらを呼ぶかはどちらの言語を選んでいるかに依存します (see section 5.8 Language Choice)。


5.2 Examining Syntax

「特定のキーワードを認識するかどうか」など、 C、C++ や Fortran 77コンパイラの文法的な機能を調べるためには、 AC_TRY_COMPILEを使ってそのキーワードや機能を使う小さなプログラムを コンパイルしてみましょう。 AC_TRY_COMPILEを使うと、特定のシステムにしかない 構造体や構造体メンバを調べることもできます。

Macro: AC_TRY_COMPILE (includes, function-body, [action-if-found [, action-if-not-found]])
このマクロは、

関数の中身がfunction-bodyの記述からなるようなテスト用のC、C++、 Fortran 77プログラム(現在選択されている言語に依存 see section 5.8 Language Choice)を書き出し、それがコンパイラでコンパイルできるかどうか調べます。

CとC++のため、includesfunction-bodyのコードが必要とする、 あらゆる#includeです(現在選択されている言語がFortran 77の場合は無 視されます)。このマクロは、現在選択されている言語がCやC++の場合、 CFLAGSCXXFLAGSも使用し、コンパイル時にはCPPFLAGS も使用します。Fortran 77が現在選択されている言語の場合、コンパイル時に FFLAGSを使用します。

もしコンパイルできたなら、shellコマンドaction-if-foundを実行します。 もしできなかったらaction-if-not-foundを実行します。

このマクロはリンクを行おうとはしません(コンパイルしかしません)。 テストのためにリンクもしたい場合、AC_TRY_LINKを使ってください (see section 5.3 Examining Libraries)。


5.3 Examining Libraries

ライブラリ、関数、またはグローバル変数を調べるために、 Autoconfの生成するconfigureスクリプトは、小さなプログラムを コンパイルしてリンクしてみます。 Metaconfigは(デフォルトでは)Cライブラリに対しnmarを 実行することで提供されている関数を調べますが、 AutoconfはMetaconfigとは違います。 実際に関数をリンクしてみる方が判定方法として確実です。 なぜなら、nmarのさまざまなオプションや出力形式、 それから標準ライブラリの置き場所に関する差異を取り扱わなくて済みます。 クロスコンパイルできるかどうかも調べられます。 それに、必要なら関数の実行時の挙動を調べることもできます。 そのかわりに、実際関数をリンクしてみるのは、 ライブラリを一度調べればいいnm式よりも遅いです。

ごく少数のシステムでは、リンク時に発見できない関数があってもリンカが 「失敗」とのexitステータスを変えしません。 このようなシステムでは、Autoconfで生成されたスクリプトが使えません。 ただし、このようなシステムの一部では、特定のコマンドラインオプションを 与えるとリンカが正しくexitステータスを返すようになります。 Autoconfは現在この問題を自動的に解決していません。 ユーザがこの問題にであった場合、環境変数LDFLAGSにリンカが必要とする オプションを設定して渡してやることで解決できるでしょう (例えばMIPS RISC/OSの場合`-Wl,-dn')。

関数とグローバル変数について調べるためには、AC_TRY_LINKを使って テストプログラムをコンパイルしてみます。 このマクロはライブラリの検査(see section 4.2 Library Files)のためにAC_CHECK_LIBの内部でも使われています。 このためには、LIBに調べたいライブラリ名を一時的に追加し、 テストプログラムをリンクしてみます。

Macro: AC_TRY_LINK (includes, function-body, [action-if-found [, action-if-not-found]])
このマクロは、 現在選択されている言語(see section 5.8 Language Choice)によって、関数の中身が function-bodyの記述からなるようなテスト用のCプログラムを書き出しま す。

CやC++では、includefunction-bodyのコードで必要となる任意の #include文です(現在選択されている言語がFortran 77の場合は無< 視さ れます)。もし現在選択されている言語がCやC++ならば、このマクロは CFLAGSCXXFLAGSも使用し、コンパイル時には、 CPPFLAGS も使用します。もしFortran 77が現在選択されている言語なら ば、コンパイル時にFFLAGSを使用します。しかし、LDFLAGSLIBSは、全ての場合でリンク時に使います。

もし成功したなら、shellコマンドaction-if-foundを実行します。 もしできなかったらaction-if-not-foundを実行します。

Macro: AC_TRY_LINK_FUNC (function, [action-if-found [, action-if-not-found]])
現在の言語に依存して(see section 5.8 Language Choice)、本体がプロトタイプからな り、functionの呼び出しを含むプログラムの、コンパイルとリンクが可能 かどうかを知るために、テストプログラムを作ります。

もし成功したなら、shellコマンドaction-if-foundを実行します。 もしできなかったらaction-if-not-foundを実行します。

Macro: AC_TRY_LINK_FUNC (function, [action-if-found [, action-if-not-found]])
functionをリンクする、小さなプログラムのコンパイルとリンクを試みま す。もしファイルのコンパイルとリンクが成功したならば、シェルコマンドの action-if-foundを実行し、それ以外ではaction-if-not-foundを実 行します。

Macro: AC_COMPILE_CHECK (echo-text, includes, function-body, action-if-found [, action-if-not-found])
これはAC_TRY_LINKに類似した、obsoleteなマクロです。 AC_COMPILE_CHECKは、echo-textが空でなければ、テストの前に `checking for echo-text'と標準出力に表示します。 テストの進行状況や結果を表示するには、 AC_MSG_CHECKINGAC_MSG_RESULTを使いましょう (see section 6.4 Printing Messages)。


5.4 Checking Run Time Behavior

システムの機能に癖やバグがある場合など、 システムが実行時にどう振舞うのか知らないといけないことがあります。 可能なら、コンパイル時でなしにパッケージの実行時に検査しましょう。 例えば、マシンのendianをプログラムの初期化時に調べることは可能です。

実行時のふるまいをどうしてもパッケージのコンパイル前に調べたい場合、 テストプログラムを書き、AC_TRY_RUNを使ってコンパイルして 実行し、結果を調べることができます。 可能な限りこの種のテストプログラムを使うことは避けましょう。 あなたのパッケージをクロスコンパイルできなくなります。

5.4.1 Running Test Programs  Running test programs.
5.4.2 Guidelines for Test Programs  General rules for writing test programs.
5.4.3 Test Functions  Avoiding pitfalls in test programs.


5.4.1 Running Test Programs

システムが実行時にどう振舞うのかをコンパイル時に調べるためには、 以下のマクロを使いましょう。

Macro: AC_TRY_RUN (program, [action-if-true [, action-if-false [, action-if-cross-compiling]]])
programにはCプログラムコードを指定します。 programに対してはshell変数やbackquoteによる置換が働きます。 programのコンパイルとリンクが成功し、 実行したときにexitステータス0が返ったら、 shellコマンドaction-if-trueを実行します。 さもなくば、action-if-falseを実行します。 このとき、プログラムのexitステータスはshell変数`$?'に入っています。 このマクロは CFLAGSCXXFLAGSCPPFLAGSLDFLAGS、それから LIBSを利用します。

(クロスコンパイルしている等の理由で)現在使っているCコンパイラが、 configureを実行しているシステムで動かないコードを出力する場合には、 テストプログラムは実行されません。 省略可能なshellコマンドaction-if-cross-compilingが指定された場合、 かわりにshellコマンドが実行されます。 action-if-cross-compilingが指定されていない場合にはconfigureは エラーメッセージを出力し終了します。

実行時の振舞いを調べられないクロスコンパイル時のために、 悲観的なデフォルト値を用意しておきましょう。 これは、 AC_TRY_RUNの最後の引数(action-if-cross-compiling)を 与えることで達成できます。 autoconfconfigureスクリプトを生成する際、 action-if-cross-compilingの指定のないAC_TRY_RUNがあるたび 警告を出します。 警告を無視しても構いませんが、その場合ユーザはあなたのパッケージを クロスコンパイルできなくなります。 Autoconfと一緒に配布されているマクロには、 このような警告を出すマクロがごく少数あります。

クロスコンパイルのためにパッケージを設定する場合、 正規化されたシステム名(see section 8. Manual Configuration)によって action-if-cross-compilingで決める値を変えることができます。 または、各ターゲットシステムにあわせた正しい値を書いた キャッシュファイルを置いておくこともできます(see section 6.3 Caching Results)。

AC_TRY_RUNは、Autoconf標準添付のマクロを含めて 他のマクロ内部から呼び出されることがあります。 このような場合に、クロスコンパイル時のためのデフォルト値を設定するためには、 AC_TRY_RUNより前にAC_PROG_CCを呼んでおくとよいでしょう。 AC_PROG_CCを呼んだあと、shell変数cross_compileが `yes'だったら、AC_TRY_RUNを呼ばず、 かわりの方法を使って設定結果の値を決めるのです。

Macro: AC_C_CROSS
このマクロはobsoleteです。 何もしません。


5.4.2 Guidelines for Test Programs

テストプログラムは標準出力になにも書き出してはいけません。 テストが成功したら0を、成功しなかったら0以外を返してexitすべきです。 これはテストの成功と、core dumpや他の理由によるテスト失敗とを 明確に区別するためです。 セグメンテーションフォールトやその他が起きたときにはexit statusは 0以外になります。 テストプログラムは関数mainからのreturnでなしに exitで終了すべきです。 一部のシステム(少なくとも古いSun)では関数mainの返り値は無視されます。

テストプログラムは#if#ifdefを使って、 既に実行された他のテストで定義されたプリプロセッサマクロを参照できます。 例えば、AC_HEADER_STDCを呼び出したら、 以後`configure.in'の中で記述するテストプログラムでANSI Cヘッダファイルを #includeすることができます:

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

テストプログラムがデータファイルを使ったり作ったりしないといけない場合、 `conftest'で始まるファイル名、例えば`conftestdata'を使いましょう。 configureスクリプトは、外部のテストプログラムが終了したときや スクリプトが中断されたときに、`rm -rf conftest*'を実行して データファイルを消去します。


5.4.3 Test Functions

テストプログラム中の関数定義をするときは、 C処理系の場合とC++処理系の場合とを条件分けして定義しなければなりません。 実際のところは、テストプログラム中で引数をとる関数を 使うことはめったにありません。

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

プロトタイプ宣言についても同様に条件分けしなければなりません。 C++処理系はC linkageの関数プロトタイプの前に`extern "C"'が必要だからです (訳註: ちょと補足)。 `extern "C"'が入っていないようなヘッダファイルを #includeしないように注意してください。

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

テストプログラム中で、(単に関数があるかないか調べるために) 不正な引数を使って関数を呼び出す場合、 間違って関数が呼び出されないように注意してプログラムを記述してください。 これは、目的の関数を、絶対呼び出されない関数fooの中から 呼び出すよう記述することで実現できます。 exitの後で目的の関数を呼び出すのではテストになりません。 GCCバージョン2は関数exitのあと処理が戻らないことを知っていて、 exitと同じブロックの以後の部分をコンパイルしない最適化を するからです。

ヘッダファイルを#includeして、その中でプロトタイプ宣言されている 関数を呼び出す場合、 プロトタイプ宣言違反でコンパイルエラーが発生しないよう、 (引数が単に0であっても)引数の個数は定義どおりにしてください。 GCCバージョン2では、インライン展開される一部の関数(memcpyとか)について コンパイラ内部でプロトタイプ宣言を持っています。 このような関数の有無をチェックする場合、 正しい個数の引数を渡すか、charなどに返り値を変えて再定義してください (訳註: 返り値の宣言変えて意味あるのか?)。


5.5 Portable Shell Programming

自分でテストマクロを記述する場合、 shellスクリプトの移植性を高く保つためにいくつかの記法を使わないように しないといけません。 Bourne shellと(BashやKorn shell等の)上位互換のshellは 長年発達してきましたが、トラブルを避けるため、 1977年ごろのUNIX version 7以降に追加された機能は使わないようにしてください。 shellスクリプト内関数、alias、character classの反転 (訳註: 「negated character classes」)、それから 必ずしも全てのBourne shell互換shellに入っていない機能は使うべきではありません。 最小公約数的なスクリプトを書くように心がけてください。 一部のshellではunsetすら使えません! スクリプトインタプリタを指定するための#!の後には、 以下のようにスペースをつけてください:

 
#! /usr/bin/perl
パス名の前のスペースがないと、 4.2BSD互換のシステム(Sequent DYNIXとか)では行は無視されます。 `#! /'を4バイトのmagic nubmerとして解釈しているためです。

configureスクリプトからは、ごく少数の外部プログラムしか 呼び出してはいけません。 呼び出していいプログラムのリストは See section `Utilities in Makefiles' in GNU Coding Standardsにあります。 この制限により、プログラム間の依存関係を最小限にとどめ、 ユーザがパッケージをインストールするために 前もって用意しないといけないプログラムを最小限に抑えることができます。

呼び出していい外部プログラムのリストに載っているプログラムについても、 最低限の共通な機能だけを使いましょう(訳註: すごく意訳)。 例えば、lnが`-f'をサポートしているとか catにコマンドラインオプションがあるとか仮定してはいけません。 sedスクリプト内には、コメントや8文字以上のラベルがあってはいけません。 `grep -s'で出力を抑制しようとしてはいけません。 System Vでは`grep -s'は出力を抑制せず、エラーメッセージだけ 抑制するからです。 かわりに、grepの標準出力と標準エラー出力の両方を`/dev/null'に リダイレクトしましょう (標準エラー出力もリダイレクトするのは、エラー発生時に出力を出さないように するためです)。 grepのexitステータスで、matchする文字列がみつかったかどうか 確認しましょう。


5.6 Testing Values and Files

configureスクリプトは多くのファイルや文字列の特性を検査する必要が あります。ここではそれら検査を行うときに用心するいくつかの移植性の問題を あげます。

testプログラムは多くのファイルや文字列をテストする手段です。それ はしばしば別の名前`['で実行されます。しかしAutoconfコードの中でその 名前を使うことはそれがm4のクォート文字の1つであるので災いを招きま す。

testを使った多重検査が必要なら、testプログラムの演算子 `-a'と`-o'の代わりに、シェル演算子`&&'と`||'で組み合 わせてください。System V では`-a'と`-o'の優先順位が単項演算子 に関連して間違っています。したがってPOSIXはそれらを記していません。 だからそれらを使うことは移植性を損ないます。 もしあなたが`&&'と`||'を同じ文で組み合わせるなら、それらが 同じ優先順位を持つことを覚えておいてください。

configureスクリプトがクロスコンパイルをサポートできるようにするに は、ターゲットシステムの代わりにホストシステムの特性を検査するべきではあ りません。しかし、時々あなたはいくつかの恣意的なファイルが存在するかどう かを検査する必要を見つけるかも知れません。そうするには`test -f' や `test -r'を使います。`test -x'を使っては行けません。なぜなら 4.3BSDそれを持たないので。

別の移植性を損なうシェルプログラミング構文は以下です。

 
var=${var:-value}
その意味はまだ値が設定されていないときにだけvarvalueを設定 し、varがなにか値を持っていれば、空文字列でさえ、そのままにしてお きます。古いBSDのシェル、Ultrix shを含みます、は、コロンを受け付けず、 不平を言って終了します。移植性のある同等なものは以下です。
 
: ${var=value}


5.7 Multiple Cases

Some operations are accomplished in several possible ways, depending on the UNIX variant. Checking for them essentially requires a "case statement". Autoconf does not directly provide one; however, it is easy to simulate by using a shell variable to keep track of whether a way to perform the operation has been found yet.

UNIXの種類に依存して、いくつかの処理は可能な方法で達成されます。本質的に それを調べるためには、"case文"が必要です。Autoconfは直接それを供給しま せん。しかし、実行する処理が見つかったかどうかの追跡を記録するため、シェ ル変数を使って簡単にシミュレーションができます。

ここに、調べる必要があるもののまだ残っているcaseの追跡を記録するため、シェ ル変数fstypeを使用する例があります。

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


5.8 Language Choice

CとC++の両方を使うパッケージは、両方のコンパイラの特徴をテストする必要が あります。Autoconfが生成したconfigureスクリプトは、デフォルトでC の特徴を調べます。以下のマクロは`configure.in'のテストで、使ってい る言語のコンパイラを決定します。

Macro: AC_LANG_C
CCCPPを使うコンパイルテストを行い、拡張子が`.c'のテ ストプログラムを使います。もし実行されたならば、AC_PROG_CCが求め た値をシェル変数cross_compilingに、それ以外では空に設定します。

Macro: AC_LANG_CPLUSPLUS
CXXCXXCPPを使うコンパイルテストを行い、拡張子が`.C' のテストプログラムを使います。もし実行されたならば、AC_PROG_CC が 求めた値をシェル変数cross_compilingに、それ以外では空に設定します。

Macro: AC_LANG_FORTRAN77
Do compilation tests using F77 and use extension `.f' for test programs. Set the shell variable cross_compiling to the value computed by AC_PROG_F77 if it has been run, empty otherwise.

F77を使うコンパイルテストを行い、拡張子が`.f'のテストプログ ラムを使います。もし実行されたならば、AC_PROG_CCが求めた値をシェ ル変数cross_compilingに、それ以外では空に設定します。

Macro: AC_LANG_SAVE
(AC_LANG_CAC_LANG_CPLUSPLUSAC_LANG_FORTRAN77が 設定するように)現在の言語をスタックに覚えさせます。現在の言語を変更しま せん。このマクロとAC_LANG_RESTOREは、特定の言語を一時的に切替える 必要があるマクロで使ってください。

Macro: AC_LANG_RESTORE
AC_LANG_SAVEが設定するように、スタックのトップに保存されている言 語を選択し、スタックから削除します。このマクロは、AC_LANG_SAVEが 最後に呼ばれた時、最も最近実行されたAC_LANG_CAC_LANG_CPLUSPLUSAC_LANG_FORTRAN77と同じです。

このマクロをAC_LANG_SAVEより多くの回数、呼び出さないでください。

Macro: AC_REQUIRE_CPP
現在、テストに使われるプリプロセッサの存在を保証します。 AC_PROG_CPPAC_PROG_CXXCPPの引数で、現在の言語に依存して、 AC_REQUIRE(see section 7.4.1 Prerequisite Macros)を呼び出してください。


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

This document was generated by Akihiro Sagawa on January, 21 2003 using texi2html