【问题标题】:Issue on adding werror flag添加错误标志的问题
【发布时间】:2016-08-04 16:59:15
【问题描述】:

我正在尝试在我的 makefile 中添加警告作为错误标志。但是我遇到了以下问题。

当我在不添加标志的情况下进行编译时,它是成功的。但是当我在一些“.mk”文件中添加 Werror 标志时,编译失败并出现一些错误。但是在成功的构建日志中没有那个源文件(“.c”)的警告,现在抛出错误(Werror)。

我正在添加他以下标志。

UN_CDEFS := -Wno-error=%
CDEFS   := -Wall -Werror -Wextra
SUB_CDEFS := -Wall -Werror -Wextra

所以请提出可能是什么问题。

【问题讨论】:

  • “编译失败并出现一些错误”? 什么错误?请发帖MCVE
  • -Werror 会影响检查/查找的警告。只是编译器是否返回错误代码[例如1] 警告(即将警告视为错误)。因此,要么基本构建正在生成被抑制/忽略/忽略的警告要么您添加了其他内容。我的猜测是-Wextra 是问题所在,因为它往往会产生一些误报。因此,请尝试以下所有 -Wall-Wall -Werror-Wall -Werror -Wextra 并注意差异。另外,-Wall -Wextra 怎么样?
  • 感谢@CraigEstey。实际上,在实际的构建日志中,该文件没有警告,我没有更改任何文件。我只在 makefile 中添加了这些标志。没有源代码更改。好的,我会尝试 -Wall _Werror(跳过 Wextra)。我需要错误标志。
  • 总是使用-Werror,从来没有遇到过问题。如果出现警告 [可能会因日志的目视检查而遗漏],它只会停止构建。 旁注:会在添加-O2 时生成一些警告,这是由于在给定编译器中如何实现检测(例如,我说的是gcc )
  • 嘿@CraigEstey 我尝试了讨论的选项。但还是一样。

标签: c compilation compiler-errors compiler-warnings


【解决方案1】:

警告:这不是一个完整的答案,因为我们需要更多信息,但对于像我已经发布的那些顶级 cmets 来说,它会变得 [太] 冗长。

当您改进问题和/或发布更多数据时,我可以相应地编辑此答案。至少,发布您的实际生成文件可能会有所帮助,以及实际的最终cc 命令和失败的.c 文件的编译器警告/错误输出[可能有多个,但单个/第一个应该足够]。

下面是一些关于如何调试的详细说明,基于我自己处理此类问题的经验。


但是,在我开始之前,我会冒险猜测一下。我注意到你在做:

CDEFS := -Wall -Werror

[留下你在评论中提到的-Wextra]。

如果这是[几乎]在 makefile 中的第一件事,那很好。但是,如果它发生在中间,您将 替换 CDEFS 为您自己的值。 如果 makefile 中的 prior 行做了(例如):

CDEFS = -Dwont_build_cleanly_without_this_option

然后,当您添加您的线路时,这可能是问题所在,因为这会[有效地]删除。你可以试试这个:

CDEFS += -Wall -Werror

这只是附加到现有符号,因此将保留任何先前的值。

此外,基本的 makefile 可能具有以下内容:

ifndef CDEFS
    CDEFS := -Dwont_build_cleanly_without_this_option
endif

通常,make 将输出它为创建目标而执行的命令的全文。对于编译,这是(例如)cc -c foo.c

一些更高级的构建将命令包装在(例如)@doit cc -c foo.c 中,其中doit 打印类似compiling foo.c ... 的消息,并且仅在出现错误时输出完整的命令。 (例如,Linux 内核构建就是这样做的,IIRC)。我假设你没有有这个,但如果你有,通常会有一个命令行覆盖,例如make VERBOSE=1

因此,某处有一些.c 文件可以使用正常选项干净地构建,但在添加额外编译选项时会生成错误。我们称这个文件为badnews.c

我们希望看到的是makebadnews.c 打印的编译命令以及两个 情况的警告/错误输出:

  1. 没有额外的选项
  2. 具有多种组合的额外选项

特别是,对照 case (2) 命令检查 case (1) 命令可能会显示-W 之外的选项other 是不同的。这表明一个 makefile 问题,类似于我上面的“猜测”。您已经说过 [您的等价物] 案例 (1) 是干净的,没有任何警告,但是,考虑到您遇到的麻烦,仔细检查不会有什么坏处。

您可以将 case (1) cc 命令剪切并粘贴到 shell 脚本中,然后手动添加 -W 选项。注意带有空格的内容,例如 makefile 中的 -DSTRING="foo bar",可能需要在 shell 脚本中使用额外的引号。


为了减轻与您类似的冲突,在我自己的 makefile 中,我将符号分开。

DFLAGS 代表所有-DFOO=1

COPTS 代表-g-O2-Wall-fno-inline-functions

那么,我要么做:

CFLAGS := $(COPTS) $(DFLAGS)

或者:

%.o: %.c:
    cc -c $(COPTS) $(DFLAGS) $<

还有其他方法可以做到这一点。


更新:

我正在使用以下命令构建:emq PRODUCT=ASG &gt;build_log_0508.log

我不熟悉emq。我找不到对它的引用,除了“JIRA 的企业邮件队列”,[AFAICT] 可能cPanel的一部分?

编译时出现以下错误:prod/libs/app/app.c:720:5: error: incompatible implicit declaration of built-in function 'free' [-Werror] free(tmp_dn);

这是确凿的证据......

我不知道您正在使用什么编译器,或者什么操作系统/环境,但它似乎默认将此标记为警告/错误。

然而,它app.c 中的一个需要修复的错误。通过添加-Wall-Werror,它被正确标记为警告/错误

注意:正如我在原始答案中提到的那样, 拥有产生此错误的最终 cc 命令行 [以及 @ 987654360@ 此文件标记时的命令]。

我创建了一个简单的测试用例:

void
myfree(void *ptr)
{

    free(ptr);
}

在这里,在gcc 下,我做了gcc -c test.c,我得到了:

test.c: In function 'myfree':
test.c:5:2: warning: implicit declaration of function 'free' [-Wimplicit-function-declaration]
  free(ptr);
  ^
test.c:5:2: warning: incompatible implicit declaration of built-in function 'free'
test.c:5:2: note: include '<stdlib.h>' or provide a declaration of 'free'

所以,gcc默认 [甚至 没有 -Wall-Werror] 标记这个。但是,你的编译器不会,除非它被给出-Wall。如果您的编译器是 clang 并且您还指定了 -std=c89

,则可能会发生这种情况

正如我之前暗示的,如果您只指定-Wall -Werror,您应该会收到相同的警告,但它们不会停止构建。在大型构建中,它们很容易在日志中被忽略 [被人类(例如)我 :-)]。

参考我原始答案中的建议,假设 case (1) ["good"] 和 case (2) ["bad"] 之间的 cc 命令只有不同添加 -Wall,解决此问题的正确方法是编辑 app.c 并添加 #include &lt;stdlib.h&gt; 作为包含的一部分。

“SUB_CDEFS := -Wall -Werror”有什么问题吗?

它会有与CDEFS类似的问题/好处。

我在 makefile 的末尾添加

这就是使用+= 而不是:= 的更多理由。如果在某处指定了-std=c89,您可能会“杀死”它。


更新 #2:

在执行 += 而不是 := 之后它起作用了。

正如我所提到的,使用 := 删除了一些关键的编译选项,这些选项在 makefile 的其他地方指定。

但是,再一次,源代码有一个错误并且是损坏。它在你触摸它之前就坏了。通过使用:= 添加-Wall -Werror,您发现了这个以前被错误地屏蔽的错误。这是一件好事

使用+= 只是通过恢复一些在:= 中丢失的构建选项,[再次] 清除了地毯下的错误。但是,这些“丢失”的构建选项错误。他们允许 C 代码中的真正缺陷逃脱检测。

不是关于使构建工作[使用解决方法],而是解决构建问题的根本原因,即修改 C 源代码。可能还有其他这样的 C 源代码错误,有些可能更严重。

通过“修复”构建的解决方法,您现在拥有了一个构建软件,该软件可以被信任以正确运行。它可能会在您的系统上间歇性地失败。或者,产生不正确的结果。或者,如果您将其放在面向公众的网站上,则允许您的系统被黑客入侵[并可能使您承担法律责任]。

如果您不方便自己修改源代码,请向软件的原作者提交错误报告。源代码应该有一个README 文件或BUGS 文件,或者任何应该概述这样做的过程的文件。

只需要再澄清一下SUB_CDEFSUN_CDEFSCDEFS 之间的区别

这完全是任意的。

使用make 构建的软件项目通常可以构建多个程序或库。这些通常放置在子目录中。每个这样的子目录通常都有自己的Makefile

为了避免不必要的重复[和潜在的错误],这些 makefile 共有的部分被放置在一个 single makefile 中,通常称为 rules 文件 [但是它只是一个makefile]。然后各个 makefile 有一行:include ../common/rules.mk

规则文件希望定义某些符号,以帮助指导它为给定子目录构建目标。

CDEFS 等。人。是此类符号的一个示例。 [应该]选择描述功能的名称。也就是说,CDEFS [可能] 表示“C 定义”。实际的符号名称及其功能取决于规则文件。我们可以使用符号SHRONK 而不是CDEFS。这对理解事情没有多大帮助,但如果所有的 makefile 都被编辑以将 CDEFS 更改为 SHRONK,它会起作用。

例如,在其他软件中,类似的符号可能被命名为 CFLAGSCOPTS,而不是 CDEFS。这很常见。

旁注:此时有点没有实际意义,但如果您编辑了问题并发布了输出 cc 命令和 [一些],事情会变得更加顺利和快速我要求的你的makefile。您会在几小时内得到具体的答案,而不是一般的指导方针[需要几天时间]。

因此,如果没有规则文件,就无法分辨。仅根据名称进行猜测

  1. CDEFS -- 全局 cc 子目录选项
  2. SUB_CDEF -- cc this 特定子目录的选项
  3. UN_CDEFS -- 指定-Ufoo 选项

您正在构建的特定软件可能在文档文件中或在一个或多个 makefile 中的 cmets 中包含此文档。

要大致了解这一点,make 有很多在线指南。在 Linux 下,有“信息”文件。所以,试试info make。其他系统有详细的手册页,man make

【讨论】:

  • emq PRODUCT=ASG >build_log_0508.log 在编译 prod/libs/app/app.c:720:5 时出现以下错误:错误:内置函数'free'的隐式声明不兼容 [ -Werror] 免费(tmp_dn); ^ cc1:所有警告都被视为错误
  • “SUB_CDEFS := -Wall -Werror”有问题吗?
  • 还有一件事..我在makefile的末尾添加。
  • 嘿克雷格,非常感谢。它在做 += 而不是 := 之后起作用。只需要再澄清一下SUB_CDEFS、UN_CDEFS和CDEFS有什么区别
  • 如果您有任何了解所有这些的链接,请告诉。Thnaks。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 2016-07-12
  • 2018-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多