添加werror标志的问题

时间:2016-08-04 16:59:16

标签: c compilation compiler-errors compiler-warnings

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

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

我正在添加以下标志。

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

所以请建议可能出现的问题。

1 个答案:

答案 0 :(得分:1)

警告:这不是完整的答案,因为我们需要更多信息,但对于我已经发布的更多热门评论来说,它会变得太长。< / p>

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

以下是有关如何根据自己对此类问题的经验进行调试的详细说明。

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

CDEFS := -Wall -Werror

[正如您在评论中提到的那样离开-Wextra

如果这是[几乎] makefile中的第一件事,那很好。但是,如果它出现在中间,则用您自己的值替换 CDEFS如果生成文件中的先前行(例如):

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. 使用各种组合的额外选项
  3. 特别是,针对case(2)命令检查case(1)命令可能会显示其他的选项不同于-W。这表示makefile问题,类似于我的&#34; guess&#34;以上。你已经说过[你的等同于]案例(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 >build_log_0508.log

    我不熟悉emq。我无法找到对它的引用,除了#34; JIRA&#34;的企业邮件队列,[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命令行有所帮助[以及当此文件标记时] cc命令。

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

    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,你应该得到相同的警告,但他们只是不会停止构建。在大型构建中,它们很容易在日志中被忽视[由人(例如)我: - )]。

    参考我原来答案中的建议,假设案例(1)[&#34;好&#34;]和案例(2)[&#34;坏&#34;之间的cc命令] 因添加-Wall而有所不同,解决此问题的正确方法是编辑app.c并添加#include <stdlib.h>作为包含的一部分。

      

    &#34; SUB_CDEFS:= -Wall -Werror&#34;是否有问题?

    CDEFS一样,它会有类似的问题/好处。

      

    我在makefile的末尾添加

    这是使用+=代替:=的更多理由。你可能会&#34;杀掉&#34;如果在某处指定了-std=c89

    更新#2:

      

    在执行+=而不是:=后,它有效。

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

    但是,再一次,源代码有 bug 并且已损坏之前你曾经碰过它。通过使用-Wall -Werror添加:=,您发现了此错误,之前被错误地掩盖了 。这是的事情。

    使用+=通过恢复:=丢失的一些构建选项,只需再次扫描地毯下的错误。但是,这些&#34;失去了&#34;构建选项错误。他们允许C代码中的真正缺陷逃脱检测。

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

    使用解决方法来修复&#34;在构建中,您现在已经拥有了一块可以可以正确运行运行的构建软件。它可能会在您的系统上以间歇方式失败。或者,产生不正确的结果。或者,如果您将此系统置于面向公众的网站上,则允许您的系统被黑客攻击[并可能使您承担法律责任]。

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

      

    只需要再澄清SUB_CDEFSUN_CDEFSCDEFS

    之间的区别

    这完全是武断的。

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

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

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

    CDEFS et。人。是这种符号的一个例子。 [应该]选择描述功能的名称。也就是说,CDEFS [可能]意味着&#34; C定义&#34;。实际的符号名称及其功能取决于规则文件。我们可以使用符号SHRONK代替CDEFS。这对理解事物没有多大帮助,但是如果编辑了所有的文件以将CDEFS更改为SHRONK,那么它就可以工作。

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

    旁注:此时此刻没有意义,但如果您编辑了问题并发布了输出cc命令,事情就会变得更加顺畅和快速和我的一些makefile一样,按照我的要求。您可能会在几个小时内获得特定的答案,而不是一般的指导方针[需要几天时间]。

    因此,如果没有规则文件,就无法分辨。只根据名称​​猜

    1. CDEFS - 子目录的全局cc选项
    2. SUB_CDEF - 特定子目录的cc个选项
    3. UN_CDEFS - 指定-Ufoo个选项
    4. 您正在构建的特定软件可能在文档文件中或在一个或多个makefile中的注释中包含此文档。

      为了理解这一点,有很多make的在线指南。在Linux下,有&#34; info&#34;文件。所以,试试info make。其他系统有详细的联机帮助页,man make

      也是如此