autoconf 检查丢失的原型

autoconf check for missing prototype

有没有比将 CFLAGS 设置为“-Werror -Wimplicit-function-declaration”更好的方法来为缺少的原型编写 autoconf 测试?

具体来说,我正在尝试确定是否需要提供我自己的 pwrite(2)pread(2)。如果环境严格,则不定义 pread/pwrite。 这是我现在拥有的,它有效:

AC_INIT([pwrite],[0.0.0],[none],[nothing],[nowhere])

AC_CONFIG_HEADERS([config.h])
old_CFLAGS=$CFLAGS
CFLAGS="-Werror $CFLAGS"

AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
    #ifdef HAVE_UNISTD_H
    #include <unistd.h>
    #endif

    int main(int argc, char **argv) {
        int ret = pwrite(99, "blah", 1, 0);
        return 0;
    } ]) ],
    AC_MSG_RESULT([using system pwrite prototype])
    AC_DEFINE(HAVE_PWRITE, 1, [pwrite protoype exists]),
    AC_MSG_RESULT([no pwrite protoype. using our own])
    )

CFLAGS=$old_CFLAGS

AC_OUTPUT()

当我这样做时,configure CFLAGS=-std=c99 确实会检测到隐式声明了 pwrite,而 configure 单独会在 unistd.h 中找到一个 pwrite 原型。但是,在 configure 中使用 CFLAGS 似乎不是 "autoconf-y" 的方法。

如果您查看 autoconf 宏的源代码,您会发现其中很多都保存和恢复 CFLAGS。但是,您需要非常小心地使用 -Werror,因为您可能会得到不正确的结果。例如,如果 argcargv 未使用 - ret - 警告(参见:-Wunused* 标志)将被解释为 pwrite 不可用。

假设 <unistd.h> 编译时没有 warning-as-errors,它应该:

<save CFLAGS>
CFLAGS="$CFLAGS -Werror=implicit-function-declaration"

AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
  [[#ifdef HAVE_UNISTD_H
    #include <unistd.h>
    #endif]],
  [[(void) pwrite(99, "blah", 1, 0);]])],
  <action-on-success>,
  <action-on-fail>)

<restore CFLAGS>

(void) 转换可能是不必要的 - 它用于 crazy-strict 警告,即使对于系统 headers 也可能不会沉默,但不会造成伤害。可能值得查看 _XOPEN_SOURCE 宏值 - 例如,在此测试和库代码中设置 _XOPEN_SOURCE

Saving/restoring CFLAGS 是可以接受的,但对于这个特定目的,AC_CHECK_DECLS 结果正是我正在寻找的,而且对于超级挑剔的编译器或试图找出等同于 -Werror-implicit-function-declaration 的 Portland Group 编译器是什么。

AC_INIT([pwrite],[0.0.0],[none],[nothing],[nowhere])
AC_CONFIG_HEADERS([config.h])
AC_CHECK_HEADERS([unistd.h])
AC_CHECK_DECLS([pwrite])
AC_OUTPUT()

然后在我的代码中我必须以不同的方式检查结果:

#if (HAVE_DECL_PWRITE == 0)
... implement our own pwrite 
#endif