【发布时间】:2023-03-16 14:33:01
【问题描述】:
如果包含的目标已过期或不存在,我希望包含指令触发构建规则。
目前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 要么没有获得依赖列表,要么总是从中获取 make.deps上一个版本,而不是当前版本。
例如:
$ 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 不能 在这些目录中的任何一个中找到, 生成警告消息,但它 不是立即致命的错误; 处理包含 包括继续。一旦有了 读完makefile,make会 尝试重新制作任何过时的东西 或者不存在。请参阅如何 Makefile 被重新制作。只有在它之后 试图找到一种方法来重新制作 makefile 并失败,将制作 将丢失的 makefile 诊断为 致命错误。
回答
这是对我接受的答案的修改。缺少的一件事是依赖文件也依赖于源文件,除非将它们添加到包含的 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
我从这篇关于递归 make 的危险的惊人论文中得到了这个想法:
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
【问题讨论】:
-
如果你还没有,你可能应该看看这个:theory.uwinnipeg.ca/localfiles/infofiles/make/…