-Werror导致编译器在#warning上停止。 我该怎么做才能防止这种情况发生?
首先,我希望它停止警告。 但我也希望打印出一些信息性的消息(比如“回来实现这个!”)。
不幸的是,我的编译器不支持#info
#message
, #pragma message()
, #pragma message()
等。
我知道有-Wno-error=
,但我的google-foo很弱,我似乎无法找到#warning
的 。 我试过
-Wno-error=warning
,只是说“没有 – -Wwarning
”。 与“ warn
”相同。
有什么建议?
值得一提的是,我使用的是Tensilica xtensa编译器,xt-xcc,它似乎是一个gnu派生词,或者至少使用了gnu前端。 它的版本是8.0.0。
我不熟悉Tensilica xtensa编译器( xt-xcc
),但您可以使用标准gcc
#pragma GCC diagnostic warning "-Wcpp"
使#warning
成为简单警告的问题(因为-Werror
而不是错误)。 要使效果暂时,您可以使用#pragma
和#pragma GCC diagnostic push
和#pragma GCC diagnostic pop
之间的#warning
。
当我编译包含以下内容的文件时
#pragma GCC diagnostic push #pragma GCC diagnostic warning "-Wcpp" #warning one #pragma GCC diagnostic pop #warning two
使用-Werror
使用gcc
4.6.1(命令gcc -c -Werror warning-test.c
),我得到以下输出:
warning-test.c:3:2: warning: #warning one [-Wcpp] warning-test.c:6:2: error: #warning two [-Werror=cpp] cc1: all warnings being treated as errors
当我删除第二个#warning
,编译不会被错误中断。
您还可以使用-Werror -Wno-error=cpp
替换-Werror
编译器选项。 我不知道cpp
类别的警告包含哪些其他影响(并且您可能在其他某个地方有一个合法的#warning
要捕获为错误),因此暂时禁用特定#warning
的错误并立即恢复设置似乎更准确的方法满足您的要求。
编辑(2016):使用gcc
版本4.8.4和4.9.2给出了几乎相同的行为(仅额外打印源行)。 但是使用gcc
版本5.0.1(Ubuntu 15.04中包含的预发布版本)将提供两个警告,除非包含选项-Werror=cpp
。 所以似乎 – 更新gcc的错误不再像以前那样暗示-Werror=cpp
,如果需要它需要单独提供。
出了什么问题:
#warning "Come back and implement this" #warning "Do not do that!" #warning "Must fix this before release"
通常,编译器会在错误或警告消息中包含参数 – 或者在#warning
之后的材料。
而且,通常情况下,如果编译器检测到需要警告的内容,它会相当清楚地报告。
鉴于这些要求,我认为解决这个问题的唯一方法是保护#warning
指令……
#ifdef DO_WARNINGS #warning "Some warning" #endif /* DO_WARNINGS */
大多数情况下,编译时不使用-DDO_WARNINGS
; 当你需要检查#warning
警告(使用-Werror
)时,你会包含-DDO_WARNINGS
,接受编译失败。 请记住,即使存在单个编译错误, make -k
也会尽可能多地执行。
GCC 4.4.1手册第5.52.9节(部分)说:
5.52.9诊断编译
GCC允许用户有选择地启用或禁用某些类型的诊断,并更改诊断的类型。 例如,项目的策略可能要求所有源使用“-Werror”进行编译,但某些文件可能具有允许特定类型警告的exception。 或者,项目可以选择性地启用诊断并将其视为错误,具体取决于定义的预处理器宏。
#pragma GCC diagnostic kind option
修改诊断的处置。 请注意,并非所有诊断都可以修改; 目前只有警告(通常由’-W ……’控制)可以控制,而不是所有警告。 使用’-fdiagnostics-show-option’确定哪些诊断可控,哪个选项控制它们。 kind是’错误’将此诊断视为错误,’警告’将其视为警告(即使’-Werror’有效),或者如果要忽略诊断则’忽略’。 option是双引号字符串,与命令行选项匹配。
#pragma GCC diagnostic warning "-Wformat" #pragma GCC diagnostic error "-Wformat" #pragma GCC diagnostic ignored "-Wformat"
请注意,这些编译指示会覆盖任何命令行选项。 此外,虽然将这些编译指示放在源中的任何位置在语法上是有效的,但它们唯一受支持的位置是在定义任何数据或函数之前。 否则可能会导致不可预测的结果,具体取决于优化程序管理源的方式。 如果多次列出相同的选项,则指定的最后一个选项是有效的选项。 此pragma不是用于命令行选项的通用替代,而是用于实现对项目策略的严格控制。
GCC还提供了一种在编译期间打印消息的简单机制。
#pragma message string
在编译时将字符串打印为编译器消息。 该消息仅供参考,既不是编译警告也不是错误。
#pragma message "Compiling " __FILE__ "..."
字符串可以用括号括起来,并打印出位置信息。
我不确定您是否想将#warning
行编辑成#pragma message
行。 这会让你解决问题 – 而且只比在#warning
中添加条件编译更糟糕的是, #pragma message
可能会被更少的编译器支持。 这取决于您的可移植性要求。
鉴于#warning大概是由预处理器处理的,你可以在没有-Werror的情况下单独运行预处理器,然后运行编译器,在前处理器输出上禁止预处理。
为此,通过预处理器运行带有除-Werror之外的所有常规选项的.c文件,并将输出生成为.i文件(.ii for C ++)。 编译器将这些文件识别为不进行预处理,因此您可以使用-Werror编译它们,并假设预处理器丢弃#warning并且编译器本身不处理它,这可能会解决您的问题。
我没有测试过这个; 当我遇到同样的问题时,我只选择使用它而不是使用-Werror。 解决方案似乎比问题更复杂!
如果您的编译器支持它,您可以尝试使用constructor
函数函数属性来定义在程序启动时(在main
之前)运行的函数,该函数将消息打印到stdout:
#define TOKENPASTE(x, y) TOKENPASTE2(x, y) #define TOKENPASTE2(x, y) x ## y #define WARNING(message) \ static void TOKENPASTE(_print_warning, __LINE__)() __attribute__((constructor)); \ static void TOKENPASTE(_print_warning, __LINE__)() \ { \ puts(message); \ } WARNING("fix this before ship") // prints out a message at runtime before main
这会导致在运行时而不是编译时打印出消息,这几乎同样好,特别是如果您没有其他选项。 唯一的限制是您必须在函数定义之外的全局范围内使用它。
不幸的是,我的特定工具链没有答案,或者Tensilica的工程师说。 它们不支持#message或#pramga message(),或者知道如何在出现-Werror时将#warning抑制为错误。
GCC工具链允许使用-Wno-error = [code]来说“这个警告不是错误”,但我还没有找到一个列表,它将#warning与任何代码相对应(或者甚至列表这可能是代码)
我可能会试着找时间深入研究标准GCC命令行和预处理器源代码,试图找到-Wno-error =可以等于的列表,或者是否有-Werror =代码对应#warning。 如果我这样做,我会回来更新答案。