我正在尝试为一些简单的C项目创建GNU make构建环境。我已经制作了makefile来编译源代码,将依赖项,objs和libs放在生成目录中,并将目标放在bin目录中。我能够生成所需的输出。问题是,即使我没有更改任何源,只要我运行使所有规则都执行即可。
这是我的目录结构
https://i.ibb.co/Cssyw2k/Capture.png
mkdefs.mk
CFLAGS := -O0 -g
CC := /usr/bin/gcc
BUILD_DIR = build_dbg
BIN_DIR = bin
MAKENOISE = echo
IN_BUILD_DIR = 0
mkrules.mk
CFLAGS += -I $(LINCS)
CPPFLAGS += $(CFLAGS)
ifneq (,$(EXE_TARGET))
$(EXE_TARGET) : $(CFILES:.c=.d) $(CFILES:.c=.o) $(CFILES) | bin_dir
@$(MAKENOISE) "linking $(filter-out %.c,$(filter-out %.d, $^))"
$(CC) $(addprefix $(BUILD_DIR)/,$(filter-out %.c,$(filter-out %.d, $^))) $(LLIBS) $(LOPTS) -o $(BIN_DIR)/$@
endif
%.d : %.c | build_dir
@$(MAKENOISE) "Generating dependencies of $<"
@cd $(BUILD_DIR); \
set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)/\1.o $(BUILD_DIR)/$@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$ ; \
-include $(addprefix $(BUILD_DIR)/, $(CFILES:.c=.d))
%.o : %.c
@$(MAKENOISE) "compiling $<"
@$(CC) $(CPPFLAGS) -c $< -o $(BUILD_DIR)/$@;
bin_dir :
@mkdir -p $(BIN_DIR)
build_dir :
@mkdir -p $(BUILD_DIR)
makefile
include ../../rules/mkdefs.mk
EXE_TARGET = show_bytes
vpath show_bytes.c /home/teja/proj/csapp/show_bytes/src
vpath main.c /home/teja/proj/csapp/show_bytes/src
CFILES += show_bytes.c main.c
LINCS += ./inc
include ../../rules/mkrules.mk
https://i.ibb.co/84djxd1/image.png
我期望当我第二次运行make时,应该不执行任何操作,因为所有文件都已更新。但是每次运行时,所有规则都将再次执行。
编辑:
因此,按照@MadScientist在评论中的建议进行了深入研究之后。我理解了这个问题,make文件正在当前目录中搜索.o和.d文件,而它们在build目录中。由于make在当前目录中找不到文件,因此每次我运行make时都会重新编译。以下是修改后的文件:
mkrules.mk
ifneq (,$(EXE_TARGET))
$(BIN_DIR)/$(EXE_TARGET) : $(DEP_FILES) $(OBJ_FILES) $(CFILES)
@test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
@$(MAKENOISE) "linking $(filter-out %.c,$(filter-out %.d, $^))"
@$(CC) $(filter-out %.c,$(filter-out %.d, $^)) $(LLIBS) $(LOPTS) -o $@
endif
$(DEP_FILES) : $(BUILD_DIR)/%.d : %.c
@-test -d $(BUILD_DIR) || mkdir -p $(BUILD_DIR)
@$(MAKENOISE) "Generating dependencies of $<"
@set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)/\1.o $(BUILD_DIR)/$@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$ ; \
-include $(addprefix $(BUILD_DIR)/, $(CFILES:.c=.d))
$(OBJ_FILES) : $(BUILD_DIR)/%.o : %.c
@test -d $(BUILD_DIR) || mkdir -p $(BUILD_DIR)
@$(MAKENOISE) "compiling $<"
@$(CC) $(CPPFLAGS) -c $< -o $@;
.PHONY: clean
clean :
rm -rf $(BUILD_DIR) $(BIN_DIR)
mkdefs.mk
CFLAGS = -O0 -g
CPPFLAGS =
CC := /usr/bin/gcc
BUILD_DIR = build_dbg
BIN_DIR = bin
MAKENOISE = echo
CFLAGS += -I $(LINCS)
CPPFLAGS += $(CFLAGS)
DEP_FILES = $(addprefix $(BUILD_DIR)/,$(CFILES:.c=.d))
OBJ_FILES = $(addprefix $(BUILD_DIR)/,$(CFILES:.c=.o))