c - 关于添加错误标志的问题

标签 c compilation compiler-errors compiler-warnings

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

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

我添加他跟随标志。

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

因此,请提出可能的问题。

最佳答案

警告:这不是一个完整的答案,因为我们需要更多信息,但是对于更多的顶级评论(如我已经发布的评论)来说,这太长了。

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

根据我对此类问题的经验,以下是一些有关如何调试它的详细说明。

但是,在此之前,我会冒险猜测。我注意到您正在执行以下操作:

CDEFS := -Wall -Werror

[删除注释中提到的-Wextra]。

如果这样做几乎是makefile中的第一件事,那就很好了。但是,如果它发生在中间,则您要用自己的值替换CDEFS。如果makefile中的前一行是(例如):
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打印的编译命令以及两种情况下的警告/错误输出:
  • ,不带额外选项
  • ,带有各种组合形式的额外选项

  • 特别是,将case(1)命令与case(2)命令对照可能会显示-W以外的其他选项是不同的。这表明有一个makefile问题,类似于我上面的“猜测”。您已经说过,[相当于](1)情况很干净,没有任何警告,但是,鉴于您遇到的麻烦,再次检查不会有任何伤害。

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

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

    所有DFLAGS-DFOO=1COPTS-g-O2-Wall等的-fno-inline-functions

    然后,我要么做:
    CFLAGS := $(COPTS) $(DFLAGS)
    

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

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

    更新:

    I am using following command to build: emq PRODUCT=ASG >build_log_0508.log



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

    Getting the following error on compilation: 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)[“良好”]与情况(2)[“不良”]之间的cc命令仅因添加了-Wall而有所不同,正确的解决方法是:编辑app.c并添加#include <stdlib.h>作为include的一部分。

    Is there any problem with "SUB_CDEFS := -Wall -Werror"?



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

    I am adding at the end of the makefiles



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

    更新2:

    It worked after doing += instead of :=.



    如前所述,使用:=删除了一些关键的编译选项,这些选项在makefile中的其他位置指定。

    但是,再次,源代码有一个错误并且被破坏了。在您触碰它之前,它已经被打破了。通过使用-Wall -Werror添加:=,您发现了此错误,该错误以前没有被正确屏蔽。这是一件好事。

    通过恢复+=丢失的一些构建选项,使用:=可以再次扫除错误。但是,这些“丢失的”构建选项是错误的。他们允许C代码中的真正缺陷逃脱检测。

    这不是要使构建正常运行(有解决方法),而是要解决构建问题的根本原因,即修改C源代码。可能还有其他这样的C源代码错误,有些可能更严重。

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

    如果您不满意自己进行源代码修改,请向软件的原始作者提交错误报告。源代码应具有README文件或BUGS文件,或应概述该过程的任何文件。

    Just need one more clarification for what is the difference between SUB_CDEFS, UN_CDEFS, and CDEFS



    这是完全任意的。

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

    为了避免不必要的重复[和潜在的错误],这些makefile共有的部分放在单个makefile中,通常称为规则文件[但是它只是一个makefile]。各个makefile的行如下:include ../common/rules.mk
    规则文件期望定义了某些符号,以帮助指导它为给定的子目录构建目标。
    CDEFS等等是此类符号的示例。 [应该]选择描述功能的名称。也就是说,CDEFS [可能]表示“C定义”。实际的符号名称及其功能取决于规则文件。我们可以使用符号SHRONK代替CDEFS。这对理解事物没有多大帮助,但是如果所有makefile都经过编辑以将CDEFS更改为SHRONK,那么它将起作用。

    例如,在其他软件中,代替CDEFS的类似符号可能被命名为CFLAGSCOPTS。这是相当普遍的。

    旁注:目前还没有定论,但是如果您编辑了问题并按照我的要求发布了输出cc命令和您的某些makefile,事情将会变得更加顺利和迅速。您将在几个小时内获得特定答案,而不是一般准则(需要花费几天时间)。

    因此,如果没有规则文件,就无法分辨。仅根据名称猜测:
  • CDEFS-子目录
  • 的全局cc选项
  • SUB_CDEF-此特定子目录
  • cc选项
  • UN_CDEFS-指定-Ufoo选项

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

    为了大致了解这一点,有许多make的在线指南。在Linux下,有“信息”文件。因此,尝试info make。其他系统有详细的手册页,man make也有

    关于c - 关于添加错误标志的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38773337/

    相关文章:

    c - 如何通过C代码从绝对地址读取值

    c++ - IDE可以直接读取C库源代码吗?如何找到需要的源代码

    比较浮点升序排序

    c - 使用数组和指针算法闪烁 LED

    php - 如何使用新的 OpenSSL 库编译 PHP

    c# - C 构建(从 C# 的角度)

    c++ - 为什么 Microsoft 的 C/C++ 编译器允许带有逗号分隔表达式的 if 语句?

    c# - 编译具有不同名称的相同程序集

    c - GSL 多个错误处理程序定义链接时出错

    c++ - 运行小程序时Windows编译报错