【问题标题】:Make / gcc cryptic error 2: how to have more information?Make / gcc 神秘错误2:如何获得更多信息?
【发布时间】:2011-07-20 09:23:41
【问题描述】:

我有这个使用 Makefile 编译的 C++ 项目,有时当(我的猜测)缺少一些包含时,我收到一条神秘的“错误 2”消息,并且 make 过程停止。 我怀疑缺少包含,因为这是当我包含一个不存在的头文件时发生的第三次。

看起来像这样:

---- Build tmp/foo.o ----
---- Build tmp/bar.o ----
---- Build tmp/toto.o ----
---- Build tmp/tata.o ----
make: *** [build_Project] Error 2

这让我发疯了,因为即使使用详细命令(显示每个 g++ 调用),我也看不到任何东西。
我预计这家伙会抛出一些错误消息,例如“找不到标头 X”或“未定义对 Y 的引用”,但什么都没有。

如果有帮助,我的 gcc 编译选项是 -O0 -Wall -Werror -Wno-write-strings -fno-rtti -fno-exceptions

啊,我们使用了包含依赖项的 Makefile 技巧:

ifneq ($(strip $(DEPENDS)),)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPENDS)
endif
endif

(请参阅herehere 了解更多信息)

虽然这是记录在案的东西,但我怀疑我的问题与包含此依赖项有关。

如果您已经偶然发现了这个问题,请随时对此发表评论......

提前致谢。

编辑: 好的,在玩了一会儿之后,在 -include $(DEPENDS) 前面抑制 - 会给我一些更多信息(makefile 确实 停止在丢失的包含文件上)。

make[1]: *** No rule to make target « foo.h », necessary for « tmp/bar.d ». Stop.

现在的缺点是,当我第一次启动make 时,我会为每个应该包含的依赖文件收到missing bar.d file 消息(这就是我们将- 放在首位的原因)。 有什么解决办法吗?

【问题讨论】:

  • 我认为我们需要查看更多的 makefile,例如您如何调用 gcc- 我倾向于显示出于这种原因编译的命令
  • 如果你设置了一个变量,一些 makefile 会关闭花哨的输出。例如,automake 会在您运行make V=1 时显示命令,也可以尝试make VERBOSE=1,或检查Makefile 以获得更好的想法。

标签: c++ gcc dependencies makefile


【解决方案1】:

这是一个定制的 Makefile,可能通过像 CMake 这样的工具隐藏编译器输出,类似于:

gcc -o a.out a.c 2>&1 > /dev/null

如果您不知道发生了什么,那么完全重新访问构建系统听起来是个好主意,请尝试重新开始。

【讨论】:

  • 不,我确实编写了 makefile,但可能传递了一些棘手的副作用。编译行不包含这样的2>&1 > /dev/null,所以不可能是这样。
【解决方案2】:

好的,我的编辑解决了问题:在 include 前面放置一个破折号 - 隐藏了来自依赖项生成的错误消息。

稍后注意:不要试图智取 Make。

【讨论】:

    【解决方案3】:

    /dev/null 2>&1 语句分成几部分:

    第 1 部分:>> 输出重定向 这用于重定向程序输出并将输出附加到文件末尾。 More...

    第 2 部分:/dev/null 特殊文件 这是一个伪设备特殊文件。 命令

    ls -l /dev/null

    将为您提供此文件的详细信息:

    crw-rw-rw-。 1根根1,20年3月3日18:37 /dev/null

    你观察到 crw 了吗?这意味着它是一个提供串行访问的字符特殊文件类型的伪设备文件。 /dev/null 接受并丢弃所有输入;不产生输出(总是在读取时返回文件结束指示)。参考:维基百科

    第 3 部分:2>&1 文件描述符

    当你执行一个程序时,操作系统总是打开三个文件,标准输入、标准输出和标准错误,正如我们所知,每当打开一个文件时,操作系统(从内核)返回一个非负整数,称为文件描述符。这些文件的文件描述符分别为 0、1 和 2。 所以 2>&1 只是说将标准错误重定向到标准输出。 & 表示后面的内容是文件描述符,而不是文件名。 简而言之,通过使用此命令,您是在告诉您的程序在执行时不要大喊大叫。 使用 2>&1 的重要性是什么? 如果您不想产生任何输出,即使终端中产生了一些错误。为了更清楚地解释,让我们考虑以下示例:

    $ ls -l > /dev/null

    对于上面的命令,终端没有打印输出,但是如果这个命令产生错误怎么办:

    $ ls -l file_doesnot_exists > /dev/null

    ls: 无法访问 file_doesnot_exists: 没有这样的文件或目录

    尽管我将输出重定向到 /dev/null,但它会打印在终端中。这是因为我们没有将错误输出重定向到/dev/null,所以为了也重定向错误输出,需要添加2>&1:

    $ ls -l file_doesnot_exists > /dev/null 2>&1

    【讨论】:

    • 欢迎堆栈溢出。看起来您的答案与问题无关(如果我错了,请纠正我)。我想它是错误发生的,您可能想删除您的答案并将其发布到您想要的位置。
    • 我回复了这个:编译行不包含这样的 2>&1 > /dev/null 所以不可能是这样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-31
    • 2021-01-18
    • 2014-11-09
    相关资源
    最近更新 更多