1. 首先把shell命令定义成变量
2. 写出各目标的路径
3. 写出各目标
4. 把目标加到各自的路径中
5. 避免死循环加上条件判断(注意用wildcard函数)
6. 写出规则
7.为了保证在make clean时不创建.d文件,为include加上条件判断
下面是一个示例makefile源码:
#phony target
.PHONY: clean all
#shell variable
GCC = gcc
RM = rm
RMFLAGS = -fr
MKDIR = mkdir
AR = ar
ARFLAGS = scr
#path of build
DIR_EXES = ../../../build/exes
DIR_LIBS = ../../../build/libs
#path of foo's src
DIR_OBJS = objs
DIR_DEPS = deps
DIRS = $(DIR_EXES) $(DIR_LIBS) $(DIR_OBJS) $(DIR_DEPS)
RMS = $(DIR_OBJS) $(DIR_DEPS)
#target
LIBS = libfoo.a
EXES =
SRC = $(wildcard *.c)
OBJS = $(SRC:.c=.o)
DEPS = $(SRC:.c=.d)
#add targets into their file
OBJS := $(addprefix $(DIR_OBJS)/,$(OBJS))
DEPS := $(addprefix $(DIR_DEPS)/,$(DEPS))
ifneq ($(LIBS),)
LIBS := $(addprefix $(DIR_LIBS)/,$(LIBS))
RMS += $(LIBS)
endif
ifneq ($(EXES),)
EXES := $(addprefix $(DIR_EXES)/,$(EXES))
RMS += $(EXES)
endif
#avoid infinite loop
ifeq ($(wildcard $(DIR_OBJS)),)
DEP_DIR_OBJS = $(DIR_OBJS)
endif
ifeq ($(wildcard $(DIR_DEPS)),)
DEP_DIR_DEPS = $(DIR_DEPS)
endif
ifeq ($(wildcard $(DIR_EXES)),)
DEP_DIR_EXES = $(DIR_EXES)
endif
ifeq ($(wildcard $(DIR_LIBS)),)
DEP_DIR_LIBS = $(DIR_LIBS)
endif
#rule
all: $(EXES) $(LIBS)
ifneq ($(MAKECMDGOALS),clean)
include $(DEPS)
endif
$(DIRS):
$(MKDIR) $@
$(EXES): $(DEP_DIR_EXES) $(OBJS)
$(GCC) -o $@ $(filter %.o,$^)
$(LIBS): $(DEP_DIR_LIBS) $(OBJS)
$(AR) $(ARFLAGS) $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o: $(DEP_DIR_OBJS) %.c
$(GCC) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.d: $(DEP_DIR_DEPS) %.c
@echo "Create $@ ..."
@set -e; \
$(RM) $(RMFLAGS) $@.tmp; \
$(GCC) -E -MM $(filter %.c,$^) >$@.tmp; \
sed 's,\(.*\)\.o[ :]*,objs/1.o $@: ,g' <$@.tmp >$@; \
$(RM) $(RMFLAGS) $@.tmp
clean:
$(RM) $(RMFLAGS) $(RMS)