Makefile参考样例3:多个文件夹.c的编译

上一篇的Makefile写得太过复杂,且不支持同名.c文件,因此经过改良后,又来一发Makefile参考样例3;

优点:代码简洁,容易解理,能自动检查头文件依赖关系,支持不同文件夹下面有相同的文件名的.c文件;

缺点:所有编译的中间文件与源码在同一路径,会造成一些文件污染,好在make clean可以干净地清除这些中间文件;

代码如下:

#这是一个makefile的样例,用于编译多文件夹,多文件的编译

#编译工具链
CC	= gcc
CXX	= g++
LD	= $(CC)
AS	= nasm

#编译选项
ASFLAGS  = -m32
CFLAGS   = -m32 -Wall $(incdir)	 
CXXFLAGS = -m32 -Wall $(incdir)
LDFLAGS	 = -m32 -static

#定义输出文件名
target = main.exe

#定义源码目录
srcdir = src \
         src/dir1 \
         src/dir2 \
         src/dir2/sub1 \
         src/dir2/sub2

#定义包含目录
incdir = $(foreach dir,$(srcdir),-I$(dir))

#定义附加依赖库
inclib = -lpthread

#遍历所有dir,并搜索该dir下面的所有.c文件
allsrc = $(foreach dir,$(srcdir),$(wildcard $(dir)/*.c))

#把所有的.c替换为.o
allobj = $(allsrc:%.c=%.o)

#把所有的.c替换为.d
alldep = $(allsrc:%.c=%.d)

#生成.d的规则
%.d: %.c
	@echo Generating $@...
	@$(CC) -MM -MT "$(<D)/$(*F).o $@" $(CFLAGS) $< >$@
	
#生成.o的规则
%.o: %.c
	@echo Compiling $<...
	@$(CC) $(CFLAGS) -c $< -o $@


#如果不是第1次调用make,则包含所有.d文件	
ifneq ($(MAKELEVEL), 0)
include $(alldep)
endif

#声明虚拟目标
.PHONY:	init clean

init: $(alldep)
	@$(MAKE) -s $(target)

ifneq ($(MAKELEVEL), 0)
$(target): $(alldep) $(allobj)
	@echo Linking target...
	@$(LD) $(LDFLAGS) -o $@ $(allobj) $(inclib)
	@echo Link done!
endif

clean:
	@rm -rf $(alldep) $(allobj) $(target)
	@echo clean done.