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
AC_COMPILE_IFELSE
的Autoconf文档位于6.4 Running the Compiler,但未讨论主题。事实上,该文件甚至没有定义AC_COMPILE_IFELSE
成功[...]"
我的第一个问题是,编译器返回值是否标准化了什么?
我的第二个问题是,Autoconf用什么来确定"成功"?
我的第三个问题是,我们如何在Autoconf中做同样的事情?除AC_COMPILE_IFELSE
之外还有其他什么用途吗?
一个相关的问题是(根据Stefan的答案),我们如何让Autoconf使用改进的AC_COMPILE_IFELSE
?是否可以取消当前AC_COMPILE_IFELSE
并将其定义为更强大的版本?
提前致谢。
答案 0 :(得分:4)
我的第一个问题是,编译器返回值是否标准化了什么?
我非常确定没有标准定义任何语言的编译器应该返回,除了退出代码0
的所有程序的明显标准意味着成功和其他一切失败,请参阅{{3功能:
参数状态的值为零(或
EXIT_SUCCESS
,必须为零)通常表示成功终止。这符合ISO C标准中exit()
的规范。该约定之后是诸如make和各种shell之类的实用程序,它们将子进程的零状态解释为成功。因此,应用程序在终止失败时不应调用exit(0)
或_exit(0)
;例如,在信号捕捉功能中。
我的第二个问题是,Autoconf用什么来确定"成功"?
最新的autoconf版本是2.69(从2012年开始),虽然有些事情可能已经改变,但我会根据它做出回答。
posix on the exit
成功,如果编译器有一个成功的退出代码(即0
)并且目标文件不为空(test -s conftest.$ac_objext
;它在运行编译器之前被删除)。如果AC_COMPILE_IFELSE
用于当前语言,则还会确保AC_LANG_WERROR
(the stderr
output of the compiler is empty除外)。
我的第三个问题是,我们如何在Autoconf中做同样的事情?除
AC_COMPILE_IFELSE
之外还有其他什么用途吗?
请记住,虽然autoconf源看起来像魔术,但它们不是 - 你可以建立自己的宏,只要你知道你想要他们做什么:)但也许shell trace log lines是一个选项,除了告诉供应商吮吸它并修复它们的废话。
我不是AC_LANG_WERROR
的粉丝:几年前我必须在多系统系统上使用/etc/ld.so.preload
来修复flashplayer的问题,并从其他arch中运行二进制文件总是会打印出一个无法加载它的错误,尽管它没有任何问题 - 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])])
conftest.err
完成后删除 AC_COMPILE_IFELSE
,因此您需要在内部操作中进行检查。