如何抑制来自库头文件的GCC警告?

166

我有一个项目使用了log4cxx、boost等库,其头文件会产生大量(重复的)警告信息。是否有一种方法可以抑制来自库包含的警告(例如#include <some-header.h>),或者抑制来自特定路径的包含?我希望像往常一样在项目代码上使用-Wall和/或-Wextra,而不会隐藏相关信息。目前我使用make输出中的grep,但我希望有更好的解决方案。

10个回答

148

如果您使用CMake,可以修改include_directories指令以包括符号SYSTEM,从而抑制对此类头文件的警告。

include_directories(SYSTEM "${LIB_DIR}/Include")
                    ^^^^^^

1
如果库提供${LIBFOO_USE_FILE}变量,该如何在CMake的include()命令中使用? - waldyrious
2
这似乎几乎是解决我的问题。我有1.)一个二进制目标,它依赖于2.)由我自己编写的仅头文件目标,该目标又依赖于3.)一些外部库。我不知道如何仅针对1和2获取警告。你有任何想法吗? - knedlsepp
2
似乎无法正常工作。我尝试了一个使用 "easylogging++" 的项目,即使已经使用 "SYSTEM" 选项将其所在的文件夹包含进来,我仍然从 "easylogging++.h" 中收到相同数量的警告信息。 - rbaleksandar
非常感谢这个。它让我免受了一页页的警告之苦。 - Svalorzen
我现在已经一直使用这种策略了,但是当与新的gcc版本(至少> 6.0)一起使用时,会导致编译错误。问题在于-isystem不能很好地与#include_next指令配合使用,例如在<cstdlib>中使用(https://dev59.com/Bpffa4cB1Zd3GeqP2Ayr)。 - bergercookie
1
同接受的答案一样,我认为这是不好的做法。 - Raffi

146

你可以尝试使用-isystem而非-I来包含库头文件。这将使它们成为“系统头文件”,GCC不会为它们报告警告。


11
如果您正在尝试在XCode中完成此操作,则应将“-isystem路径”添加到目标构建设置中的“自定义编译器标志”的“其他C++标志”中。 - Matt Parkins
5
潜在的缺点是,在某些平台上,g++会自动将任何系统头文件用extern "C"包装起来,如果你在-isystem路径下#include一个C++头文件,就会出现关于C链接的奇怪错误。 - Tavian Barnes
1
+1 帮助我解决了烦人的 Boost 警告问题。http://stackoverflow.com/questions/35704753/warnings-from-boost - mrgloom
3
为什么这个回答的投票数比原帖的回答多得多,而且这个回答和原帖的回答在1.5小时前就已经说了完全相同的内容? - underscore_d
1
对于Xcode:如果我的目标构建设置中的“其他C++标志”中没有文件夹路径,怎么办?有人能详细说明一下解决方案吗? - Ossir
显示剩余5条评论

67
您可以使用编译指示("pragmas")进行设置。例如:
// save diagnostic state
#pragma GCC diagnostic push 

// turn off the specific warning. Can also use "-Wall"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/lexical_cast.hpp>

// turn the warnings back on
#pragma GCC diagnostic pop

3
仅适用于 GCC 版本大于等于 4.6。 - Caduchon
1
我很喜欢推入/弹出编译指示的能力。我记得几年前Java有这样的功能,而C/C++却没有,当时我感到非常沮丧和嫉妒。我很高兴现在gcc中也有了这个功能。 - Trevor Boyd Smith
1
@TrevorBoydSmith MS的cl已经有这个功能多年了... 有时候gcc适应得有点慢。 - Alexis Wilke
2
似乎你只能一个一个地禁用警告,即-Wall无效。请参见相关问题 - luator

35

我发现了一个诀窍。对于库的包含,不要使用-Idir,而是在makefile中使用-isystem dir。GCC将boost等库视为系统包含文件,并忽略它们造成的任何警告。


1
请注意,如果您使用预编译头文件,则需要在编译头文件和代码时添加标志。 - user202729

9

#pragma是给编译器的指令。你可以在 #include 前设置一些内容,然后在后面禁用它。

你也可以在命令行上这样做。

GCC还有另一页专门介绍禁用警告

我会选择在源代码中使用 #pragma,并提供一个合理的理由(作为注释)来解释为什么要禁用这些警告。这意味着需要对头文件进行推理。

GCC通过分类警告类型来处理这个问题。你可以将它们分类为警告或忽略。前面链接的文章会向你展示哪些警告可以被禁用。

注意:你也可以使用属性调整源代码以防止某些警告;但是,这会使你与GCC联系得更紧密。

注意2:GCC也使用微软编译器中使用的pop/push接口,微软通过这个接口禁用警告。我建议您进一步调查此事,因为我不知道是否可能。

1
我考虑过使用编译指示,但如果我在包含头文件之前抑制了一个警告,那么在 #include 之后如何将其设置回先前的状态呢?我想查看项目代码的所有警告(已经帮助我几次了),但又想从命令行控制。 - AdSR

6
把以下内容放入:
#pragma GCC system_header

这将关闭本文件中所有后续代码的GCC警告。


4
您可以尝试使用预编译头文件。警告不会消失,但至少不会显示在主要编译中。 点击此处 了解更多信息。

1
这实际上可能是个好主意。第三方包不会每天都改变。 - AdSR
没错。虽然我在Linux上没有用过它们,但在Visual Studio上它们运行得相当不错。 - Pablo Santa Cruz
不,除非你使用其他方式来抑制它们(例如 -isystem,但要记得在编译头文件和代码时都使用它),否则它们仍会显示在编译中。 - user202729

2
如果需要显式地覆盖系统头文件,则只能使用编译指示(pragma)。您可以通过“make depend”输出验证正在使用哪些包含文件。
另请参阅GCC 4.6及以上版本的诊断推送弹出

0
另一种方法是在makefile中告诉编译器忽略特定文件夹的警告。
$(BUILD_DIR)/libs/%.c.o: CFLAGS += -w

这会抑制所有警告,而不仅仅是外部库头文件中的警告,这很可能不是所期望的。 - user686249

-10

这些警告肯定有原因。它们可能是由于你使用库的代码中存在错误,也可能是由于库本身存在错误。如果是前者,就修复你的代码。如果是后者,要么停止使用该库,要么如果它是FOSS代码,则修复它。


+1 个好建议 :D 但他正在询问如何做某个具体的事情 :D - Hassan Syed
6
有些警告是不可能或者非常难修复的,尤其是在第三方代码中,特别是在像 Boost 这样富含元编程的代码中。 - ulidtko
3
让我困扰的更糟糕的是,某个boost头文件中深深嵌入了一个声明“c”的警告:“声明‘c’掩盖了‘this’的成员[-Werror=shadow]”。虽然这确实不是问题,但类似的问题不断地产生输出信息,并且使我很难找到我们代码库中真正的变量重名问题。 - dmckee --- ex-moderator kitten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接