Makefile 死循环

轮子学长 2014-08-01 10:29:56
模仿 李云的Makefile写的,添加include后死循环,
源文件 ./src/main.c ./src/foo.c ./src/foo.h
执行结果 在
$(DIR_DEPS)/%.dep:$(DIR_DEPS) $(DIR_SRCS)/%.c
@echo "Making $@..."
@set -e;\
$(RM) $(RMFLAGS) $@.tmp;\
$(CC) -E -MM $(filter %.c,$^) > $@.tmp;\
sed 's,\(.*\)\.o[:]*,$(DIR_OBJS)/\1.o:,g' < $@.tmp > $@;\
$(RM) $(RMFLAGS) $@.tmp
这里死循环了。。。Makefile源文件如下

Makefile[/color]
.PHONY:all clean

CC = gcc
RM = rm
RMFLAGS = -fr

MKDIR = mkdir
DIR_OBJS = objs
DIR_EXES = exes
DIR_SRCS = src
DIR_DEPS = deps
DIRS = $(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS)

EXE = exe
EXE := $(addprefix $(DIR_EXES)/, $(EXE))

SRCS := $(wildcard $(DIR_SRCS)/*.c)
OBJS := $(patsubst $(DIR_SRCS)/%.c,$(DIR_OBJS)/%.o,$(SRCS))
DEPS := $(patsubst $(DIR_SRCS)/%.c,$(DIR_DEPS)/%.dep,$(SRCS))

all: $(EXE)

-include $(DEPS)
-include $(DEPS)

$(DIRS):
$(MKDIR) $@

$(EXE): $(DIR_EXES) $(OBJS)
@echo "This is EXE"
@echo $@
$(CC) -o $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o:$(DIR_OBJS) $(DIR_SRCS)/%.c
$(CC) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep:$(DIR_DEPS) $(DIR_SRCS)/%.c
@echo "Making $@..."
@set -e;\
$(RM) $(RMFLAGS) $@.tmp;\
$(CC) -E -MM $(filter %.c,$^) > $@.tmp;\
sed 's,\(.*\)\.o[:]*,$(DIR_OBJS)/\1.o:,g' < $@.tmp > $@;\
$(RM) $(RMFLAGS) $@.tmp
clean:
$(RM) $(RMFLAGS) $(DIRS)

...全文
1061 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
xirurensheng_123 2016-08-05
  • 打赏
  • 举报
回复
引用 6 楼 baidu_34049639 的回复:
[quote=引用 5 楼 colabean 的回复:] 完善一下: .PHONY:all clean 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,$^) 也一样。
如何取消目录的依赖关系?上面好像没有提到这一点。[/quote] 你好问下你按照你说的 这个改变objs目录的时间戳动作是在生成objs/*.o文件之后发生的 那么假设有两个文件a.c,b.c 那么生成a.o以后其目录也会更新,那么a.o的时间戳比后边的时间戳早那么根据依赖关系其会更新那么不是继续死循环吗
baidu_34049639 2016-07-11
  • 打赏
  • 举报
回复
引用 5 楼 colabean 的回复:
完善一下: .PHONY:all clean 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,$^) 也一样。
如何取消目录的依赖关系?上面好像没有提到这一点。
colabean 2016-02-24
  • 打赏
  • 举报
回复
完善一下: .PHONY:all clean 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,$^) 也一样。
colabean 2016-02-24
  • 打赏
  • 举报
回复
其原因是:因为.dep文件的创建会造成存放.dep文件的目录的时间戳也发生改变,于是Makefile认为目录的变化需要重新构建.dep文件,于是进入了死循环。解决的方法很简单,就是在发现存放.dep文件的目录已存在时,就不让.dep文件依赖于目录。 .PHONY:all clean 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):$(DEP_DIR_EXES) $(OBJS) $(CC) -o $@ $(filter %.o,$^) $(DIR_OBJS)/%.o:$(DEP_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) 注意后面的$(RM) $(RMFLAGS) $@; \ 有的会写成$(RM) $(RMFLAGS) $@.tmp; \ 其实根据上下文,应该是要删除之前已经存在的dep文件。 $@.tmp这个临时文件在下面已经被删除了。
xxb249 2014-12-11
  • 打赏
  • 举报
回复
我也遇到这个问题啦 我知道问题原因,但是不知道怎么修改。 问题原因是 在同一个src目录中只能有一个.c 如果有两个或者两个以上.c 就会出现 不断创建依赖文件!!! 我不会修改啊。。。。。。。。。。
zhxianbin 2014-08-01
  • 打赏
  • 举报
回复
sed 's,\(.*\)\.o[:]*,$(DIR_OBJS)/\1.o:,g' < $@.tmp > $@;\ 这是干啥,看不懂
colddown 2014-08-01
  • 打赏
  • 举报
回复
把DIR_DEPS从条件中去掉,手工建立该目录

2,163

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 UNIX文化
社区管理员
  • UNIX文化社区
  • 文天大人
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧