Makefile Gnu自动生成依赖项

Makefile Gnu自动生成依赖项,makefile,dependencies,auto-generate,Makefile,Dependencies,Auto Generate,基于并改编自,并假设您的所有源文件都是.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-onl

基于并改编自,并假设您的所有源文件都是
.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:=$(通配符*.cpp*/*.cpp)
DEPDIR:=.d
DEPS:=$(SRCS:%.cpp=$(DEPDIR)/%.d)
#临时的.Td依赖文件?
DEPFLAGS=-MT$@-MD-MP-MF$(DEPDIR)/$*.Td
#这不是一个只有订单的先决条件吗?
$(shell mkdir-p$(dir$(DEPS))>/dev/null)
%.o:%.cpp#删除隐式规则?两次?
%.o:%.cpp$(DEPDIR)/%.d#依赖于.d?
g++-o$@$(DEPFLAGS)$(CXXFLAGS)$(CPPFLAGS)-c$<
#避免一些错误?
mv-f$(DEPDIR)/$*.Td$(DEPDIR)/$*.d&&touch$@
#如果删除了“%.d”依赖项,是否仍有必要?
.PRECIOUS=$(DEPDIR)/%.d
美元(DEPDIR)/%;
-包括美元(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)
SRCS:=$(通配符*.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$<
#触摸$(DEPDIR)/$.d#??
-包括美元(DEPS)
我还有两个额外的疑问;在上面的第一个链接中,它说

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

但是,在
gist
(上面的第二个链接)中,
touch
命令被删除,并且由于依赖文件不再是任何规则的先决条件,是否有任何理由继续包含它?这个“gcc错误”是否仍然以任何形式存在


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

您无法删除
%.d
先决条件。您链接的页面中需要此选项的原因

我不知道你对删除隐含规则的评论是什么意思?两次?。需要删除隐式规则,以确保使用新的隐式规则,并且只删除一次

临时文件<代码> TD.<代码>,以防有人使用^ C或类似的方法在创建该文件的过程中杀死他们的作业。通过写入一个临时文件,然后在我们知道真实文件已完成后,仅以原子方式替换真实文件,我们永远不必担心部分文件会导致下一次调用make生成错误,或者更糟糕的是,不会重新编译应重新编译的源文件

关于比依赖项文件更早的对象文件的注释,首先,您链接到的要点使用的是
clang
而不是GCC,而且clang可能没有这个问题(或者可能有,但人们没有意识到)。第二,博客文章的更新相对较新,因为有人用GCC向我报告了这个问题。我自己也没见过(我只使用GCC),所以可能这只是一些GCC版本的问题


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

关于“删除两次”注释,您又刚好低于相同的目标(好的,具有额外的.d依赖项)。为什么这不是多余的?第一个删除了内置模式,因为它没有配方。请参见第二行,这是使用新配方创建新模式规则的开始。它们根本不是一回事。好吧,我理解删除依赖项文件的问题,但它也会重新创建已更新的
.o
,并且会导致不必要的工作量,因为重新创建依赖项文件比编译要快得多。想想删除
main.d
的例子。对于这种情况,有什么更好的解决方案?我在考虑三个选项:只点
%.d
依赖项,
%.d
取决于
%.cpp
,这将使我们进入第1步,或者两个不同的配方,根据
%.cpp`是否在
$?
中,使用
%.d
先决条件,使用
ifeq。我看不出一个只点
%.d
的先决条件会有什么不同。很明显,你不能使用ifeq,因为这是一个make构造,不能在配方中使用。您必须使用shell条件或
$(if…
make函数。在我看来,这是一个针对罕见情况(人们不应该手动删除
.d
文件)的微型优化,而且不值得为避免编译步骤而增加复杂性。您可以在配方中添加make条件,但它将在解析makefile时进行计算,而不是在扩展配方时进行计算。这意味着您无法检查任何自动变量等的内容,因为它们在解析makefile时不可用,只有在稍后运行配方时才可用。因此,您不能使用这些语句来检查
$?
是否包含特定值:它将始终是空字符串。