Gnu Make自动依赖生成

时间:2018-07-04 18:13:01

标签: makefile dependencies auto-generate

基于this famous link并改编自this gist,并假设您的所有源文件都是.cpp,您将很容易获得这样的解决方案,可以自动生成依赖项:

SRCS := $(wildcard *.cpp */*.cpp)

DEPDIR := .d
DEPS := $(SRCS:%.cpp=$(DEPDIR)/%.d)

# Temporary .Td dependence file... ?
DEPFLAGS = -MT $@ -MD -MP -MF $(DEPDIR)/$*.Td

# Isn't it better a order-only prerequisite?
$(shell mkdir -p $(dir $(DEPS)) >/dev/null)

%.o: %.cpp # Removal of implicit rules... ? Twice?
%.o: %.cpp $(DEPDIR)/%.d  # Dependency on .d... ?
        g++ -o $@ $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c $<
        # Avoid some bugs?
        mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@

# If the `%.d` dependency is removed, is this still necessary?
.PRECIOUS = $(DEPDIR)/%.d
$(DEPDIR)/%.d: ;

-include $(DEPS)

为了不让这个问题太长时间深入讨论我为什么认为上面摘录中的所有注释都是不必要的,我将以简短的形式提出。如果我仅将此代码段更改为:

SRCS := $(wildcard *.cpp */*.cpp)
DEPDIR := .d
DEPS := $(SRCS:%.cpp=$(DEPDIR)/%.d)

DEPFLAGS := -MT $@ -MD -MP -MF $(DEPDIR)/$*.d

$(DEPDIR)/%:
        mkdir -p $@

%.o: %.cpp | $(DEPDIR)/$(dir %)
        g++ -o $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c $<
        # touch $(DEPDIR)/$.d # ??

-include $(DEPS)

我还有两个疑问:在上面的第一个链接中,它说

  

据报道,某些版本的GCC可能会离开目标文件   比依赖文件更早,这会导致不必要的重建。

但是,在gist(上面的第二个链接)中,touch命令已删除,并且由于依赖文件不再是任何规则的前提,是否有任何理由要保留它?此“ gcc错误”是否仍以任何形式适用?

第二个疑问与目录创建有关,已移至仅订购规则;是否需要制定“仅订购” $(DEPDIR)/%规则.PRECIOUS?我不知道如果make配方失败,%.o是否会尝试删除目录,因为我不知道仅订购规则的具体功能。

1 个答案:

答案 0 :(得分:1)

您无法删除%.d先决条件。 is explained在您链接的页面中是必需的。

我不知道您所说的意思是什么删除隐式规则...?两次?。需要删除隐式规则,以确保使用我们的新隐式规则,并且只删除一次。

临时文件.Td用于在创建此文件的过程中有人使用^ C或类似文件杀死其make job的情况。通过写入临时文件,然后仅在知道完整文件后就原子地替换实际文件,我们不必担心部分文件可能会导致下次调用make产生错误,或更糟糕的是,不重新编译应为重新编译。

关于与依赖文件相比更早的目标文件的注释,首先链接到的要旨使用clang而不是GCC,也许Clang没有这个问题(或者也许是这个问题,但是人们没有意识到这一点) )。其次,由于人们已通过GCC向我报告了此问题,因此博客帖子的更新相对较新。我自己还没有看到它(我只使用GCC),所以也许这只是某些版本的GCC的问题。

关于.PRECIOUSmake永远不会(当前)递归删除目录,因此无论该设置如何,它都不会删除任何非空目录。