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

优点:可以很好地解决.h头文件依赖问题,修改任意头文件,会自动重新编译对应的c文件;

缺点:在不同的文件夹下面不能有同名的c文件!

源码目录结构如下:

src
├─main.c
├─dir1
│ ├─file11.c
│ ├─file11.h
│ ├─file12.c
│ └─file12.h
└─dir2
    ├─sub1
    │  ├─file211.c
    │  ├─file211.h
    │  ├─file212.c
    │  └─file212.h
    └─sub2
        ├─file221.c
        ├─file221.h
        ├─file222.c
        └─file222.h

这个Makefile理解起来有点麻烦,Make进行了递归调用,第1次生成depend文件,第2次进行编译和链接.代码如下:

#|这是一个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

#定义输出根目录
objdir = obj/

#定义源码根目录
srcdir = src/

#定义所有的文件夹和需要编译的目标文件
alldir = . dir1 dir2 \
	     dir2/sub1 dir2/sub2

#定义所有文件
allsrc = main.c\
         file11.c file12.c\
         file211.c file212.c\
		 file221.c file222.c

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

#定义连接依赖库
inclib = -lpthread

#配置搜索路径
vpath %.c	$(foreach dir,$(alldir),$(srcdir)$(dir)/ )
vpath %.h	$(foreach dir,$(alldir),$(srcdir)$(dir)/ )
vpath %.o 	$(foreach dir,$(alldir),$(objdir)$(dir)/ )
vpath %.d 	$(foreach dir,$(alldir),$(objdir)$(dir)/ )

#所有依赖关系
autdep = $(allsrc:.c=.d)
autobj = $(allsrc:.c=.o)

#所有目标
allobj = $(foreach file,$(allsrc), \
		 $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
		 $(firstword $(subst .c,.o,$(wildcard $(srcdir)$(dir)/$(file)))))))

alldep = $(foreach file,$(allsrc), \
		 $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
		 $(firstword $(subst .c,.d,$(wildcard $(srcdir)$(dir)/$(file)))))))


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

#定义虚拟目标
ifeq ($(MAKELEVEL), 0)
all: init $(autdep)
	@echo $(MAKELEVEL) make done.
	@$(MAKE) all
else
all: $(autobj) $(target)
	@echo $(MAKELEVEL) make done.
endif

init:
	@mkdir -p $(foreach dir, $(alldir),$(objdir)$(dir))
	
clean:
	@rm -rf $(objdir) $(target)
	@echo clean done.
	
#生成d文件
%.d: %.c
	@echo $(MAKELEVEL) Generating depend file for $<...
	@$(CC) -MM -MT "$(subst $(srcdir),$(objdir),$(<D))/$(*F).o $(subst $(srcdir),$(objdir),$(<D))/$(@F)" -x c++ $(CXXFLAGS) $< >$(subst $(srcdir),$(objdir),$(<D))/$(@F)

ifeq ($(MAKELEVEL), 1)
%.o:
	@echo $(MAKELEVEL) Compiling $<...
	@$(CC) $(CFLAGS) -c $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F)
else
%.o: %.c
	@echo $(MAKELEVEL) Compiling $<...
	@$(CC) $(CXXFLAGS) -c $< -o $@
endif


ifeq ($(MAKELEVEL), 1)
include	$(alldep)

$(target): $(allobj)
	@echo Linking executable... $(target)
	@$(LD) $(LDFLAGS) -o $@ $^ $(inclib)
endif