警告:这不是一个完整的答案,因为我们需要更多信息,但对于像我已经发布的那些顶级 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
我们希望看到的是make 为badnews.c 打印的编译命令以及两个 情况的警告/错误输出:
- 没有额外的选项
- 具有多种组合的额外选项
特别是,对照 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 >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 <stdlib.h> 作为包含的一部分。
“SUB_CDEFS := -Wall -Werror”有什么问题吗?
它会有与CDEFS类似的问题/好处。
我在 makefile 的末尾添加
这就是使用+= 而不是:= 的更多理由。如果在某处指定了-std=c89,您可能会“杀死”它。
更新 #2:
在执行 += 而不是 := 之后它起作用了。
正如我所提到的,使用 := 删除了一些关键的编译选项,这些选项在 makefile 的其他地方指定。
但是,再一次,源代码有一个错误并且是损坏。它在你触摸它之前就坏了。通过使用:= 添加-Wall -Werror,您发现了这个以前被错误地屏蔽的错误。这是一件好事。
使用+= 只是通过恢复一些在:= 中丢失的构建选项,[再次] 清除了地毯下的错误。但是,这些“丢失”的构建选项错误。他们允许 C 代码中的真正缺陷逃脱检测。
这不是关于使构建工作[使用解决方法],而是解决构建问题的根本原因,即修改 C 源代码。可能还有其他这样的 C 源代码错误,有些可能更严重。
通过“修复”构建的解决方法,您现在拥有了一个构建软件,该软件不可以被信任以正确运行。它可能会在您的系统上间歇性地失败。或者,产生不正确的结果。或者,如果您将其放在面向公众的网站上,则允许您的系统被黑客入侵[并可能使您承担法律责任]。
如果您不方便自己修改源代码,请向软件的原作者提交错误报告。源代码应该有一个README 文件或BUGS 文件,或者任何应该概述这样做的过程的文件。
只需要再澄清一下SUB_CDEFS、UN_CDEFS 和CDEFS 之间的区别
这完全是任意的。
使用make 构建的软件项目通常可以构建多个程序或库。这些通常放置在子目录中。每个这样的子目录通常都有自己的Makefile。
为了避免不必要的重复[和潜在的错误],这些 makefile 共有的部分被放置在一个 single makefile 中,通常称为 rules 文件 [但是它只是一个makefile]。然后各个 makefile 有一行:include ../common/rules.mk
规则文件希望定义某些符号,以帮助指导它为给定子目录构建目标。
CDEFS 等。人。是此类符号的一个示例。 [应该]选择描述功能的名称。也就是说,CDEFS [可能] 表示“C 定义”。实际的符号名称及其功能取决于规则文件。我们可以使用符号SHRONK 而不是CDEFS。这对理解事情没有多大帮助,但如果所有的 makefile 都被编辑以将 CDEFS 更改为 SHRONK,它会起作用。
例如,在其他软件中,类似的符号可能被命名为 CFLAGS 或 COPTS,而不是 CDEFS。这很常见。
旁注:此时有点没有实际意义,但如果您编辑了问题并发布了输出 cc 命令和 [一些],事情会变得更加顺利和快速我要求的你的makefile。您会在几小时内得到具体的答案,而不是一般的指导方针[需要几天时间]。
因此,如果没有规则文件,就无法分辨。仅根据名称进行猜测:
-
CDEFS -- 全局 cc 子目录选项
-
SUB_CDEF -- cc this 特定子目录的选项
-
UN_CDEFS -- 指定-Ufoo 选项
您正在构建的特定软件可能在文档文件中或在一个或多个 makefile 中的 cmets 中包含此文档。
要大致了解这一点,make 有很多在线指南。在 Linux 下,有“信息”文件。所以,试试info make。其他系统有详细的手册页,man make