config-targets := 0
mixed-targets := 0
dot-config := 1
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
dot-config := 0
endif
endif
ifeq ($(KBUILD_EXTMOD),)
ifneq ($(filter config %config,$(MAKECMDGOALS)),)
config-targets := 1
ifneq ($(words $(MAKECMDGOALS)),1)
mixed-targets := 1
endif
endif
endif
ifeq ($(mixed-targets),1)
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.
PHONY += $(MAKECMDGOALS) __build_one_by_one
$(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one
@:
__build_one_by_one:
$(Q)set -e; \
for i in $(MAKECMDGOALS); do \
$(MAKE) -f $(srctree)/Makefile $$i; \
done
else
ifeq ($(config-targets),1)
# ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend
# in scripts/kconfig to make the *config target
# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'
include arch/$(SRCARCH)/Makefile
export KBUILD_DEFCONFIG KBUILD_KCONFIG
config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
else
# ===========================================================================
# Build targets only - this includes vmlinux, arch specific targets, clean
# targets and others. In general all targets except *config targets.
ifeq ($(KBUILD_EXTMOD),)
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
# in parallel
PHONY += scripts
scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
asm-generic
$(Q)$(MAKE) $(build)=$(@)
# Objects we will link into vmlinux / subdirs we need to visit
init-y := init/
drivers-y := drivers/ sound/ firmware/
net-y := net/
libs-y := lib/
core-y := usr/
endif # KBUILD_EXTMOD
第 490~507 行和 uboot 一样,都是设置定义变量 config-targets、 mixed-targets 和 dot-config的值,最终这三个变量的值为:
config-targets= 1
mixed-targets= 0
dot-config= 1
因为 config-targets=1,因此第 534 行~541 行成立。第 534 行引用 arch/arm/Makefile 这个文件,这个文件很重要, 因为 zImage、 uImage 等这些文件就是由 arch/arm/Makefile 来生成的。
第 535 行导出变量 KBUILD_DEFCONFIG KBUILD_KCONFIG。
第 537 行,没有目标与之匹配,因此不执行。
第 540 行,“make xxx_defconfig”与目标“%config”匹配,因此执行。“%config”依赖scripts_basic、 outputmakefile 和 FORCE,“%config”真正有意义的依赖就只有 scripts_basic,scripts_basic 的规则如下:
448 scripts_basic:
449 $(Q)$(MAKE) $(build)=scripts/basic
450 $(Q)rm -f .tmp_quiet_recordmcount
build 定义在文件 scripts/Kbuild.include 中,值为 build := -f $(srctree)/scripts/Makefile.buildobj,因此将代码展开就是:
scripts_basic:
@make -f ./scripts/Makefile.build obj=scripts/basic //也可以没有@,视配置而定
@rm -f . tmp_quiet_recordmcount //也可以没有@
Makefile.build 脚本分析
从上一小节可知,“ make xxx_defconfig“配置 Linux 的时候如下两行命令会执行脚本
scripts/Makefile.build:
@make -f ./scripts/Makefile.build obj=scripts/basic
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
我们依次来分析一下:
1、 scripts_basic 目标对应的命令
scripts_basic 目标对应的命令为: @make -f ./scripts/Makefile.build obj=scripts/basic。打开文件 scripts/Makefile.build,有如下代码:
41 # The filename Kbuild has precedence over Makefile
42 kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
43 kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuilddir)/Kbuild,$(kbuild-dir)/Makefile)
44 include $(kbuild-file)
将 kbuild-dir 展开后为:
kbuild-dir=./scripts/basic
将 kbuild-file 展开后为:
kbuild-file= ./scripts/basic/Makefile
最后将 59 行展开,即:
include ./scripts/basic/Makefile
继续分析 scripts/Makefile.build,如下代码:
94 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target)$(extra-y)) \
95 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
96 $(subdir-ym) $(always)
97 @:
__build 是默认目标,因为命令“@make -f ./scripts/Makefile.build obj=scripts/basic”没有指定目标,所以会使用到默认目标__build。在顶层 Makefile 中, KBUILD_BUILTIN 为 1,KBUILD_MODULES 为空,因此展开后目标__build 为:
__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:
可以看出目标__build 有 5 个依赖: builtin-target、 lib-target、 extra-y、 subdir-ym 和 always。
这 5 个依赖的具体内容如下:
builtin-target =
lib-target =
extra-y =
subdir-ym =
always = scripts/basic/fixdep scripts/basic/bin2c
只有 always 有效,因此__build 最终为:
__build: scripts/basic/fixdep scripts/basic/bin2c
@:
__build 依赖于 scripts/basic/fixdep 和 scripts/basic/bin2c,所以要先将 scripts/basic/fixdep 和scripts/basic/bin2c.c 这两个文件编译成 fixdep 和 bin2c。
综上所述, scripts_basic 目标的作用就是编译出 scripts/basic/fixdep 和 scripts/basic/bin2c 这两个软件。
2、 %config 目标对应的命令
%config 目 标 对 应 的 命 令 为 :
@make -f ./scripts/Makefile.build obj=scripts/kconfig
xxx_defconfig,此命令会使用到的各个变量值如下:
src= scripts/kconfig
kbuild-dir = ./scripts/kconfig
kbuild-file = ./scripts/kconfig/Makefile
include ./scripts/kconfig/Makefile
可以看出, Makefile.build 会读取 scripts/kconfig/Makefile 中的内容,此文件有如下所示内容:
113 %_defconfig: $(obj)/conf
114 $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@
$(Kconfig)
目标%_defconfig 与 xxx_defconfig 匹配,所以会执行这条规则,将其展开就是:
%_defconfig: scripts/kconfig/conf
@ scripts/kconfig/conf --defconfig=arch/arm/configs/%_defconfig Kconfig
%_defconfig依赖scripts/kconfig/conf,所以会编译scripts/kconfig/conf.c生成conf这个软件。
此软件就会将%_defconfig 中的配置输出到.config 文件中,最终生成 Linux kernel 根目录下的.config 文件。