MKDIR=mkdir
RM=rm
RMFLAGS=-rf
CC=gcc
DIR_OBJS=objs
DIR_EXES=exes
DIR_DEPS=deps
DIRS=$(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS)
EXE=complicated.exe
EXE:=$(addprefix $(DIR_EXES)/,$(EXE))
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS))
DEPS=$(SRCS:.c=.dep)
DEPS:=$(addprefix $(DIR_DEPS)/,$(DEPS))
#ifeq ("$(wildcard $(DIR_EXES))","")
# DEP_DIR_EXES := $(DIR_EXES)
#endif
#ifeq ("$(wildcard $(DIR_OBJS))", "")
# DEP_DIR_OBJS := $(DIR_OBJS)
#endif
ifeq ("$(wildcard $(DIR_DEPS))", "")
DEP_DIR_DEPS := $(DIR_DEPS)
endif
all:$(EXE)
include $(DEPS)
$(DIRS):
$(MKDIR) $@
$(EXE):$(DIR_EXES) $(OBJS)
$(CC) -o $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o:$(DIR_OBJS) %.c
$(CC) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep:$(DEP_DIR_DEPS) %.c
@echo "Making $@..."
@set -e; \
$(RM) $(RMFLAGS) $@; \
$(CC) -E -MM $(filter %.c,$^) > $@.tmp; \
sed 's,\(.*\)\.o[:]*,objs/\1.o:,g' < $@.tmp > $@; \
$(RM) $(RMFLAGS) $@.tmp
clean:
$(RM) $(RMFLAGS) $(DIRS)
这个是最终版。
$(DIR_OBJS)/%.o:$(DIR_OBJS) %.c
$(CC) -o $@ -c $(filter %.c,$^)
不会导致死循环,原因是文件$(DIR_OBJS)/%.o它不是由include这个命令包含进来的。
生成的objs/*.o文件也会改变objs目录的时间戳,这个改变objs目录的时间戳动作是在
生成objs/*.o文件之后发生的。但如果文件(如$(DIR_DEPS)/%.dep)是include包含进来的
,则执行完规则中的命令“ @echo "Making $@ ..."……$@.tmp”后,该文件还会再被包含
进来一次,以确保被包含的文件是最新的(这个是重点)。这样又会导致make检查对应规则,
发现$(DEPS_DIR_DEPS)目录比dep文件新,那又会执行一次……,这样就陷入了死循环。
而文件$(DIR_OBJS)/%.o不是由include这个命令包含进来的,所以不存在以上死循环问题。
$(EXE):$(DIR_EXES) $(OBJS)
$(CC) -o $@ $(filter %.o,$^)
也一样。 这个改变objs目录的时间戳动作是在生成objs/*.o文件之后发生的
那么假设有两个文件a.c,b.c
那么生成a.o以后其目录也会更新,那么a.o的时间戳比后边的时间戳早那么根据依赖关系其会更新那么不是继续死循环吗