有时候,你需要知道系统在运行时作了些什么,比如说某个给定的函数是否具备某种能力或者是否含有错误。如果你能, 你可以在你的程序初始化时自行检查这类事件(比如说machine’s endianness)。

如果你实在需要在配置时刻检查运行时的特征,你可以编写一个测试程序以确定结果,并且通过AC_TRY_RUN 来编译和运行它。如果可能就避免运行测试程序,这是因为使用它们使得人们不能对你的包进行交叉编译。

运行测试程序
如果你希望在配置的时候测试系统运行时的特征,就使用如下的宏。

宏: AC_TRY_RUN (program, [action-if-true [, action-if-false [, action-if-cross-compiling]]])
program是C程序的文本,将对该文本进行shell变量和反引用(backquote)替换。如果它被成功地编译和连接了并且 在执行的时候返回的退出状态为0,就运行shell命令action-if-true。否则就运行shell命令action-if-false; 程序的退出状态可以通过shell变量`$?’得到。本宏在编译时使用CFLAGS或者CXXFLAGS以及 CPPFLAGS、LDFLAGS和LIBS。

如果使用的C编译器生成的不是在configure运行的系统上运行的可执行文件,那么测试程序就不运行。 如果给出了可选的shell命令action-if-cross-compiling,它们就代替生成的可执行文件执行。否则, configure打印一条错误消息并且退出。

当交叉编译使运行时测试变得不可能的时候,就尝试提供一个应急(pessimistic)的缺省值以供使用。你通过把可选的最后一个参数 传递给AC_TRY_RUN来完成这个工作。在每次生成configure的过程中,每次遇到没有提供 action-if-cross-compiling参数的AC_TRY_RUN调用时,autoconf都打印一条警告消息。 虽然用户将不能为交叉编译你的包而进行配置,你仍可以忽略该警告。与Autoconf一同发行的少数宏产生该警告消息。

为了为交叉编译进行配置,你还可以根据规范系统名(canonical system name)为这些参数选择值 (参见手工配置)。另一种方式是把测试缓存文件设置成目标系统的正确值 (参见缓存结果)。

为了给嵌入到其它宏(包括少数与Autoconf一同发行的宏)中的,对AC_TRY_RUN的调用提供缺省值, 你可以在它们运行之前调用AC_PROG_CC。那么,如果shell变量cross_compiling被设置成`yes’,就使用另一种方法来获取结果,而不是调用宏。

宏: AC_C_CROSS
本宏已经过时;它不作任何事情。

测试程序指南
测试程序不应该向标准输出输出任何信息。如果测试成功,它们应该返回0,否则返回非0,以便于把成功的执行 从core dump或者其它失败中区分出来;段冲突(segmentation violations)和其它失败产生一个非0的退出状态。 测试程序应该从main中exit,而不是return,这是因为在某些系统中 (至少在老式的Sun上),main的return的参数将被忽略。

测试程序可以使用#if或者#ifdef来检查由已经执行了的测试定义的预处理器宏的值。 例如,如果你调用AC_HEADER_STDC,那么在`configure.in’的随后部分,你可以使用一个有 条件地引入标准C头文件的测试程序:

#if STDC_HEADERS

include <stdlib.h>

#endif
如果测试程序需要使用或者创建数据文件,其文件名应该以conftest'开头,例如conftestdata’。 在运行测试程序之后或者脚本被中断时,configure将通过运行`rm -rf conftest*’来清除数据文件。

测试函数
在测试程序中的函数声明应该条件地含有为C++提供的原型。虽然实际上测试程序很少需要带参数的函数。

#ifdef __cplusplus
foo(int i)

#else
foo(i) int i;

#endif
测试程序声明的函数也应该有条件地含有为C++提供的,需要`extern “C”‘的原型。要确保不要引入 任何包含冲突原型的头文件。

#ifdef _cplusplus
extern “C” void *malloc(size
t);

#else
char *malloc();

#endif
如果测试程序以非法的参数调用函数(仅仅看它是否存在),就组织程序以确保它从不调用这个函数。你可以 在另一个从不调用的函数中调用它。你不能把它放在对exit的调用之后,这是因为GCC第2版知道 exit永远不会返回,并且把同一块中该调用之后的所有代码都优化掉。

如果你引入了任何头文件,确保使用正确数量的参数调用与它们相关的函数,即使它们不带参数也是如此, 以避免原型造成的编译错误。GCC第2版为有些它自动嵌入(inline)的函数设置了内置原型;例如, memcpy。为了在检查它们时避免错误,既可以给它们正确数量的参数,也可以以不同的返回 类型(例如char)重新声明它们。