ifeq ($(MAKECMDGOALS),)
KBUILD_MODULES := 1
endif
export KBUILD_MODULES KBUILD_BUILTIN
#导出变量给子make
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
# Beautify output 格式化的回显控制
# ---------------------------------------------------------------------------
#
# Normally, we echo the whole command before executing it. By making
# that echo $($(quiet)$(cmd)), we now have the possibility to set
# $(quiet) to choose other forms of output instead, e.g.
#
# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
# cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
#
# If $(quiet) is empty, the whole command will be printed.表示如果为空则完全回显
# If it is set to "quiet_", only the short version will be printed. $(quiet)=quiet_表示只有版本显示
# If it is set to "silent_", nothing will be printed at all, since如果$(quiet)=silent表示完全不回显
# the variable $(silent_cmd_cc_o_c) doesn't exist.
#
# A simple variant is to prefix commands with $(Q) - that's useful..$(Q)用作前缀,如果$(Q)=@表示
# for commands that shall be hidden in non-verbose mode. 不回显,为空表示回显
#
# $(Q)ln $@ :<
#
# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
# If KBUILD_VERBOSE equals 1 then the above command is displayed.
ifeq ($(KBUILD_VERBOSE),1) #这里就是定义是否要回显
quiet =
Q = #不以@开头表示回显
else
quiet=quiet_
Q = @ #这里以@开头表示不回显
endif
# If the user is running make -s (silent mode), suppress echoing of
# commands
ifneq ($(findstring s,$(MAKEFLAGS)),)
#如果MAKEFLAGS中带了-s表示完全不要回显
quiet=silent_
endif
export quiet Q KBUILD_VERBOSE #导出子make
# Look for make include files relative to root of kernel src
MAKEFLAGS += --include-dir=$(srctree)
# We need some generic definitions (do not try to remake the file).
$(srctree)/scripts/Kbuild.include: ;
#这里执行remake操作请看GNU make 流程
include $(srctree)/scripts/Kbuild.include #这里是文件包含
#Kbuild.include 这里定义了大量通用的函数和变量
#重点!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Make variables (CC, etc...)
#这里是设置编译连接的默认程序,都是变量赋值操作
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
AWK = awk
GENKSYMS = scripts/genksyms/genksyms
DEPMOD = /sbin/depmod
KALLSYMS = scripts/kallsyms
PERL = perl
CHECK = sparse #默认的字符串检查
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
AFLAGS_MODULE = $(MODFLAGS)
LDFLAGS_MODULE =
CFLAGS_KERNEL =
AFLAGS_KERNEL =
# Use LINUXINCLUDE when you must reference the include/ directory.
# Needed to be compatible with the O= option
LINUXINCLUDE := -Iinclude /
$(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) /
-include include/linux/autoconf.h
KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs /
-fno-strict-aliasing -fno-common /
-Werror-implicit-function-declaration
KBUILD_AFLAGS := -D__ASSEMBLY__
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)#
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
# When compiling out-of-tree modules, put MODVERDIR in the module
# tree rather than in the kernel tree. The kernel tree might
# even be read-only.
export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
# Files to ignore in find ... statements
RCS_FIND_IGNORE := /( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git /) -prune -o
export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git
# ===========================================================================
# Rules shared between *config targets and build targets
# Basic helpers built in scripts这里生成基本的scripts配置工具fixdep docproc两个/
PHONY += scripts_basic #定义一个伪目标
scripts_basic: #该伪目标要执行的操作
$(Q)$(MAKE) $(build)=scripts/basic
#build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj 定义在Kbuild.include中我们在前面
#包含了该文件
#src := $(obj)因为我们Makefile.build中需要带入参数obj用于赋给src
#这里会执行.../scripts/Makefile.build 文件===========================
#Makefile.build中包含了scripts/basic/Makefile
# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;
PHONY += outputmakefile
# outputmakefile generates a Makefile in the output directory, if using a
# separate output directory. This allows convenient use of make in the
# output directory.
outputmakefile:
ifneq ($(KBUILD_SRC),) #$(CONFIG_SHELL)即被设置为/bin/sh或者其它shell
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile /#这里的用shell执行mkmakefile
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) #并在输出目录中输出
#这个规则的命令运行一个shell脚本scripts/mkmakefile,
#并传递四个参数。这个脚本主要是在$(objtree)参数指定的目录中
#生成一个Makefile文件。由于这里KBUILD_SRC为空,
#所以这个脚本并不会被执行
endif
# To make sure we do not include .config for any of the *config targets
# catch them early, and hand them over to scripts/kconfig/Makefile
# It is allowed to specify more targets when calling make, including
# mixing *config targets and build targets.
# For example 'make oldconfig all'.
# Detect when mixed targets is specified, and make a second invocation
# of make so .config is not included in this case either (for *config).
#GNU configure 中的build/target和host的区别
#build就是现在使用的机器,即编译平台
#host就是我们的目标机,编译好的程序运行的平台
#target一般在构建编译本身的时候(gcc),采用target
no-dot-config-targets := clean mrproper distclean /
cscope TAGS tags help %docs check% /
include/linux/version.h headers_% /
kernelrelease kernelversion
#这里是默认值,
config-targets := 0#如果有config %config则为1
mixed-targets := 0#当有config %config 还有其它目标时为1
dot-config := 1 #当有config %config时肯定为1
#根据输出参数修改
#make后面的目标包括三类:
#(1)和.config无关的目标即(no_dot_config-targets)比如:clean,mrproper,distclean,
# headers_install,kernelrelease,kernelversion等等;
#(2)和.config相关的目标dot_config
# a:配置目标(config targets)主要是产生.config文件
# b:构建目标(build targets)主要是使用.config像all,vmlinux,modules,zImage,等等
#(3)single targets
# 上面没有列出的,如:dir/,dir/file,dir/file.ko
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)#如果我们命令行目标CMDGOALS
#有任何clean之类的命令
ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)#且除了clean之类目标外为空
#那么标识应该删除.config文件
dot-config := 0
endif
endif
ifeq ($(KBUILD_EXTMOD),)
ifneq ($(filter config %config,$(MAKECMDGOALS)),)#这里就是匹配我们命令行
#中是否有menuconfig/xconfig等有则表示
#这是一条配置命令,因而config-targets置1
#标识应该生成.config文件
config-targets := 1
ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)#如果不仅有config目标
#还有别的目标,表示为混合目标模式
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.
#%代表make 后带任何目标都执行该命令
#那就是
%:: FORCE
$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@
#从代码中可以看出,这里使用了一个双冒号的模式匹配规则。
#百分号代表任何目标都使用这个规则,其中
#$(srctree) 为内核代码树所在目 录 , KBUILD_SRC 定义为空 。
#所以如果 make 命令为 : make s3c2410_defconfig all
#那么构建系统就会分别执行下面两条命令:
#make -C $(srctree) KBUILD_SRC= s3c2410_defconfig
#make -C $(srctree) KBUILD_SRC= all
#这其实和简单的用手动的输入两条连续命令
#(make s3c2410_defconfig 和 make all) 是一样效果的。
# ============%config targe配置时执行以下规则===========
#这里是%config target时执行的规则!!!!!!!!!!!!!!!!!!!!!!!!!!
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 $(srctree)/arch/$(SRCARCH)/Makefile#直接包含平台架构下
#的makefile
export KBUILD_DEFCONFIG
###############执行make menuconfig的入口点#####################
#生配置工具,根据我们的kconfig
config %config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
#在顶层目录执行”make menuconfig”会执行顶层Makefile 第415行的规则
#config %config: scripts_basic outputmakefile FORCE
#$(Q)mkdir -p include/linux include/config
#$(Q)$(MAKE) $(build)=scripts/kconfig $@
#这里"menuconfig"与模式"%config”匹配。所以其执行的规则如下:
#menuconfig: scripts_basic outputmakefile FORCE
#$(Q)mkdir -p include/linux include/config
#$(Q)$(MAKE) $(build)=scripts/kconfig menuconfig
#$@目标变量
#build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
#之所以我们引用$(build)=...每次都要是build带一个等于号的
#的原因就是因为我们的变量后面带了一个obj用于指定
#我们的obj目录是哪里!!!!!!!!!!!!
#这个规则有三个依赖:scripts_basic、outputmakefile、FORCE
#PHONY += scripts_basic #定义一个伪目标
#scripts_basic: #该伪目标要执行的操作
# $(Q)$(MAKE) $(build)=scripts/basic
#build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
#之所以我们引用$(build)=...每次都要是build带一个等于号的
#的原因就是因为我们的变量后面带了一个obj用于指定
#我们的obj目录是哪里!!!!!!!!!!!!
#==============================================
#==============================================
#这个命令依然是执行scripts/Makefile.build这个makefile文件。
#并执行它里面$@表示menuconfig的规则。根据上面的分析,
#在Makefile.build会包含scripts/kconfig/Makefile文件!!!!!!!!!!!!!。
#然后执行以menuconfig为目标的规则,
#在scripts/kconfig/Makefile的13行定义
#menuconfig: $(obj)/mconf
# $< arch/$(ARCH)/Kconfig
#即$<表示依赖集$(obj)/mconf这个是一个解析Kconfig的程序
#arch/$(ARCH)/Kconfig 是被解析的文件
# ===============编译模块或者目标时目标=========================
# Build targets only - this includes vmlinux, arch specific targets, clean
# targets and others. In general all targets except *config targets.
else
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
$(Q)$(MAKE) $(build)=$(@)
#这里生成scripts_basic include/config/auto.conf
# Objects we will link into vmlinux / subdirs we need to visit
init-y := init/
drivers-y := drivers/ sound/
net-y := net/
libs-y := lib/
core-y := usr/
endif # KBUILD_EXTMOD
ifeq ($(dot-config),1)#若.config已经被配置,则可包含产生的auto.conf文件
# Read in config
-include include/config/auto.conf
ifeq ($(KBUILD_EXTMOD),)
# Read in dependencies to all Kconfig* files, make sure to run
# oldconfig if changes are detected.
-include include/config/auto.conf.cmd
# To avoid any implicit rule to kick in, define an empty command
$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
# If .config is newer than include/config/auto.conf, someone tinkered
# with it and forgot to run make oldconfig.
# if auto.conf.cmd is missing then we are probably in a cleaned tree so
# we execute the config step to be sure to catch updated Kconfig files
#这里是生成我们的需要的三个文件
include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
else
# external modules needs include/linux/autoconf.h and include/config/auto.conf
# but do not care if they are up-to-date. Use auto.conf to trigger the test
PHONY += include/config/auto.conf
include/config/auto.conf:
$(Q)test -e include/linux/autoconf.h -a -e $@ || ( /
echo; /
echo " ERROR: Kernel configuration is invalid."; /
echo " include/linux/autoconf.h or $@ are missing."; /
echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; /
echo; /
/bin/false)
endif # KBUILD_EXTMOD
else
# Dummy target needed, because used as prerequisite
include/config/auto.conf: ;
endif # $(dot-config)
#==============the read targets starts======================
#==============vmlinux all modules and other targets ============
# The all: target is the default when no target is given on the
# command line.
# This allow a user to issue only 'make' to build a kernel including modules
# Defaults vmlinux but it is usually overridden in the arch makefile
all: vmlinux #这个是默认的目标
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os
else
KBUILD_CFLAGS += -O2
endif
ifneq (CONFIG_FRAME_WARN,0)
KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
endif
# Force gcc to behave correct even for buggy distributions
# Arch Makefiles may override this setting
KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
include $(srctree)/arch/$(SRCARCH)/Makefile
ifdef CONFIG_FRAME_POINTER
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
else
KBUILD_CFLAGS += -fomit-frame-pointer
endif
ifdef CONFIG_DEBUG_INFO
KBUILD_CFLAGS += -g
KBUILD_AFLAGS += -gdwarf-2
endif
# We trigger additional mismatches with less inlining
ifdef CONFIG_DEBUG_SECTION_MISMATCH
KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
endif
# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
# warn about C99 declaration after statement
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
# disable pointer signed / unsigned warnings in gcc 4.0
KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)
# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
# But warn user when we do so
warn-assign = /
$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")
ifneq ($(KCPPFLAGS),)
$(call warn-assign,CPPFLAGS)
KBUILD_CPPFLAGS += $(KCPPFLAGS)
endif
ifneq ($(KAFLAGS),)
$(call warn-assign,AFLAGS)
KBUILD_AFLAGS += $(KAFLAGS)
endif
ifneq ($(KCFLAGS),)
$(call warn-assign,CFLAGS)
KBUILD_CFLAGS += $(KCFLAGS)
endif
# Use --build-id when available.
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,/
$(call ld-option, -Wl$(comma)--build-id,))
LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)
LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID)
# Default kernel image to build when no specific target is given.
# KBUILD_IMAGE may be overruled on the command line or
# set in the environment
# Also any assignments in arch/$(ARCH)/Makefile take precedence over
# this default value
export KBUILD_IMAGE ?= vmlinux
#
# INSTALL_PATH specifies where to place the updated kernel and system map
# images. Default is /boot, but you can set it to other values
export INSTALL_PATH ?= /boot
#默认的安装目录
#
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
# relocations required by build roots. This is not defined in the
# makefile but the argument can be passed to make if needed.
#
MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
#
# INSTALL_MOD_STRIP, if defined, will cause modules to be
# stripped after they are installed. If INSTALL_MOD_STRIP is '1', then
# the default option --strip-debug will be used. Otherwise,
# INSTALL_MOD_STRIP will used as the options to the strip command.
ifdef INSTALL_MOD_STRIP
ifeq ($(INSTALL_MOD_STRIP),1)
mod_strip_cmd = $(STRIP) --strip-debug
else
mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
endif # INSTALL_MOD_STRIP=1
else
mod_strip_cmd = true
endif # INSTALL_MOD_STRIP
export mod_strip_cmd
#这里是编译的主体!!!!!!!!!!!!!!!!!!!!!!!
ifeq ($(KBUILD_EXTMOD),)#如果外部模块为空,即编译内核
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
#此时我们的core-y目标需要添加各个模块
#vmlinux-dirs即我们编译内核需要添加的各个模块
#所在的内核目录
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) /
$(core-y) $(core-m) $(drivers-y) $(drivers-m) /
$(net-y) $(net-m) $(libs-y) $(libs-m)))
#这里的vmlinux即取目录名称
vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, /#sort is a sequence!
$(init-n) $(init-) /
$(core-n) $(core-) $(drivers-n) $(drivers-) /
$(net-n) $(net-) $(libs-n) $(libs-))))
#################重点###############################
################################################
################################################
init-y := $(patsubst %/, %/built-in.o, $(init-y))#这里所有的init/都被
#init/built-in.o所替代
core-y := $(patsubst %/, %/built-in.o, $(core-y))#同上
#vmlinux-main即由各个目录下的build-in.o链接而成
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
# Build vmlinux
# ---------------------------------------------------------------------------
# vmlinux is built from the objects selected by $(vmlinux-init) and
# $(vmlinux-main). Most are built-in.o files from top-level directories
# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
# Ordering when linking is important, and $(vmlinux-init) must be first.
#
# vmlinux
# ^
# |
# +-< $(vmlinux-init)
# | +--< init/version.o + more
# |
# +--< $(vmlinux-main)
# | +--< driver/built-in.o mm/built-in.o + more
# |
# +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
#
# vmlinux version (uname -v) cannot be updated during normal
# descending-into-subdirs phase since we do not yet know if we need to
# update vmlinux.
# Therefore this step is delayed until just before final link of vmlinux -
# except in the kallsyms case where it is done just before adding the
# symbols to the kernel.
#
# System.map is generated to document addresses of all kernel symbols
vmlinux-init := $(head-y) $(init-y)#head-y定义在/arch/xx/Makefile
#head-y := arch/x86/kernel/head_$(BITS).o
#head-y += arch/x86/kernel/head$(BITS).o
#head-y += arch/x86/kernel/init_task.o
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)#the main body of linux kernel;
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds
#使用与架构相关的
#链接文件lds
export KBUILD_VMLINUX_OBJS := $(vmlinux-all)
# Rule to link vmlinux - also used during CONFIG_KALLSYMS
# May be overridden by arch/$(ARCH)/Makefile
quiet_cmd_vmlinux__ ?= LD $@ #?=means the defualts if without other operation
cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ /
-T $(vmlinux-lds) $(vmlinux-init) /
--start-group $(vmlinux-main) --end-group /
$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
# Generate new vmlinux version
quiet_cmd_vmlinux_version = GEN .version
cmd_vmlinux_version = set -e; /
if [ ! -r .version ]; then /
rm -f .version; /
echo 1 >.version; /
else /
mv .version .old_version; /
expr 0$$(cat .old_version) + 1 >.version; /
fi; /
$(MAKE) $(build)=init
# Generate System.map
quiet_cmd_sysmap = SYSMAP
cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
# Link of vmlinux
# If CONFIG_KALLSYMS is set .version is already updated
# Generate System.map and verify that the content is consistent
# Use + in front of the vmlinux_version rule to silent warning with make -j2
# First command is ':' to allow us to use + in front of the rule
#以下是一个命令包,即一组命令可能在多个规则中使用
#相同的一组命令,通过define来定义这组命令作为一个命令,以后
#在需要的规则中通过变量名直接引用!!!!!!!
define rule_vmlinux__
#这里是执行vmlinux的规则
:
$(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
$(call cmd,vmlinux__)
#cmd = @$(echo-cmd) $(cmd_$(1))
#即被展开为cmd_vmlinux__!!!!!!!!!!!!!!!=======
#而此命令为一个连接命令,如下!!!!!!!!========即我们连接命令
#cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ /
# -T $(vmlinux-lds) $(vmlinux-init) /
# --start-group $(vmlinux-main) --end-group /
# $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
$(Q)$(if $($(quiet)cmd_sysmap), #生成System.map /
echo ' $($(quiet)cmd_sysmap) System.map' &&) /
$(cmd_sysmap) $@ System.map; /
if [ $$? -ne 0 ]; then /
rm -f $@; /
/bin/false; /
fi;
$(verify_kallsyms)
endef
#至此我们的vmlinux就链接完成了,接下来就是我们的bzImage了!!!
ifdef CONFIG_KALLSYMS
# Generate section listing all symbols and add it into vmlinux $(kallsyms.o)
# It's a three stage process:
# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is
# empty
# Running kallsyms on that gives us .tmp_kallsyms1.o with
# the right size - vmlinux version (uname -v) is updated during this step
# o .tmp_vmlinux2 now has a __kallsyms section of the right size,
# but due to the added section, some addresses have shifted.
# From here, we generate a correct .tmp_kallsyms2.o
# o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
# o Verify that the System.map from vmlinux matches the map from
# .tmp_vmlinux2, just in case we did not generate kallsyms correctly.
# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
# .tmp_vmlinux3 and .tmp_kallsyms3.o. This is only meant as a
# temporary bypass to allow the kernel to be built while the
# maintainers work out what went wrong with kallsyms.
ifdef CONFIG_KALLSYMS_EXTRA_PASS
last_kallsyms := 3
else
last_kallsyms := 2
endif
kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
#以下是一个命令包,即一组命令可能在多个规则中使用
#相同的一组命令,通过define来定义这组命令作为一个命令,以后
#在需要的规则中通过变量名直接引用!!!!!!!
define verify_kallsyms #这里是命令包名称
$(Q)$(if $($(quiet)cmd_sysmap), /
echo ' $($(quiet)cmd_sysmap) .tmp_System.map' &&) /
$(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map
$(Q)cmp -s System.map .tmp_System.map || /
(echo Inconsistent kallsyms data; /
echo Try setting CONFIG_KALLSYMS_EXTRA_PASS; /
rm .tmp_kallsyms* ; /bin/false )
endef
# Update vmlinux version before link
# Use + in front of this rule to silent warning about make -j1
# First command is ':' to allow us to use + in front of this rule
cmd_ksym_ld = $(cmd_vmlinux__)
define rule_ksym_ld
:
+$(call cmd,vmlinux_version)
$(call cmd,vmlinux__)
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
endef
# Generate .S file with all kernel symbols
quiet_cmd_kallsyms = KSYM $@
cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) /
$(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
$(call if_changed_dep,as_o_S)
.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
$(call cmd,kallsyms)
# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
$(call if_changed_rule,ksym_ld)
.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
$(call if_changed,vmlinux__)
.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
$(call if_changed,vmlinux__)
# Needs to visit scripts/ before $(KALLSYMS) can be used.
$(KALLSYMS): scripts ;
# Generate some data for debugging strange kallsyms problems
debug_kallsyms: .tmp_map$(last_kallsyms)
.tmp_map%: .tmp_vmlinux% FORCE
($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
.tmp_map3: .tmp_map2
.tmp_map2: .tmp_map1
endif # ifdef CONFIG_KALLSYMS
# Do modpost on a prelinked vmlinux. The finally linked vmlinux has
# relevant sections renamed as per the linker script.
quiet_cmd_vmlinux-modpost = LD $@
cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ /
$(vmlinux-init) --start-group $(vmlinux-main) --end-group /
$(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
define rule_vmlinux-modpost: #定义命令包
+$(call cmd,vmlinux-modpost)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
$(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
endef
#==================================================
#==================================================
#vmlinux的依赖目标集,开始真正的做主目录下的映像文件
# vmlinux image - including updated kernel symbols
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK #这里主要是头检验
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
#PHONY += headers_check 当make -f $(srctree)/Makefile headers_check执行以下命令
#headers_check: headers_install
# $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include HDRCHECK=1
endif
ifdef CONFIG_SAMPLES
#配置样本即调用Makefile.build 到Samples目录下make生成样本
$(Q)$(MAKE) $(build)=samples
endif
$(call vmlinux-modpost)#vmlinux-modpost没有被定义,是一条多余的没有被定义的变量
$(call if_changed_rule,vmlinux__)
#在我们所以依赖目标都生成后我们开始链接!!!!!!!!!!===========
#if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), /
# @set -e; /
# $(rule_$(1)))即执行rule_vmlinux__ 924line
$(Q)rm -f .old_version
# build vmlinux.o first to catch section mismatch errors early
ifdef CONFIG_KALLSYMS
.tmp_vmlinux1: vmlinux.o
endif
#modpost-init表示除了init/下的built-in.o
modpost-init := $(filter-out init/built-in.o, $(vmlinux-init))
vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE
$(call if_changed_rule,vmlinux-modpost)#这里是没有存在的,无效
# The actual objects are generated when descending,
# make sure no implicit rule kicks in
$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
# Handle descending into subdirectories listed in $(vmlinux-dirs)
# Preset locale variables to speed up the build process. Limit locale
# tweaks to this spot to avoid wrong language settings when running
# make menuconfig etc.
# Error messages still appears in the original language