如何使Autoconf来测试来自外部文件的源代码?

时间:2019-01-18 08:25:11

标签: compilation autotools autoconf

我们使用GNUmakefile作为我们的主要构建系统。 Makefile使用源文件中的测试程序执行功能测试:

$ ls TestPrograms/
dump2def.cxx         test_arm_sm4.cxx      test_x86_avx.cxx
test_32bit.cxx       test_cxx.cxx          test_x86_avx2.cxx
test_64bit.cxx       test_mixed_asm.cxx    test_x86_avx512.cxx
...

一个测试程序就是人们所期望的:

$ cat test_cxx.cxx
#include <string>
int main(int argc, char* argv[])
{
    unsigned int x=0;
    return x;
}

我们支持Debian和Fedora等发行版的Autotools。我们希望自动工具使用GNUmakefile和CMake等测试程序。 AC_COMPILE_IFELSE上的Autools文档为here,但与往常一样可悲。它不讨论主题也不提供示例。

在黑暗中刺伤:

CXXFLAGS="-msse2"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS and Foo Bar])
AC_LINK_IFELSE(
   [AC_LANG_PROGRAM([TestPrograms/test_x86_sse2.cxx])],
   [AC_MSG_RESULT([yes])],
   [AC_MSG_RESULT([no])]
)

结果:

checking if g++ supports -msse2 and Foo Bar... no

将文件cat放入字符串的结果相同:

CXXFLAGS="-msse2"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS and Foo Bar])
AC_LINK_IFELSE(
   [AC_LANG_PROGRAM(`cat TestPrograms/test_x86_sse2.cxx`)],
   [AC_MSG_RESULT([yes])],
   [AC_MSG_RESULT([no])]
)

在Skylake机器上结果不正确。 SSE2是核心指令集的一部分,并且始终可用:

$ g++ -msse2 TestPrograms/test_x86_sse2.cxx
$

我们如何告诉Autoconf编译测试文件?

1 个答案:

答案 0 :(得分:1)

  

AC_COMPILE_IFELSE [...]上的Autools文档照常可怜。它不讨论主题也不提供示例。

尽管单个页面没有提供完整的详细信息,但它是一本较大的手册的一部分,该手册在附近的章节中提供了更多详细信息和一些相关示例。即使是该页面本身也建议使用AC_LANG_PROGRAM作为为该宏生成input参数的一种适当方式,而documentation for that macro给出了对其生成的一般形式的合理理解-实际来源程序的代码,而不是文件名。

在回答问题时,我建议不要在黑暗中故意。即使您认为文档不足,至少configure的日志文件(config.log)仍应包含许多有关什么,确切,失败以及如何的信息。如果发生故障,它将向您显示所使用的测试程序的完整源代码,为实际执行测试而执行的命令以及发出的所有诊断信息。

例如,使用受您的示例启发而从configure.ac派生的配置脚本...

AC_INIT([test_test], [0.0.1])
AC_CONFIG_SRCDIR([test_src/test_cxx.cxx])
AC_PROG_CXX
CXXFLAGS="-msse2"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS and Foo Bar])
AC_LINK_IFELSE(
   [AC_LANG_PROGRAM([`cat test_src/test_cxx.cxx`])],
   [AC_MSG_RESULT([yes])],
   [AC_MSG_RESULT([no])]
)
AC_OUTPUT

...我在日志中得到以下相关输出的失败结果:

configure:2891: gcc -o conftest -g -O2   conftest.c  >&5
conftest.c:9:18: fatal error: string: No such file or directory
 #include <string>
                  ^
compilation terminated.
configure:2891: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "test_test"
| #define PACKAGE_TARNAME "test_test"
| #define PACKAGE_VERSION "0.0.1"
| #define PACKAGE_STRING "test_test 0.0.1"
| #define PACKAGE_BUGREPORT ""
| #define PACKAGE_URL ""
| /* end confdefs.h.  */
| #include <string>
| int main(int argc, char* argv[])
| {
|     unsigned int x=0;
|     return x;
| }
| int
| main ()
| {
| 
|   ;
|   return 0;
| }
configure:2895: result: no

这表明确实从外部文件中读取了源代码,并且还揭示了两个关键问题:

    在这种情况下,
  1. AC_LANG_PROGRAM提供的功能超出了您的期望(与其文档一致)。实际上,如果要提供测试程序的完整源代码,则根本不需要它。

  2. 测试程序正在作为C程序进行编译和链接,但是其源代码是C ++。该默认设置已记录在in the manual中。

仅通过将源直接馈送到AC_LINK_IFELSE即可解决问题(1),而无需通过AC_LANG_PROGRAM进行包装,但是在这种情况下Autoconf将发出警告,提示您看不到AC_LANG_SOURCE。一个合理而舒适的解决方案是直接使用AC_LANG_SOURCE而不是AC_LANG_PROGRAM。但是,这将为提供的源添加一些额外的#defines,但这可能不适合您。如果您不希望这样做,那么我认为在这种情况下可以忽略警告。

问题(2)可以通过使用AC_LANG宏告诉Autoconf来解决,即应该使用C ++编译器以及有关C ++标志的相关Autotools变量来执行测试。

因此,如果我将configure.ac更新为

AC_INIT([test_test], [0.0.1])
AC_CONFIG_SRCDIR([test_src/test_cxx.cxx])
AC_PROG_CXX
AC_LANG([C++])
CXXFLAGS="-msse2"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS and Foo Bar])
AC_LINK_IFELSE(
   [AC_LANG_SOURCE([`cat test_src/test_cxx.cxx`])],
   [AC_MSG_RESULT([yes])],
   [AC_MSG_RESULT([no])]
)
AC_OUTPUT

然后我的配置运行成功,并且在日志中看到它成功执行了编译命令

configure:2296: g++ -o conftest -msse2   conftest.cpp  >&5

。也就是说,它使用选定的C ++编译器进行编译,使用CXXFLAGS中指定的标志,并适当命名测试源文件以进行C ++编译。