【问题标题】:How can Autoconf be made to test source code from an external file?如何使 Autoconf 测试来自外部文件的源代码?
【发布时间】:2019-01-18 08:25:10
【问题描述】:

我们使用 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。我们希望 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 编译测试文件?

【问题讨论】:

    标签: compilation autotools autoconf


    【解决方案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

    问题 (1) 可以通过直接将源提供给AC_LINK_IFELSE 来解决,而不是通过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++。

    【讨论】:

    • 谢谢约翰。我希望今天晚些时候能对其中一些进行测试。
    • @jww - 是的,好吧,自动工具可以处理近 30 年的边缘案例、深奥的标志、编译器、ABI 和数千种系统特性。 每一个构建系统都将成为下一个“简化”的构建系统,因为它不可避免地会重新发明轮子,因此它的规模和复杂性都在迅速增加。 AC_PROG_CXX; AC_LANG([C++])???
    • @BrettHale - 是的,we use themAC_LANG_ASSERT([C++])
    猜你喜欢
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 2011-03-16
    • 2019-10-22
    • 1970-01-01
    相关资源
    最近更新 更多