【发布时间】:2014-09-09 06:20:59
【问题描述】:
例如,gcc 4.7 有一个新特性 -Wnarrowing。在 configure.ac 中,如何测试当前 gcc 是否支持某个功能?
gnulibc 中有一个file,但对我来说没有多大意义。
【问题讨论】:
-
也许这个问题应该概括一下。您不能假设编译器是 gcc,因此您应该询问如何检查编译器是否支持特定功能,而不是 gcc 是否支持特定功能。
例如,gcc 4.7 有一个新特性 -Wnarrowing。在 configure.ac 中,如何测试当前 gcc 是否支持某个功能?
gnulibc 中有一个file,但对我来说没有多大意义。
【问题讨论】:
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@ 声明。
AC_PROG_CC 和早期测试。
AC_LANG_PROGRAM 如何定义@987654337 @,至少有一个选项可以引起警告。如果我找到更具体的,我会告诉你的。
clang++ -std=c++11 -Wc++98-compat 正确警告 int i {1.0}; 并带有“警告:通用初始化列表与 C++98 不兼容”。跨度>
-Weverything 标志启用,它忽略标准并打开 c++98-compat 警告。
这背后的逻辑大概应该是:
创建一个正确的文件,该文件应该会收到带有-Wnarrowing 的警告。验证它是否被正确编译。这是一个健全性检查。
然后用-Wnarrowing 编译同一个文件,并验证它是否仍然被正确编译。这可确保您检测到不支持 -Wnarrowing 作为选项的编译器,并且不会尝试将虚假选项传递给它们。
最后,用-Werror=narrowing 编译同一个文件,并验证它现在没有被正确编译。如果现在失败,您可以相当肯定编译器确实支持-Wnarrowing。最后一项检查对于检测接受-Wnarrowing/-Werror=narrowing,但发出警告“忽略未知选项-Wnarrowing”的编译器很有用。在这种情况下,您不应该传递-Wnarrowing。
或者,您可能还希望编译一个不应该收到警告的文件,该文件带有-Wnarrowing 和-Werror=narrowing,以防您发现-Wnarrowing 无用的编译器和@ 987654332@ 是一个硬错误。不过,我想不出一个需要这样做的编译器。
将其转换为配置检查应该很简单。
【讨论】:
-Wnarrowing时报错,但在不传递-Wnarrowing时也报错。在这种情况下,该错误根本没有说明是否支持 -Wnarrowing。如果测试程序无意中依赖于特定于实现的功能,则可能会发生这种情况,并且调整测试以解决这一问题只是防御性编码。
-Wnarrowing 是默认值,并且出现错误。
-Wnarrowing 绝对没有效果,所以根据我的方法,不会添加到 CXXFLAGS 中,这很好,因为它添加它不会有任何区别。但是默认情况下clang实际上并没有启用-Wnarrowing,它只在C++11模式下启用。是的,-Wnarrowing 在 C++98 模式下确实有意义:它会警告 int a[] = { 1.0 };。因此,使用合适的程序,我的方法会在这种情况下正确地导致 -Wnarrowing 被添加到 CXXFLAGS。
-Wnarrowing 功能 - 例如,可以在 C++11 中使用 -Wno-narrowing 将其关闭。你能提供configure.ac 测试吗?
请参阅http://code.google.com/p/opendoom/source/browse/trunk/VisualC8/autotools/ac_c_compile_flags.m4 以获取此类示例测试 - 这会尝试使用给定的编译器标志编译一个简单的程序,如果可行,则将其添加到 CFLAGS。
【讨论】:
-Wnarrowing 选项被编译器接受并带有消息“忽略未知选项-Wnarrowing”(是的,这样的编译器存在),-Wnarrowing不应该添加。您的方法确实会导致它被添加。