更强大的AC_COMPILE_IFELSE功能测试?

jww*_*jww 7 c++ autoconf compiler-warnings

Autoconf AC_COMPILE_IFELSE在不同的编译器下错误地检测了我们的功能,例如Sun的C++编译器和IBM的xlC编译器.AC_COMPILE_IFELSE似乎检查返回值,但有些编译器不打扰设置它或将其设置为意外值.稍后,我们使用不可用的选项.

在我的非Autoconf构建脚本中,我"fatal|error|illegal|unrecognized|not found|not exist"用来检测编译器或链接器投诉.它比仅仅检查更健壮$?.测试看起来像:

# infile and outfile are temp files that allow testing a feature
SH_ERROR=$($CXX -Wl,--enable-new-dtags -o "$outfile" "$infile" 2>&1 | $EGREP -i -c -E 'fatal|error|illegal|unrecognized|not found|not exist')
if [[ "$SH_ERROR" -eq "0" ]]; then
    CXXFLAGS+="-Wl,--enable-new-dtags"
fi
Run Code Online (Sandbox Code Playgroud)

Autoconf文档AC_COMPILE_IFELSE位于6.4运行编译器,但它没有讨论主题.事实上,该文件甚至没有定义AC_COMPILE_IFELSE"成功["]的含义.

我的第一个问题是,编译器返回值是否标准化了?

我的第二个问题是,Autoconf用什么来确定"成功"?

我的第三个问题是,我们如何在Autoconf中做同样的事情?除此之外还有其他东西可供使用AC_COMPILE_IFELSE吗?

一个相关的问题是(基于Stefan的答案),我们如何让Autoconf使用改进的AC_COMPILE_IFELSE?是否有可能取消当前的流量AC_COMPILE_IFELSE并将其定义为更强大的版本?

提前致谢.

Ste*_*fan 4

我的第一个问题是,编译器返回值是否在某处标准化?

我很确定没有标准定义任何语言的编译器应该返回什么,除了退出代码0意味着成功和其他一切失败的所有程序的明显标准之外,请参阅函数上的 posixexit

参数状态的值为零(或EXIT_SUCCESS,要求为零)通常表示成功终止。exit()这对应于ISO C 标准中的规范。该约定之后是 make 和各种 shell 等实用程序,它们将子进程的零状态解释为成功。因此,应用程序不应在未成功终止时调用exit(0)或;_exit(0)例如,在信号捕获功能中。


我的第二个问题是,Autoconf 使用什么来确定“成功”?

最新的 autoconf 版本是 2.69(从 2012 年开始),尽管有些事情可能发生了变化,但我的答案将基于它。

AC_COMPILE_IFELSE成功,前提是编译器有成功的退出代码(即0)并且目标文件不为空(test -s conftest.$ac_objext;在运行编译器之前将其删除)。如果AC_LANG_WERROR用于当前语言,它还会确保编译器的输出为空stderr除了shell 跟踪日志行)。


我的第三个问题是,我们如何在 Autoconf 中做同样的事情?除此之外还有什么可以用的吗AC_COMPILE_IFELSE

请记住,虽然 autoconf 源看起来很神奇,但事实并非如此 - 只要您知道您想要它们做什么,您就可以构建自己的宏:) 但也许AC_LANG_WERROR是一个选择,除了让供应商接受它之外并解决他们的问题。

我不喜欢AC_LANG_WERROR:几年前,我不得不/etc/ld.so.preload在多架构系统上使用来解决 flashplayer 的问题,并且从另一个架构运行二进制文件总是会打印一个无法加载它的错误,尽管没有任何问题它 -AC_LANG_WERROR在这样的环境下会严重损坏

作为自定义编译检查宏的示例,请看一下:

# MY_COMPILE_CLEAN_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
# ---------------------------------------------------------------
# Try to compile PROGRAM.
AC_DEFUN([MY_COMPILE_CLEAN_IFELSE],
[AC_REQUIRE([AC_PROG_EGREP])
AC_COMPILE_IFELSE([$1],[retval=0
if $EGREP -i -c -E 'fatal|error|unrecognized|not found|not exist' conftest.err >/dev/null; then retval=1; fi
],[retval=1])
AS_IF([test $retval = 0],[$2],[$3])])
Run Code Online (Sandbox Code Playgroud)

conftest.err完成后就被删除了AC_COMPILE_IFELSE,所以需要在内部actions中查看。