简体   繁体   English

Makefile:自动生成二进制文件的依赖项

[英]Makefile: automatic generation of dependencies for binaries

I would like to "completely" automate the process of dependency generation in a project's Makefile. 我想“完全”自动化项目的Makefile中依赖项生成的过程。 So far, I have followed this tutorial on automatic dependencies, which works very nicely. 到目前为止,我已经遵循了有关自动依赖项的教程该教程非常好用。 There is only one catch: this only works for head-file dependencies, so it will automatically detect if say bin_1.o depends on header_1.h as well as header_2.h. 只有一个陷阱:仅适用于头文件依赖项,因此它将自动检测bin_1.o是否依赖header_1.h以及header_2.h。 However, I can directly translate header-file dependencies to object-file dependencies. 但是,我可以直接将头文件依赖关系转换为目标文件依赖关系。 Say, one of the automatically generated dependency files says 说,自动生成的依赖文件之一说

bin_1.o: bin_1.cpp header_1.h header_2.h

So, in the linking step, I can immediately conclude that I will need to link together the files bin_1.o, header_1.o, and header_2.o in order to generate the binary bin_1. 因此,在链接步骤中,我可以立即得出结论,我将需要将文件bin_1.o,header_1.o和header_2.o链接在一起,以生成二进制bin_1。 In other words, a corresponding dependency file for bin_1 should have 换句话说,bin_1的对应依赖项文件应具有

bin_1: bin_1.o header_1.o header_2.o

That is exactly what I have tried to achieve. 这正是我试图实现的目标。 The translation described above is done by a small python script, extract_dependencies.py, and a stripped-down version of my Makefile then looks like this: 上面描述的翻译是通过一个小的python脚本extract_dependencies.py完成的,然后我的Makefile的精简版看起来像这样:

binaries = bin_1 bin_2 bin_3

SRCS := $(wildcard *.cpp)

all: $(binaries)

# dependencies
DEPDIR := .d
$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td

COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) -c
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
GENERATE_BINARY_DEPS = python extract_dependencies.py $(DEPDIR)/$*.d > $(DEPDIR)/$*.bin.d

$(DEPDIR)/%.d: ;
$(DEPDIR)/%.bin.d: ;
.PRECIOUS: $(DEPDIR)/%.d $(DEPDIR)/%.bin.d

$(binaries): % : %.o $(DEPDIR)/%.bin.d
    ${CC} ${CFLAGS} $(shell cat .d/$@.bin.d | cut -d ' ' -f 2-) ${LDFLAGS} -o $@

%.o: %.cpp
%.o: %.cpp $(DEPDIR)/%.d
    $(COMPILE) $<
    $(POSTCOMPILE)
    $(GENERATE_BINARY_DEPS)

clean:
    rm -vf *.o
    rm -vf bin_1 bin_2 bin_3

realclean:
    $(MAKE) clean
    rm -fr .d

-include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))
-include $(patsubst %,$(DEPDIR)/%.bin.d,$(basename $(SRCS)))

Now comes the problem: in order for that to work, I need to run "make" twice. 现在出现了问题:为了使其正常工作,我需要运行两次“ make”。 The *.bin.d dependency files are generated, but only on the second run, Make actually "realizes" that say header_1.o is also necessary for bin_1, not only bin_1.o. * .bin.d依赖文件已生成,但仅在第二次运行时,Make实际上“意识到”说header_1.o对于bin_1也是必要的,而不仅仅是bin_1.o。 On the first run, it tries to link all the object files together without actually building all the object files first. 在第一次运行时,它将尝试将所有目标文件链接在一起,而无需先实际构建所有目标文件。

Is there any way to come around that issue, ie get everything right on the first pass? 有什么办法可以解决该问题,即在第一遍解决所有问题?

Thanks! 谢谢!

Since Make will read-in whole makefile at 1st, then perform targets. 由于Make将在1日读取整个makefile,然后执行目标。 It's hard to get %.bin.d updated in one pass. 很难一次性更新%.bin.d。 Alternatively, we could try to trigger 2nd "make" internally like, 另外,我们可以尝试在内部触发第二个“ make”,例如

ifneq ($(STAGE),2)
$(binaries): % : %.o $(DEPDIR)/%.bin.d
        @{MAKE} $(binaries) STAGE=2
else
#2nd pass
$(binaries):
        ${CC} ${CFLAGS} -o $@ $(shell cat .d/$@.bin.d | cut -d ' ' -f 2-) ${LDFLAGS}
endif

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM