一个通用的Makefile

时间:2021-11-20 12:43:31
 平时做项目的时候总是缺不了Makefile,不过都是别人写好的,俺只是在上面修修补补而已,尤其是代码一多的时候,Makefile互相嵌套,要想一下子搞清楚,还是的费一番功夫的。下面是俺周末的时候写的一个通用的Makefile,支持增量编译和多层目录编译。
  Project代码的构架:
       Project Name ----> include -> .h
                     | 
                     |--> src     -> .c Makefile
                     |
                     |--> .output ----> bin
                                   |
                                   |--> depend
                                   |
                                   |--> obj 
 
####################################################  
#子目录
SUBDIRS =
#最终bin目录里面的内容   
TARGET = ch2freq
#在这里可以定义一些宏
DEFINES =
#clean时用的指令
RM = rm
#编译器
CC = gcc
#编译参数设定
CFLAGS = -g -D_DEBUG
#头文件搜索顺序
INCLUDES :=   -I include -I ../include
#自动查找当前目录下的所有.c文件, 好处是添加.c文件的时候不需要更改Makefile
CSRCS ?= $(wildcard *.c)
#定义输出目录结构
ODIR := ../.output
OBJODIR := $(ODIR)/obj
LIBODIR := $(ODIR)/lib
BINODIR := $(ODIR)/bin
DEPODIR := $(ODIR)/dep
#定义相互关联性
OBJS := $(CSRCS:%.c=$(OBJODIR)/%.o)
TARGET:= $(BINODIR)/$(TARGET)
DEPS := $(CSRCS:%.c=$(DEPODIR)/%.d)
CFLAGS = $(CFLAGS) $(DEFINES) $(INCLUDES)
####################################################
#make 顺序 begin->.subdir->*.obj->target->end
all: begin .subdirs $(OBJS) $(TARGET) end

clean:
 $(foreach d, $(SUBDIRS), $(MAKE) -C $(d) clean;)
 $(RM) -rf $(ODIR)
clobber:
 $(foreach d, $(SUBDIRS), $(MAKE) -C $(d) clobber;)
 $(RM) -rf $(ODIR)
begin:
 @echo --------begin-----------
end:
 @echo --------end-------------
 
gccversion:
 @$(CC) --version
.subdirs:
 @echo .subdirs begin                          
 @set -e; $(foreach d, $(SUBDIRS), $(MAKE) -C $(d);)
 @echo .subdirs end
 
#注意在这里,先include .d文件,由于第一次make时不存在这个.d文件,所有
#make的第一步就是生成.d文件
ifdef DEPS
sinclude $(DEPS)
endif
#生成.d 文件的依赖关系
$(DEPODIR)/%.d: %.c
 @mkdir -p $(DEPODIR)
 @echo DEPEND: $(CC) -M $(CFLAGS) $<
 @set -e; rm -f $@; /
 $(CC) -M $(CFLAGS) $< > $@.$$$$; /
 sed 's,/($*/.o/)[ :]*,$(OBJODIR)//1 $@ : ,g' < $@.$$$$ > $@; /
 rm -f $@.$$$$
#生成 .o 文件
$(OBJODIR)/%.o: %.c
 @mkdir -p $(OBJODIR);
 $(CC) $(CFLAGS) -o $@ -c $<
#生成最终的target
$(TARGET) : $(OBJS)
 @mkdir -p $(BINODIR);
 $(CC) -o $@ $^