一个专注于SLAM、机器视觉、Linux 等相关技术文章分享的公众号
从u-boot-2014.10
版本引入Kbuild系统之后,Makefile的管理和组织跟以前版本的代码有了很大的不同,这使Makefile变得更加复杂。整个Makefile中,include很多其它不同用途的Makefile,各种目标和依赖也很多,因此要想搞清楚make的执行过程很困难;使用u-boot之前首先是对其进行配置,命令为:
make xxx_defconfig
上述命令执行之后会生成对应的.config文件,接下来就可以进行最后的编译工作了,直接输入make即可。
执行make xxx_defconfig
命令时,u-boot根目录下的Makefile中有唯一的规则匹配目标:
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
其中$(build)
在kbuild.include
中定义:
build := -f $(srctree)/scripts/Makefile.build obj
依赖scripts_basic:
# Basic helpers built in scripts/
PHONY += scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
可见scripts_basic没有进一步的依赖,展开后规则如下:
scripts_basic:
$(Q) make -f ./scripts/Makefile.build obj=scripts/basic
$(Q) rm -f .tmp_quiet_recordmcount
简而言之,scripts_basic
规则
scripts_basic:
$(Q) make -f ./scripts/Makefile.build obj=scripts/basic
的最终结果就是编译scripts/basic/fixdep.c
生成主机上的可执行文件fixdep。
第二次调用scripts/Makefile.build进行编译
文件script/Makefile.build
的开头会根据传入的obj=scripts/kconfig
参数设置src=scripts/kconfig
。然后搜寻$(srctree)/$(src)
子目录下的makefile,由于src=scripts/kconfig
参数不同于第一次调用的参数(src=scripts/basic
),此处包含的makefile也不同于第一次的makefile了:
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
这里替换展开后相当于:
include ./scripts/kconfig/Makefile
对于这里传入的xxx_defconfig
,匹配的目标是:
%_defconfig: $(obj)/conf
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
展开为:
xxx_defconfig: scripts/kconfig/conf
$(Q)scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig
此处目标xxx_defconfig
依赖于scripts/kconfig/conf
,接下来检查并生成依赖。
hostprogs-y := conf nconf mconf kxgettext qconf gconf
hostprogs-y
指出conf被定义为主机上执行的程序,其依赖于另外两个文件:
conf-objs := conf.o zconf.tab.o
通过编译conf.c
和zconf.tab.c
生成conf-objs
,并链接为scripts/kconfig/conf
。
生成依赖后就是执行目标的命令了:
$(Q)scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig
conf
工具从根目录下开始树状读取默认的Kconfig
文件,分析其配置并保存在内存中。分析完默认的Kconfig
后再读取指定文件(即arch/../configs/xxx_defconfig
)更新得到最终的符号表,并输出到.config
文件中。