如果包含的目标已过期或不存在,我希望构建规则由include指令触发。
目前makefile看起来像这样:
program_NAME := wget++
program_H_SRCS := $(wildcard *.h)
program_CXX_SRCS := $(wildcard *.cpp)
program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
program_OBJS := $(program_CXX_OBJS)
DEPS = make.deps
.PHONY: all clean distclean
all: $(program_NAME) $(DEPS)
$(program_NAME): $(program_OBJS)
$(LINK.cc) $(program_OBJS) -o $(program_NAME)
clean:
@- $(RM) $(program_NAME)
@- $(RM) $(program_OBJS)
@- $(RM) make.deps
distclean: clean
make.deps: $(program_CXX_SRCS) $(program_H_SRCS)
$(CXX) $(CPPFLAGS) -MM $(program_CXX_SRCS) > make.deps
include $(DEPS)
问题在于,似乎include规则在构建make.deps的规则之前执行,这实际上意味着如果make.deps不存在或者始终从make.deps获取make,则要么不获取依赖关系列表上一个版本,而不是当前版本。
例如:
$ make clean
$ make
makefile:32: make.deps: No such file or directory
g++ -MM addrCache.cpp connCache.cpp httpClient.cpp wget++.cpp > make.deps
g++ -c -o addrCache.o addrCache.cpp
g++ -c -o connCache.o connCache.cpp
g++ -c -o httpClient.o httpClient.cpp
g++ -c -o wget++.o wget++.cpp
g++ addrCache.o connCache.o httpClient.o wget++.o -o wget++
修改
我读了docs for the include directive,听起来如果包含目标不存在,它将继续处理父makefile尝试并构建目标,但我不完全清楚这是如何工作的:
如果包含的makefile不能 在任何这些目录中找到,a 生成警告消息,但它 不是一个立即致命的错误; 处理包含的makefile 包括继续。一旦它有了 完成阅读makefile,make will 尝试重新制作任何过时的东西 或者不存在。见节如何 Makefile是重制的。只有在它之后 我试图找到一种方法来重拍 makefile和失败,将使 将缺少的makefile诊断为 致命的错误。
ANSWER
这是我接受的答案的修改。缺少的一件事是依赖文件也依赖于源,并且除非将它们添加到包含的deps文件中,否则不会重新生成:
%.d: $(program_CXX_SRCS)
@ $(CXX) $(CPPFLAGS) -MM $*.cpp | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' > $@
sed
将.d
文件的名称添加到每个依赖关系行的开头,如下所示:
foo.d foo.o: foo.cpp foo.h bar.h baz.h
我从这篇关于递归制作的危险的惊人论文中得到了这个想法:
Recursive Make Considered Harmful
我还将以下内容添加到makefile中:
clean_list += ${program_SRCS:.c=.d}
# At the end of the makefile
# Include the list of dependancies generated for each object file
# unless make was called with target clean
ifneq "$(MAKECMDGOALS)" "clean"
-include ${program_SRCS:.c=.d}
endif
答案 0 :(得分:2)
您依靠隐式规则来编译.cpp文件。您必须重新定义它以使用将创建依赖项文件的-MM和-MF标志。
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ -MM -MF $@.d
然后,您必须使用-include
在Makefile中包含这些依赖项文件,这些文件在依赖项文件尚不存在时(第一次或在干净之后)不会出错。
program_DEPS := $(program_OBJS:.o=.o.d)
-include $(program_DEPS)
请记住在clean规则中为依赖项文件添加rm命令。
答案 1 :(得分:2)
我花了一段时间才掌握的重点是上一版本的make.deps足够好。考虑一下:对于给定的目标文件,依赖项文件列表可以更改的唯一方法是...是否已更改其中一个旧的依赖项文件。如果是这种情况,那么旧的make.deps将导致重建该目标文件,如果重建目标文件也重建make.deps,那么一切都将是最新的。 在检查哪些对象必须重建之前,您不必重建make.deps。
答案 2 :(得分:0)
include指令的工作方式与它们在C和C ++中的工作方式相同 - 它们在发生任何其他事件之前进行处理,以构建生成然后进程的“真实”makefile。具体来说,它们在任何规则被触发之前被处理。