Makefile每隔一次忽略依赖项

时间:2018-10-12 16:10:56

标签: makefile build gnu-make

我希望我的Makefile执行以下操作:

  • 当主要目标需要某个文件时,总是运行一些命令
  • 如果文件已更改(由于运行这些命令),请重新构建依赖于该文件的所有内容

在我的情况下,该文件是C头文件,应该包含版本信息。我希望makefile始终更新此版本标题并重建包含它的所有文件。

会发生什么: 当我运行make时,每次都会执行版本头更新(如我所愿)。 但是,依赖此标头的文件仅在其他时间重新构建。

这是我删除的Makefile:

SOURCES:= main.c

app.exe: $(SOURCES:%.c=%.o)
    gcc -o $@ $^

# always recompile when dependency information is missing
$(SOURCES:%.c=%.o): %.o: %.c %.d
    gcc -c $< -MMD

$(SOURCES:%.c=%.d):

version.h: update-version

update-version:
    touch version.h

# include C/C++ header-dependencies
-include $(SOURCES:%.c=%.d)

.PHONY: update-version

# disables builtin suffix-rules
.SUFFIXES:

有人可以帮助我理解为什么它不是每次都重新编译,而是每秒钟一次吗?

make是GNU Make 4.2.1,而remake的行为完全相同。

1 个答案:

答案 0 :(得分:1)

excerpt from make's manual阐明了您的makefile无法按您预期的方式工作的原因:

  

GNU make在两个不同的阶段进行工作。在第一阶段   它读取所有makefile,包含的makefile等,并内部化   所有变量及其值,隐式和显式规则,以及   构造所有目标及其依赖关系图   先决条件。在第二阶段,使用这些内部   确定需要重建哪些目标以及   调用必要的规则。

由于您是在规则内执行命令(在示例中为touch),因此make将在第二阶段执行该命令。但是到那时,依赖性图和过时的目标已经确定。在第一阶段就发生了。

牢记这一点,您可以了解为什么它每隔一次就能工作。每次都会执行您所需的命令 ,但是只有在第一阶段文件main.o已经比version.h更新时,main.o才会被视为过时。 ,即未执行任何规则。因此,基本上main.o仅在您调用version.h命令时早于make时才被认为是过时的。如果上次调用main.o时没有重新编译make,就是这种情况。

您每次可以及时执行命令的技巧是在开始处的某个地方添加一个虚拟变量,并使其在评估期间执行所需的命令。再次以touch作为示例命令,您将在第一行中执行以下操作:

DUMMY := $(shell touch version.h)

由于这是立即分配,因此该命令将在第一阶段执行。如果该命令更新了version.h,那么所有依赖于version.h的目标都将被视为过时并重新构建。其中包括main.o

使用这种方法,您不再需要任何.PHONY: update-version机制及其相关的规则和配方。


更新

重读后,我意识到您写道:“当主要目标需要某个文件时,总是运行某些命令 ”。你是什​​么意思?再往下看,您写了“当我运行make时,每次都会执行版本头更新(就像我想要的那样)”,这就是此答案产生的makefile所做的。你能澄清一下吗? “主要目标”是什么意思?