我有一个带有两个源文件的简单C程序,Makefile自动生成依赖项,如section 4.14 of the GNU Make Manual中所述:
set allGroups = Application.Session.AddressLists.Item("All Groups")
set addressEntry = allGroups.AddressEntries.Item("<Enter Group Name Here>")
for each m in addressEntry.Members
MsgBox m.Name
next
这将创建类似于all: main
%.d: %.c
@set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
include main.d
include hello.d
main: main.o hello.o
的文件,如下所示:
main.d
如果我更改源代码(和Makefile)以删除hello.c和hello.h,就会出现问题。在下一次增量重建时,main.o main.d : main.c hello.h
失败:
make
make: *** No rule to make target `hello.h', needed by `main.d'. Stop.
文件已过期,但是main.d
无法重建它,因为(根据陈旧的make
),它仍然依赖于不再存在的{{1} }。
在这种情况下,干净的构建将成功。如何使增量构建也成功?
答案 0 :(得分:0)
我修改了main.d
配方,以便仅在文件仍然存在时才考虑依赖项。新的Makefile规则:
hello.h
第二个%.d
将%.d: %.c
@set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed --in-place 's,\($*\)\.o[ :]*,\1.o $@ : ,g' $@.$$$$ ; \
sed 's^: \(.*\)^: $$(foreach t,\1,$$(if $$(wildcard $$t),$$t,))^g' < $@.$$$$ > $@; \
rm -f $@.$$$$
修改为:
sed
因此,如果任何依赖文件消失了,main.d
不会抱怨。
此方法的一个缺点是,在全新构建失败的情况下,增量构建可能会成功。例如,如果删除main.o main.d : $(foreach t,main.c hello.h,$(if $(wildcard $t),$t,))
却没有从make
中正确删除hello.h
,则增量构建将成功(因为它不会尝试重建#include
)完整版本会失败。
此方法是否还有其他缺点?例如,是否有增量构建不完整的情况?