如何在 Autoconf 中确定编译器名称或供应商?

Posted

技术标签:

【中文标题】如何在 Autoconf 中确定编译器名称或供应商?【英文标题】:How to determine compiler name or vendor in Autoconf? 【发布时间】:2017-11-04 18:09:50 【问题描述】:

我正在使用 SunCC 开发 Solaris。 Autoconf 的AC_COMPILE_IFELSEAC_LINK_IFELSE 错误检测编译器功能。 Autoconf 报告功能可用,即使编译器通过 illegal option 等消息拒绝它们。

$ echo 'int main(int argc, char* argv[]) ' > test.C
$ /opt/solarisstudio12.4/bin/CC test.C
$ /opt/solarisstudio12.4/bin/CC -msse4.2 -msha test.C
CC: Warning: Option -msse4.2 passed to ld, if ld is invoked, ignored otherwise
CC: Warning: Option -msha passed to ld, if ld is invoked, ignored otherwise
ld: fatal: option '-h a' is incompatible with building a dynamic executable
$ /opt/solarisstudio12.4/bin/CC -xarch=sha test.C
CC: Warning: illegal use of -xarch option, illegal value ignored: sha

我想尝试解决错误检测,但我需要知道编译器才能做到这一点。 Autoconf 有一些提供canonicalized names for CPU, Vendor and OS 的宏,但它们似乎不包括编译器或其供应商。

我们如何在 Autoconf 中检测或确定编译器名称或供应商?


添加以下内容并没有真正的帮助,因为它不能识别编译器。

AC_MSG_NOTICE(["Build: $build"])
AC_MSG_NOTICE(["Compiler: $compiler"])

然后:

CXX=/opt/solarisstudio12.4/bin/CC ./configure
...

configure: "Build: i386-pc-solaris2.11"
configure: "Compiler: /opt/solarisstudio12.4/bin/CC"

【问题讨论】:

【参考方案1】:

我认为没有标准的方法可以做到这一点。

我们根据predef.sourceforge.net 以及更多来源(如cc --version、cc 的命令名称、操作系统名称...)手动检查编译器宏的存在。

即你编译一个程序,并检查定义。 如果它不存在/程序 #errors out -> 不是 SunCC。

它看起来很乱,但这里有一个直接来自 Score-P 源 (vendor/common/build-config/m4/ax_compiler_vendor.m4) 的示例。也许你可以从中得到一些启发:

AC_DEFUN([AX_COMPILER_VENDOR],
[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
  dnl Please add if possible support to ax_compiler_version.m4
  [# note: don't check for gcc first since some other compilers define __GNUC__
  vendors="intel:     __ICC,__ECC,__INTEL_COMPILER
           ibm:       __xlc__,__xlC__,__IBMC__,__IBMCPP__
           pathscale: __PATHCC__,__PATHSCALE__
           clang:     __clang__
           cray:      _CRAYC
           fujitsu:   __FUJITSU
           gnu:       __GNUC__
           sun:       __SUNPRO_C,__SUNPRO_CC
           hp:        __HP_cc,__HP_aCC
           dec:       __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
           borland:   __BORLANDC__,__CODEGEARC__,__TURBOC__
           comeau:    __COMO__
           kai:       __KCC
           lcc:       __LCC__
           sgi:       __sgi,sgi
           microsoft: _MSC_VER
           metrowerks: __MWERKS__
           watcom:    __WATCOMC__
           portland:  __PGI
           tcc:       __TINYC__
           unknown:   UNKNOWN"
  for ventest in $vendors; do
    case $ventest in
      *:) vendor=$ventest; continue ;;
      *)  vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;;
    esac
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
      #if !($vencpp)
        thisisanerror;
      #endif
    ])], [break])
  done
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
 ])
])

【讨论】:

谢谢罗尼。有趣的是,Score-P 决定使用预处理器宏而不是来自$compiler --version$compiler --qversion$compiler -V 的字符串。似乎转储版本字符串与转储宏的工作量相同(许多编译器不同)。我得考虑一下。你知道为什么要使用预处理器宏吗? 我觉得解析--version比较乱,字符串/关键字可以在版本之间变化。我没有参与那个决定。但我认为这对编译器是有意义的。这是一个可靠的来源。请参阅 predef.sourceforge.net -> 编译器。对于平台/库/其他东西,我们确实使用其他来源。例如。如何判断是Cray系统,还是linux集群等 谢谢罗尼。我将使用编译器字符串而不是预处理器宏。我们的GNUmakefile 使用这两种技术,但它传统上使用--version 和朋友作为编译器版本字符串。【参考方案2】:

正如@Ronny 所说,似乎没有确定编译器供应商的标准方法。在配置过程中检测供应商对于在错误检测期间解决 Autoconf 错误等任务很重要:CC: Warning: illegal use of -xarch option, illegal value ignored: sha

@Ronny 展示了如何使用预处理器宏来做到这一点。我们避免了这种情况,因为编译器伪装成 GCC。 Clang 和 Intel 的编译器都定义了__GNUC__,可能其他人也这样做。

下面是使用configure.ac 中的版本字符串的方法:

## Determine the compiler's vendor.

COMPILER_VERSION=`"$CXX" --version 2>/dev/null`

## IBM xlC test if COMPILER_VERSION is empty
if test x"$COMPILER_VERSION" = "x"; then
   COMPILER_VERSION=`"$CXX" -qversion 2>/dev/null`
fi

## SunCC test if COMPILER_VERSION is empty
if test x"$COMPILER_VERSION" = "x"; then
   COMPILER_VERSION=`"$CXX" -V 2>&1`
fi

那么,vendor 可以这样使用:

IS_SUN_COMPILER=`echo $COMPILER_VERSION | $EGREP -i -c -E 'Sun C\+\+'`
echo "IS_SUN_COMPILER: $IS_SUN_COMPILER"
...

## This block handles SunCC.
if test "$IS_SUN_COMPILER" -ne "0"; then    
    ...    
fi

【讨论】:

是的,定义多个宏是正确的。检查多个来源可能是一个好方法。我不是特别喜欢--version,因为它们喜欢改变。如果你想提取例如编译器的版本号变得更加混乱。

以上是关于如何在 Autoconf 中确定编译器名称或供应商?的主要内容,如果未能解决你的问题,请参考以下文章

如何将编译器标志从 Autoconf 传递给 Automake?

路径中的 Autoconf 空格

如何从 LIB 中告诉 Autoconf“需要符号 A 或 B”?

我应该使用 automake/autoconf 来分发小型 ansi C 应用程序吗?

使用 autoconf/automake,如何指定包含文件路径?

如何正确使用带有子目录的 automake/autoconf?