接着上一篇
顶级目录Makefile.build
PHONY := __build
__build:
obj-y :=
subdir-y :=
include Makefile
# obj-y := a.o b.o c/ d/
# $(filter %/, $(obj-y)) : c/ d/
# __subdir-y : c d
# subdir-y : c d
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
# c/built-in.o d/built-in.o
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)
# a.o b.o
cur_objs := $(filter-out %/, $(obj-y))
dep_files := $(foreach f,$(cur_objs),.$(f).d)
dep_files := $(wildcard $(dep_files))
ifneq ($(dep_files),)
include $(dep_files)
endif
PHONY += $(subdir-y)
__build : $(subdir-y) built-in.o
$(subdir-y):
make -C $@ -f $(TOPDIR)/Makefile.build
built-in.o : $(cur_objs) $(subdir_objs)
$(LD) -r -o $@ $^
dep_file = .$@.d
%.o : %.c
$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<
.PHONY : $(PHONY)
PHONY := __build
__build:
上面的语法定义一个伪目标
obj-y := #目标文件变量
subdir-y := #字母文件变量
上面两个语句定义了两个变量,但赋空值,这是因为下面的语句
include Makefile
包括当前目录下的Makefile,而当前目录下的Makefile是有各级子目录定义的,子目录的Makefile的内容就是该目录中需要编译的文件和子目录,#表示注释
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
filter函数:在$(obj-y)中提取格式为%/的内容,%是一个通配符;patsubst函数:filter提取出来的内容,按照指定格式子替换,此处是把%/格式的内容,替换为%,即去掉了/
ifneq ($(dep_files),)
include $(dep_files)
endif
如果没有include 变量的内容,就include一下。
PHONY += $(subdir-y)
以上语句将子目录定义为伪目标,伪目标一不生成真正的目标文件,二他只是用来执行其规则下面的命令而已。伪目标可以称之为标签。
__build : $(subdir-y) built-in.o
依赖关系伪目标__build,依赖文件为$(subdir-y) built-in.o,根据Makefile语法,检查依赖文件是否最新或者是否存在,如果存在,则跳过下一个语句。如果不存在,则在文件中找到生成该文件的规则来中执行。那么此时可以执行以下规则:
$(subdir-y):
make -C $@ -f $(TOPDIR)/Makefile.build
这段意思为用根目录下的Makefile.build来对目标文件指定的目录进行执行make命令, 自身调用自身形成递归调用,直到该目录下没有子目录。然后执行下面的语句:
built-in.o : $(cur_objs) $(subdir_objs)
$(LD) -r -o $@ $^
上面这条规则是,如果子目录不存在,即$(subidir_objs)为空,则把当前文件夹下的依赖文件用LD链接命令,链接为一个built-in.o文件,如果存在子目录,则把子目录的built-in.o文件和当前文件夹下的依赖文件一块链接成built-in.o文件。
dep_file = .$@.d
%.o : %.c
$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<
上面的规则对应的是,首先依赖文件%.o文件,而%.o文件不存在时,则用这条规则下的命令生成由对应的%.c文件生成%.o文件以及依赖文件。这条命令生成的有,.%.o.d和%.o文件,%是通配符。
最后,Makefile.build重点理解它的递归性质,顶级目录下Makefile调用一个Makefile.buld ,然后这个Makefile.build调用形成递归,先进入最底层目录把整个文件夹编译链接为build-in.o,然后再和上一级目录的所有.o文件链接形成build-in.o直到顶级目录形成目标文件。
子目录的Makefile明天说吧...挺简单的