[英]Makefile builds target every time
我编写了一个makefile来编译不同目录中的所有源代码并构建目标。 当我运行make时,即使文件没有变化,它也不会重新编译未修改的文件。 但是,它总是建立目标。 为什么每次运行make时都会单独构建目标?
CC = gcc
CFLAGS = $(INCLUDES)
TARGET = FinalBin
OUTDIR := obj
INCLUDES = -Isrc/in
S1 = src/s1
S2 = src/s2
S1_SRC = $(wildcard $(S1)/*.c)
S2_SRC = $(wildcard $(S2)/*.c)
SRCS := $(S1_SRC) \
$(S2_SRC)
OBJS := $(patsubst %.c,$(OUTDIR)/%.o,$(SRCS))
SRCDIRS := $(S1) $(S2)
all: $(TARGET)
$(TARGET): builddir $(OBJS)
@echo "Building..." $@
@$(CC) $(OBJS) $(CFLAGS) -o $@
@echo "Build Complete!"
$(OUTDIR)/%.o: %.c
@echo "Compiling.." $(notdir $<)
@$(CC) $(CFLAGS) -MMD -c $< -o $@
clean:
-@rm -rf $(OUTDIR) FinalBin
@echo "Clean complete!"
builddir :
@$(call create-dir)
define create-dir
for dir in $(SRCDIRS); \
do \
mkdir -p $(OUTDIR)/$$dir; \
done
endef
-include $(wildcard $(OBJS:.o=.d))
$(TARGET)每次都是从目标文件构建的。 请指导我哪里出错了。
更新:
CC = gcc
CFLAGS = $(INCLUDES)
TARGET = FinalBin
OUTDIR := obj
INCLUDES = -Isrc/in
S1 = src/s1
S2 = src/s2
S1_SRC = $(wildcard $(S1)/*.c)
S2_SRC = $(wildcard $(S2)/*.c)
SRCS := $(S1_SRC) \
$(S2_SRC)
OBJS := $(patsubst %.c,$(OUTDIR)/%.o,$(SRCS))
SRCDIRS := $(S1) $(S2)
OUTDIRS := $(addprefix $(OUTDIR)/,$(SRCDIRS))
all: $(TARGET)
$(TARGET): $(OBJS)
@echo "Building..." $@
@$(CC) $(OBJS) $(CFLAGS) -o $@
@echo "Build Complete!"
$(OUTDIR)/%.o: $(OUTDIRS) %.c
@echo "Compiling.." $(notdir $(filter %.c,$^))
@$(CC) $(CFLAGS) -MMD -c $(filter %.c,$^) -o $@
clean:
-@rm -rf $(OUTDIR) FinalBin
@echo "Clean complete!"
$(OUTDIRS):
mkdir -p $@
builddir :
@$(call create-dir)
define create-dir
for dir in $(SRCDIRS); \
do \
mkdir -p $(OUTDIR)/$$dir; \
done
endef
-include $(wildcard $(OBJS:.o=.d))
这会每次构建所有文件。
最终解决方案
CC = gcc
CFLAGS = $(INCLUDES)
TARGET = FinalBin
OUTDIR := obj
INCLUDES = -Isrc/in
S1 = src/s1
S2 = src/s2
S1_SRC = $(wildcard $(S1)/*.c)
S2_SRC = $(wildcard $(S2)/*.c)
SRCS := $(S1_SRC) \
$(S2_SRC)
OBJS := $(patsubst %.c,$(OUTDIR)/%.o,$(SRCS))
SRCDIRS := $(S1) $(S2)
OUTDIRS := $(addprefix $(OUTDIR)/,$(SRCDIRS))
all: $(TARGET)
$(TARGET): $(OUTDIRS) $(OBJS)
@echo "Building..." $@
@$(CC) $(OBJS) $(CFLAGS) -o $@
@echo "Build Complete!"
$(OUTDIR)/%.o: %.c
@echo "Compiling.." $(notdir $<)
@$(CC) $(CFLAGS) -MMD -c $< -o $@
clean:
-@rm -rf $(OUTDIR) FinalBin
@echo "Clean complete!"
$(OUTDIRS):
@mkdir -p $@
-include $(wildcard $(OBJS:.o=.d))
最终解决方案按预期工作!
您可以使用make的调试输出来查找它认为需要重建的内容:
make -d | grep remake
你可能会看到这样的东西:
No need to remake target `Makefile'.
Must remake target `builddir'.
No need to remake target `src/s1/x.c'.
No need to remake target `obj/src/s1/x.o'.
Must remake target `FinalBin'.
Must remake target `all'.
这表明它总是认为builddir
目标需要重新制作。 由于这是$(TARGET)
的依赖,它也会重建后者。
如果您使用规则来创建构建目录而不是函数, make
将知道它是否需要创建它们。 例如,添加变量$(OUTDIRS)
,它的规则,并使其成为编译的依赖:
SRCDIRS := $(S1) $(S2)
OUTDIRS := $(addprefix $(OUTDIR)/, $(SRCDIRS)) # <---------- Add this variable
All: $(TARGET)
$(TARGET): $(OBJS)
@echo "Building..." $@
@$(CC) $(OBJS) $(CFLAGS) -o $@
@echo "Build Complete!"
$(OUTDIR)/%.o: $(OUTDIRS) %.c # <--------------------------- Add dependency to $(OUTDIRS)
@echo "Compiling.." $(notdir $<)
@$(CC) $(CFLAGS) -MMD -c $< -o $@
clean:
-@rm -rf $(OUTDIR) FinalBin
@echo "Clean complete!"
$(OUTDIRS): # <--------------------------------------------- Add rule
mkdir -p $@
-include $(wildcard $(OBJS:.o=.d))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.