【问题标题】:how can I check a particular gcc feature in configure.ac如何检查 configure.ac 中的特定 gcc 功能
【发布时间】:2014-09-09 06:20:59
【问题描述】:

例如,gcc 4.7 有一个新特性 -Wnarrowing。在 configure.ac 中,如何测试当前 gcc 是否支持某个功能?
gnulibc 中有一个file,但对我来说没有多大意义。

【问题讨论】:

  • 也许这个问题应该概括一下。您不能假设编译器是 gcc,因此您应该询问如何检查编译器是否支持特定功能,而不是 gcc 是否支持特定功能。

标签: c++ c gcc autoconf


【解决方案1】:

gcc 和 clang 都支持 -W[no-]narrowing-W[no-]error=narrowing 选项。

使用-std=c++11,gcc 默认发出 warning,而 clang 默认发出 error。即使您只提到 gcc,我认为您可以将功能检查扩展到尝试提供相同选项和扩展的编译器,如 clang。这可能也包括英特尔的 icc。

假设您选择了带有AC_PROG_CXX 的C++ 编译器,并确保了it's using the C++11 standard

ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -Werror -Wno-error=narrowing"
AC_LANG_PUSH([C++])

AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
  [[int i {1.0}; (void) i;]])],
  [ac_cxx_warn_narrowing=1], [ac_cxx_warn_narrowing=0])

AS_IF([test $ac_cxx_warn_narrowing -ne 0],
  [AC_MSG_RESULT(['$CXX' supports -Wnarrowing])])

AC_LANG_POP([C++])
CXXFLAGS="$ac_save_CXXFLAGS"

只有在以下情况下编译才会成功:1) 编译器支持 -Wnarrowing 相关选项,这意味着它支持 -Werror,并且:2) 识别 C++11 初始化语法。

通常,传递给配置的configure.ac 脚本和标志应该避免-Werror,因为它破坏了太多内部测试。在这种情况下,我们确保除了缩小之外没有其他警告,这就是为什么需要(void) i; 来防止出现未使用变量的警告。

【讨论】:

  • -Werror 在这个配置测试中是错误的,正是因为你说它在配置测试中通常是错误的:有正当的原因导致该测试程序可能产生警告(包括简单的事情用户在 CXXFLAGS 中添加额外的警告选项)您没有考虑也不能考虑。我似乎确实记得一些编译器对无用语句 (void) i; 发出警告,用户的警告选项可能会警告初始化中的 C++98 兼容性问题,用户的警告选项可能会警告 @ 的特定形式987654334@ 声明。
  • @hvd - 我很想知道添加到 gcc(或 clang)的任何额外标志选项会在这个测试程序中给出不正确的结果。在任何情况下,配置脚本都应该处理病态的编译器标志组合吗?有些标志无法通过AC_PROG_CC 和早期测试。
  • 不是一般情况,但我确实认为添加警告标志应该始终是安全的,至少因为新警告一直添加到较新版本的编译器,所以检查已经需要预测所有可能的警告。一般来说(不是针对您的具体示例,因为您碰巧选择了 C++ 检查),作为一个病态示例,对非原型函数有警告,对原型函数有警告,所以不管AC_LANG_PROGRAM 如何定义@987654337 @,至少有一个选项可以引起警告。如果我找到更具体的,我会告诉你的。
  • 经过测试,我建议的假设警告确实存在于 clang 中:clang++ -std=c++11 -Wc++98-compat 正确警告 int i {1.0}; 并带有“警告:通用初始化列表与 C++98 不兼容”。跨度>
  • @hvd - 嗯。这也通过-Weverything 标志启用,它忽略标准并打开 c++98-compat 警告。
【解决方案2】:

这背后的逻辑大概应该是:

创建一个正确的文件,该文件应该会收到带有-Wnarrowing 的警告。验证它是否被正确编译。这是一个健全性检查。

然后用-Wnarrowing 编译同一个文件,并验证它是否仍然被正确编译。这可确保您检测到不支持 -Wnarrowing 作为选项的编译器,并且不会尝试将虚假选项传递给它们。

最后,用-Werror=narrowing 编译同一个文件,并验证它现在没有被正确编译。如果现在失败,您可以相当肯定编译器确实支持-Wnarrowing。最后一项检查对于检测接受-Wnarrowing/-Werror=narrowing,但发出警告“忽略未知选项-Wnarrowing”的编译器很有用。在这种情况下,您不应该传递-Wnarrowing

或者,您可能还希望编译一个不应该收到警告的文件,该文件带有-Wnarrowing-Werror=narrowing,以防您发现-Wnarrowing 无用的编译器和@ 987654332@ 是一个硬错误。不过,我想不出一个需要这样做的编译器。

将其转换为配置检查应该很简单。

【讨论】:

  • 这个很脆弱,需要3次编译,我分不清第1步和第2步的区别。
  • @BrettHale 在配置检查期间多次编译没有任何问题。它们是极短的程序,应该编译得非常快。至于第1步和第2步的区别,假设编译器在传递-Wnarrowing时报错,但在不传递-Wnarrowing时也报错。在这种情况下,该错误根本没有说明是否支持 -Wnarrowing。如果测试程序无意中依赖于特定于实现的功能,则可能会发生这种情况,并且调整测试以解决这一问题只是防御性编码。
  • clang 失败 - 因为-Wnarrowing 是默认值,并且出现错误。
  • @BrettHale 在 clang 的情况下,根据您的评论,-Wnarrowing 绝对没有效果,所以根据我的方法,不会添加到 CXXFLAGS 中,这很好,因为它添加它不会有任何区别。但是默认情况下clang实际上并没有启用-Wnarrowing,它只在C++11模式下启用。是的,-Wnarrowing 在 C++98 模式下确实有意义:它会警告 int a[] = { 1.0 };。因此,使用合适的程序,我的方法会在这种情况下正确地导致 -Wnarrowing 被添加到 CXXFLAGS。
  • 我在这里无法按照您的方法进行操作 - 因为 clang 确实支持 -Wnarrowing 功能 - 例如,可以在 C++11 中使用 -Wno-narrowing 将其关闭。你能提供configure.ac 测试吗?
【解决方案3】:

请参阅http://code.google.com/p/opendoom/source/browse/trunk/VisualC8/autotools/ac_c_compile_flags.m4 以获取此类示例测试 - 这会尝试使用给定的编译器标志编译一个简单的程序,如果可行,则将其添加到 CFLAGS。

【讨论】:

  • 它是 AC_C_COMPILE_FLAGS 宏的第一个参数(在宏展开时替换)。
  • 这种方法正是我警告过的:如果一个-Wnarrowing 选项被编译器接受并带有消息“忽略未知选项-Wnarrowing”(是的,这样的编译器存在),-Wnarrowing不应该添加。您的方法确实会导致它被添加。
  • 这是否意味着我可以像 AC_C_COMPILE_FLAGS([flag1 flag2 flag3]) 这样调用这个宏?
  • 那要看他在不行的情况下想做什么。如果他只是试图避免由于无法识别的选项而导致编译器中止,那么这将按原样工作。如果他想检测和处理选项不支持的情况,那么你的方法很好,这个宏可以帮助他开始。
  • 是的,您可以使用标志列表调用它(请参阅我链接的项目的 configure.in)。
猜你喜欢
  • 2013-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-13
相关资源
最近更新 更多