更强大的 AC_COMPILE_IFELSE 功能测试? [英] More robust AC_COMPILE_IFELSE feature testing?

查看:36
本文介绍了更强大的 AC_COMPILE_IFELSE 功能测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

# infile 和 outfile 是允许测试功能的临时文件SH_ERROR=$($CXX -Wl,--enable-new-dtags -o "$outfile" "$infile" 2>&1 | $EGREP -i -c -E 'fatal|error|illegal|unrecognized|not发现|不存在')if [[ "$SH_ERROR" -eq "0" ]];然后CXXFLAGS+="-Wl,--enable-new-dtags"菲

AC_COMPILE_IFELSE 的 Autoconf 文档位于 6.4 运行编译器,但不讨论主题.事实上,该文档甚至没有定义 AC_COMPILE_IFELSE 的成功[ful]"意味着什么.

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

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

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

一个相关的问题是(基于 Stefan 的回答),我们如何让 Autoconf 使用改进的 AC_COMPILE_IFELSE?是否可以取消定义当前的 AC_COMPILE_IFELSE 并将其定义为更健壮的版本?

提前致谢.

解决方案

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

我很确定没有标准定义任何语言的编译器应该返回什么,除了所有程序的明显标准,退出代码 0 意味着成功,其他一切都失败,见 关于exit 函数的posix:

<块引用>

参数状态的值为零(或 EXIT_SUCCESS,要求为零)通常表示成功终止.这对应于 ISO C 标准中 exit() 的规范.遵循惯例的是诸如 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 的问题几年前,从另一个 arch 运行二进制文件总是会打印一个错误,它无法加载它,尽管它没有任何问题 - AC_LANG_WERROR 在这种环境中严重中断

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

# MY_COMPILE_CLEAN_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE])# ---------------------------------------------------------------# 尝试编译 PROGRAM.AC_DEFUN([MY_COMPILE_CLEAN_IFELSE],[AC_REQUIRE([AC_PROG_EGREP])AC_COMPILE_IFELSE([$1],[retval=0如果 $EGREP -i -c -E '致命|错误|无法识别|未找到|不存在' conftest.err >/dev/null;然后 retval=1;菲],[retval=1])AS_IF([测试 $retval = 0],[$2],[$3])])

conftest.err是在AC_COMPILE_IFELSE完成后删除的,需要在内部actions中查看.

Autoconf's AC_COMPILE_IFELSE is misdetecting features for us under different compilers, like Sun's C++ compiler and IBM's xlC compiler. AC_COMPILE_IFELSE appears to check return values, but some compilers don't bother to set it or set it to unexpected values. Later, we use options that are not available.

In my non-Autoconf build scripts I use "fatal|error|illegal|unrecognized|not found|not exist" to detect a compiler or linker complaint. It is more robust than just checking $?. The test looks like:

# 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

The Autoconf documentation for AC_COMPILE_IFELSE is at 6.4 Running the Compiler, but it does not discuss the subject matter. In fact, the document does not even define what it means for AC_COMPILE_IFELSE to be "success[ful]".

My first question is, are compiler return values standardized somewhere?

My second question is, what does Autoconf use to determine "success"?

My third question is, how do we do the same in Autoconf? Is there something else to use besides AC_COMPILE_IFELSE?

A related question is (based on Stefan's answer), how do we get Autoconf to use an improved AC_COMPILE_IFELSE? Is it possible to undef the current AC_COMPILE_IFELSE and define it to the more robust version?

Thanks in advance.

解决方案

My first question is, are compiler return values standardized somewhere?

I'm pretty sure there is no standard defining what compilers for any language should return, apart from the obvious standard for all programs that exit code 0 means success and everything else failure, see posix on the exit function:

A value of zero (or EXIT_SUCCESS, which is required to be zero) for the argument status conventionally indicates successful termination. This corresponds to the specification for exit() in the ISO C standard. The convention is followed by utilities such as make and various shells, which interpret a zero status from a child process as success. For this reason, applications should not call exit(0) or _exit(0) when they terminate unsuccessfully; for example, in signal-catching functions.


My second question is, what does Autoconf use to determine "success"?

The latest autoconf release is 2.69 (from 2012), and although some things might have changed, I'm going to base my answer on it.

AC_COMPILE_IFELSE is successful, iff the compiler has a successful exit code (i.e. 0) and the object file is not empty (test -s conftest.$ac_objext; it is removed before running the compiler). If AC_LANG_WERROR was used for the current language it also makes sure the stderr output of the compiler is empty (apart from shell trace log lines).


My third question is, how do we do the same in Autoconf? Is there something else to use besides AC_COMPILE_IFELSE?

Keep in mind, that although the autoconf sources look like magic, they are not - you can build your own macros as long as you know what you want them to do :) But maybe AC_LANG_WERROR is an option, apart from telling the vendor to suck it and fix their crap.

I'm not a fan of AC_LANG_WERROR: I had to use /etc/ld.so.preload on a multiarch system to fix problems with flashplayer some years ago, and running binaries from the other arch would always print an error it couldn't load it, although there was nothing wrong with it - AC_LANG_WERROR breaks horribly in such environment

As an example of a custom compile check macro take a look at this:

# 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 is deleted after AC_COMPILE_IFELSE is done, so you need to check it in the inner actions.

这篇关于更强大的 AC_COMPILE_IFELSE 功能测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆