查看 make rpi_defconfig 的执行过程
由于带了命令 rpi_defconfig,所以
ifeq ($(KBUILD_EXTMOD),)
ifneq ($(filter config %config,$(MAKECMDGOALS)),)
config-targets := 1
ifneq ($(words $(MAKECMDGOALS)),1)
mixed-targets := 1
endif
endif
endif
config-targets=1
执行匹配顶层Makefile中 if config-targets里面的内容
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
依赖于 scripts_basic outputmakefile。
再展开后面命令为 ($(build)在include scripts/Kbuild.include中定义)
@make -f ./scripts/Makefile.build obj=scripts/kconfig rpi_defconfig
先处理依赖
1 scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
展开执行第一句
@make -f ./scripts/Makefile.build obj=scripts/basic
Makefile.build中执行的是
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
@:
KBUILD_BUILTIN在顶层makefile中被定义为1。
初始时候什么都没有配置。所以
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a
endif
ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
builtin-target := $(obj)/built-in.o
endif
都为空。
KBUILD_MODULES配置为空。
subdir-ym在include Makefile.lib里面
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
subdir-m += $(__subdir-m)
subdir-ym := $(sort $(subdir-y) $(subdir-m))
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
obj-y和obj-m都为空
subdir-ym也为空
在看always由于在前面有
prefix := tpl
src := $(patsubst $(prefix)/%,%,$(obj))
$(patsubst PATTERN,REPLACEMENT,TEXT)
搜索TEXT中用空格分开的单词。如果符合PATTERN。那么将PATTERN替换成REPLACEMENT
从$(obj)中寻找以tpl/开头字符串。用后面的部分替换。其实也就是如果有tpl/开头的。那么去掉 tpl/
这里$(obj)=scripts/basic
所以src=scripts/basic
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
$(filter PATTERN...,TEXT);
过滤掉TEXT当中不符合PATTERN的字符串
$(if condition,then,else)
如果条件满足返回then.否则返回else
也就是判断$(src)是不是以/开头的绝对路径。如果是,返回$(src)。否则返回$(srctree)/$(src)。
这里
$(src)=scripts/basic
$(srctree)=.
返回的是./scripts/basic
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
$(wildcard PATTERN) 返回当前目录满足PATTERN的文件名
先查看./scripts/basic/Kbuild是否存在。如果存在。返回./scripts/basic/Kbuild。否则返回./scripts/basic/Makefile
include $(kbuild-file)
包含这个 $(kbuild-file)
这里就是 include ./scripts/basic/Makefile
hostprogs-y := fixdep
always := $(hostprogs-y)
# fixdep is needed to compile other host programs
$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
这里always= $(hostprogs-y)=fixdep
filter-out是保留不符合pattern的。
$(filter-out fixdep,$(always))为NULL
$(addprefix $(obj)/,$(filter-out fixdep,$(always))) 也为NULL
所以always为fixdep
也就是构建fixdep,在scripts/basic/Makefile中有
hostprogs-y := fixdep
又在Makefile.build中有
ifneq ($(hostprogs-y)$(hostprogs-m),)
include scripts/Makefile.host
endif
因此包含了 Makefile.host。在Makefile.host中
__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
# C code
# Executables compiled from a single .c file
host-csingle := $(foreach m,$(__hostprogs), \
$(if $($(m)-objs)$($(m)-cxxobjs)$($(m)-sharedobjs),,$(m)))
host-csingle 表示在本机运行的由单一的c文件编译的。因此fixdep在这里面。
构建fixdep
$(host-csingle): $(obj)/%: $(src)/%.c FORCE
$(call if_changed_dep,host-csingle)
调用if_changed_dep。这个函数在Kbuild.include里面。
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
@set -e; \
$(echo-cmd) $(cmd_$(1)); \
scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\
rm -f $(depfile); \
mv -f $(dot-target).tmp $(dot-target).cmd)
$(cmd_$(1));也就是执行cmd_host-csingle
cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
具体指令后续再看
后续还调用了fixdep。
2 依赖outputmakefile
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree) source
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
由于KBUILD_SRC为NULL。所以这一部分不执行
3执行 @make -f ./scripts/Makefile.build obj=scripts/kconfig rpi_defconfig
参考 scripts_basic的执行过程。
会包含scripts/config目录下的Makefile 并构建rpi_defconfig目标。
因此命中kconfig/Makefile当中的
%_defconfig: $(obj)/conf
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
第一步先构建依赖 $(obj)/conf
再执行 scripts/kconfig/conf --defconfig=arch/../configs/rpi_defconfig Kconfig
(注意当前的执行目录依然是顶层目录)
构建依赖conf的过程也是由于kconfig/Makefile中有
hostprogs-y := conf nconf mconf kxgettext qconf gconf
所以和前面的fixdep一样包含了Makefile.host。只是此时由于还有conf-objs:= conf.o zconf.tab.o
因此conf是
host-cmulti := $(foreach m,$(__hostprogs),\
$(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
主机上运行的由多用.o文件组成的bin
同样编译过程就是Link这些o
cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
$(addprefix $(obj)/,$($(@F)-objs)) \
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
对于.o文件则是
$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
$(call if_changed_dep,host-cxxobjs)
cmd_host-cxxobjs = $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
这些都是根据依赖($(host-cxxobjs):) 一个个递归寻找的。
编译好conf之后
执行scripts/kconfig/conf --defconfig=arch/../configs/rpi_defconfig Kconfig
因此make rpi_defconfig主要工作是
1产生fixdep
2产生conf
3调用scripts/kconfig/conf --defconfig=arch/../configs/rpi_defconfig Kconfig
关键的部分还是在conf的执行
如果不执行第三步。光执行1 2可以看出文件比原来多了
如果再执行第三步,那么就会多出一个.config
最关键的还是第3步