【问题标题】:Make: Unexpected Behavior with Dependencies and include StatementMake:具有依赖关系和包含语句的意外行为
【发布时间】:2015-12-20 22:24:05
【问题描述】:

我有以下 Makefile:

a.d:
    gcc -m32 -MM -o $@ a.c
    sed 's!a.o!$@ a.o!' --in-place $@

a.o:
    gcc -c -m32 -o $@ a.c

all: a.d a.o

-include a.d

a.d的内容是:

a.d a.o: a.c a.h

我有两个问题。 1、运行“make all”后如果我运行:

touch a.h
make a.d

我看到了:

gcc -m32 -MM -o a.d a.c
sed 's!a.o!a.d a.o!' --in-place a.d
make: 'a.d' is up to date.

a.d 规则明显运行,为什么我看到“make: 'a.d' is up to date.”?

2,在我运行“make all”之后:

touch a.h
make a.o

我看到了:

gcc -m32 -MM -o a.d a.c
sed 's!a.o!a.d a.o!' --in-place a.d
gcc -c -m32 -o a.o a.c

为什么它还运行广告规则?没有任何依赖关系。

我真正不明白的是当我将“-include a.d”替换为make文件中a.d的内容时,例如:

#-include a.d
a.d a.o: a.c a.h

我没有看到任何问题。 include 语句不应该使包含文件直接包含在同一个 make 文件中吗?

这就是我的 a.h 的样子:

#define FOO 0

这是交流电:

#include <stdio.h>
#include "a.h"

void foo(void)
{
    printf("foo %d", FOO);
}

我使用的是 Cygwin 64 位。这是 make -v 的输出:

$ make -v
GNU Make 4.1
Built for x86_64-unknown-cygwin
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

【问题讨论】:

  • FWIW,当我在 GNU Make 3.81 下运行时,都没有出现问题。
  • @Beta 我刚刚还在 VM 中的 32 位 Ubuntu 中进行了测试,但我仍然看到了问题,GNU Make 3.81。您确定将 -include ... 语句留在了 make 文件中吗?
  • @Beta 我在其中一个编辑中打错了字。我纠正了它。你现在就会看到问题了。

标签: include makefile dependencies gnu-make


【解决方案1】:

GNU make 尝试重建包含的 makefile 可以解释您的两种行为;见How Makefiles are Remade。因此,在您的第一个问题中,第一个输出来自 make 尝试重建 a.d 文件的时间,第二个输出来自 make re-execs 本身之后;它看到目标a.d 是最新的。

在您的第二个问题中,它运行a.d 规则,因为a.d 依赖于a.h,并且由于您包含a.d,因此请尝试重建它。

对于您的最后一个问题,如果您直接嵌入内容不会发生这种情况的原因是您没有使用include。

其他有趣的内容是:Generating Prerequisites Automatically 和 Advanced Auto-Dependency Generation。也可以Constructed Include Files 了解更多背景信息。

【讨论】:

  • 那么当一个包含的make文件被修改时,make会重新启动原始的make文件吗?这不是第二个问题的真正答案。我要求 make build a.o,而不是 a.d。是的 a.d 依赖于 a.h,但我要求重建 a.o,而 a.d 不是 a.o 的依赖项。另外,当我将include的内容直接放在文件中时,不会出现此问题。
  • 我解释了这两件事。请重新阅读我的答案的第 2 和第 3 段。因为包含了a.d,所以即使你明确要求a.o,make 也会总是尝试重建它。无论您要求构建什么目标,make 总是尝试重建所有包含的文件。由于a.d 依赖于a.h 并且a.h 是较新的并且包含a.d,因此重新构建a.d。总是。对于另一个问题,显然如果您不使用 include 操作,则没有包含任何内容,也没有要重建的包含文件。
  • 谢谢,这条评论对我有帮助:“因为包含了 a.d,所以即使你明确要求 a.o,make 也会始终尝试重建它。”始终检查并可能更新包含的目标。现在行为很清楚了。我还从 GNU 邮件列表中获得了一些支持,长话短说,在 make 文件中使用依赖项作为目标并不是一个好主意。您提供链接的高级自动依赖生成文章中的高级方法将是一种更好的方法。我猜你是那篇文章的作者?谢谢你帮助我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-23
  • 1970-01-01
  • 2023-04-06
  • 2022-06-15
  • 2016-05-18
  • 2015-10-11
  • 2012-09-21
相关资源
最近更新 更多