linux 顶层Makefile执行的流程

  

1、make menuconfig

# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
# More info can be located in ./README
# Comments in this file are targeted only to the developer, donot
# expect to learn how to build the kernel reading this file.

# Do not:
# o  use make's built-in rules and variables
   (thisincreases performance and avoids hard-to-debug behaviour);
# o  print "Entering directory ...";
MAKEFLAGS += -rR --no-print-directory
#-r禁止使用build-in规则
#--no-print-directory是:不要再屏幕上打印"Entering directory.."
#记住变量SHELL,MAKEFLAGS在整个make的执行过程中
#始终被自动的传递给所有的子make

# We are using a recursive build, so we need to do a littlethinking
# to get the ordering right.
#
# Most importantly: sub-Makefiles should only ever modify filesin
# their own directory. If in some directory we have a dependencyon
# a file in another dir (which doesn't happen often, but it'soften
# unavoidable when linking the built-in.o targets which finy
# turn into vmlinux), we will call a sub make in that other dir,and
# after that we are sure that everything which is in that otherdir
# is now up to date.
#
# The only cases where we need to modify files which haveglobal
# effects are thus separated out and done before therecursive
# descending is started. They are now explicitly listed asthe
# prepare rule.

# To put more focus on warnings, be less verbose asdefault
# Use 'make V=1' to see the full commands
 
ifdef V   #v=1
  ifeq ("$(origin V)", "command line")
   KBUILD_VERBOSE = $(V)  #把V的值作为KBUILD_VERBOSE的值
  endif
endif

ifndef KBUILD_VERBOSE  #即默认我们是不回显的
       #回显即在命令执行前显示要执行的命令
  KBUILD_VERBOSE = 0 
endif


#函数origin并不操作变量的值,只是告诉你你的这个变量是哪里来的。
# 语法是: $(origin <variable>;)#origin函数的返回值有:
#"undefined"从来没有定义过、“default”是一个默认的定义、“
#"environment"是一个环境变量、
#"file"这个变量被定义在Makefile中
#"command line"这个变量是被命令行定义的
#"override"是被override指示符重新定义的
#"automatic"是一个命令运行中的自动化变量


# Call a source code checker (by default, "sparse") as part ofthe
# C compilation.调用一个静态分析工具作为c编译器的
#部分
# Use 'make C=1' to enable checking of only re-compiledfiles.
# Use 'make C=2' to enable checking of *all* source files,regardless
# of whether they are re-compiled or not.
#
# See the file "Documentation/sparse.txt" for more details,including
# where to get the "sparse" utility.
ifdef C
  ifeq ("$(origin C)", "command line")
   KBUILD_CHECKSRC = $(C)
  endif
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
endif


#用M来指定外部模块的目录
# Use make M=dir to specify directory of external module tobuild
# Old syntax make ... SUBDIRS=$PWD is still supported
# Setting the environment variable KBUILD_EXTMOD takeprecedence
#识别这里是定义一个外部模块吗??
#当我们定义了M变量或者SUBDIRS时表示编译一个外部模块

# “?=”操作符
#条件赋值的赋值操作符。被称为条件赋值是因为:只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。例如:
             FOO ?= bar
#其等价于:
          ifeq ($(origin FOO), undefined)
            FOO = bar
          endif
#含义是:如果变量“FOO”在没有定义过,就给它赋值“bar”。否则不改变它的值。

ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS) #?=为条件赋值操作符仅仅在变量还
  #还没有定义的情况下有效
endif
ifdef M
  ifeq ("$(origin M)", "command line")

在使用“:=”
定义变量时,变量值中对另外变量的引用或者函数的引用在定义时被展开(对变量进行替换)
而=是在使用时才进行替换
举例:
CFLAGS = $(include_dirs)-O
include_dirs = -Ifoo -Ibar
“CFLAGS”会在命令中被展开为“-Ifoo -Ibar-O”
CFLAGS := $(include_dirs)-O
include_dirs := -Ifoo-Ibar
由于在变量“include_dirs”的定义出现在“CFLAGS”定义之后。因此在“CFLAGS”的定义中,
“include_dirs”的值为空。“CFLAGS”的值为“-O”而不是“-Ifoo -Ibar-O”。

     KBUILD_EXTMOD := $(M)
  endif
endif

# kbuild supports saving output files in a separatedirectory.
# To locate output files in a separate directory two syntaxes aresupported.
# In both cases the working directory must be the root of thekernel src.
# 1) O=
# Use "make O=dir/to/store/output/files/"
#
# 2) Set KBUILD_OUTPUT
# Set the environment variable KBUILD_OUTPUT to point to thedirectory
# where the output files shall be placed.
# export KBUILD_OUTPUT=dir/to/store/output/files/
# make
#
# The O= assignment takes precedence over the KBUILD_OUTPUTenvironment
# variable.

# KBUILD_SRC is set on invocation of make in OBJ directory
# KBUILD_SRC is not intended to be used by the regular user (fornow)
###################make的最开始###################
####################################################
ifeq ($(KBUILD_SRC),)#如果KBUILD_SRC没有定义则进入下面一层即首次进入
                                   #时一般都需要两次进入顶层Makefile
                                        #若定义了则不为空直接跳入下一步
# OK, Make called in directory where kernel src resides
# Do we want to locate output files in a separate directory?
ifdefO                            #把输出文件放在不同的文件夹内
  ifeq ("$(origin O)", "command line")
   KBUILD_OUTPUT := $(O)  #用于指定我们的输出文件的输出目录
  endif
endif

# That's our default target when none is given on the commandline
PHONY := _all
_all:

# Cancel implicit rules on top Makefile取消隐式推倒规则
$(CURDIR)/Makefile Makefile: ;  #remake 操作查看当前目录Makefile是否为最新
                                                          #CURDIR值为当前的内核源码目录current dir
                                                          #为GNU make使用的变量,CURDIR设置当前工作目录的路径名

ifneq ($(KBUILD_OUTPUT),)     #如果输出目录不为空即设置了输出目录则检测
# Invoke a second make in the output directory, passing relevantvariables
# check that the output directory actually exists
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT)&&/bin/pwd)    #这里是测试此目录是否
                                                                                                                            #存在,若存在则赋给K BUILD_OUTPUT
$(if $(KBUILD_OUTPUT),,/                                                                           #这里的<then-part>为空即表示输出目录不存在
    $(error output directory "$(saved-output)" does notexist))                #使用了error函数
                                                                                                                           #这里的if函数语法为:if<condition>,<then-part>
                                                                                                                            #或者是if<condition>,<thenpart>,<else-part>

# make的环境变量叫MAKECMDGOALS 这个变量中会存放你所指定的
#终极目标的列表,如果在命令行上,你没有指定目标,
#那么,这个变量是空值。

PHONY += $(MAKECMDGOALS) sub-make

#将任何在命令行中给出的目标放入变量MAKECMDGOALS
#这里 filter-out是返回$(MAKECMDGOALS)中除了Makefile _allsub-make以外的
#其他文件; 匹配模式的过滤掉,留下不匹配的

$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS))_all: sub-make
 $(Q)@:         

#这里仅仅只是取消回显没有别的意思

#如果要执行的命令行以字符“@”开始,则make在执行时这个命令就不会被回显。
#$(KBUILD_VERBOSE:1=)为变量替换,如果为1就替换为空
#if KBUILD_VERBOSE = 1 or KBUILD_VERBOSE is NULL
#then
#$(MAKE) -C $(KBUILD_OUTPUT) //回显
#else
#@ $(MAKE) -C $(KBUILD_OUTPUT)//即不回显
#endif

sub-make: FORCE
 $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT)/   #KBUILD_OUTPUT==dir前面测试了
 KBUILD_SRC=$(CURDIR) /
 KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f$(CURDIR)/Makefile/     #
 $(filter-out _allsub-make,$(MAKECMDGOALS))                                       #这里是表示要生成的目标
                                                                                                                              #make -C dir KBUILD_SRC=`pwd` KBUILD_EXTMOD="" -f `pwd`/Makefile[Targets]
 #这里表示再次执行Makefile 但此时我们的KBUILD
#此时再次执行完make后skip-makefile := 1从而
# Leave processing to above invocation ofmake结束子make返回根目录的make
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)这里是ifneq
endif # ifeq ($(KBUILD_SRC),)#这里是ifeq的结束处
####################################################
####################################################

ifeq($(skip-makefile),)         #如果为空则开始分类执行!!!!!!
                                                  #endif # skip-makefile在1813行处结束最大的ifeq结构
# If building an external module we do not care about the all:rule
# but instead _all depend on modules
PHONY +=all                         #声明一个伪目标all
ifeq ($(KBUILD_EXTMOD),) #如果外部模块定义为空则_all依赖于all
_all:all                                                               
else
_all:modules                           #否则依赖于modules
endif

srctree  := $(if$(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR)) #看KBUILD_SRC是否为空,  #设置源码目录
TOPDIR  :=$(srctree)                                                                         #顶层目录
# FIXME - TOPDIR is obsolete, use srctree/objtree
objtree  :=$(CURDIR)                                                                       #CURDIR为make的默认环境变量

src  :=$(srctree)                                                                                  #源文件的目录也设置为当前目录        
obj  :=$(objtree)                                                                                  #目标文件的输出目录设置当前目录

VPATH  := $(srctree)$(if$(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
                                                                                                                #这里是说当前目录找不到源文件时的搜索目录
export srctree objtree VPATHTOPDIR
                                                                                                                #export用于要将指定变量输出给子make,


# SUBARCH tells the usermode build what the underlying archis.  That is set
# first, and if a usermode build is happening, the "ARCH=um" on thecommand
# line overrides the setting of ARCH below.  If anative build is happening,
# then ARCH is assigned, getting whatever value it gets normally,and
# SUBARCH is subsequently ignored.
#这里是获取cpu的具体型号存在变量SUBARCH中
#sed -e s表示替换,这里表示出现i.86的用i386替换
#出现sun4u的用sparc64替换
#一般写成sed -e 's/i.86/i386' 用''括起来
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -es/sun4u/sparc64/ /
     -e s/arm.*/arm/ -e s/sa110/arm/ /
     -e s/s390x/s390/ -e s/parisc64/parisc/ /
     -e s/ppc.*/powerpc/ -e s/mips.*/mips/ /
     -e s/sh.*/sh/ )

# Cross compiling and selecting different set ofgcc/bin-utils
#---------------------------------------------------------------------------
#
# When performing cross compilation for other architectures ARCHshall be set
# to the target architecture. (See archMakefile
export KBUILD_BUILDHOST := $(SUBARCH) #这里是把宿主机的cpu结构导出到
          #KBUILD_BUILDHOST变量,并传入子make
ARCH  ?=$(SUBARCH)    
# 设置变量 ARCH 的方法有两种,
# 一:在命令行中 如: make ARCH=ia64 ;
# 二:设置环境变量,在环境变量中默认
#的 ARCH 的值是执行 make 的 cpu 架构
  "?="表示为ARCH 条件赋值如果ARCH前面没有赋值则这里赋值
#成功,否则不重新赋值
CROSS_COMPILE ?=                   #交叉编译工具的设置在嵌入式系统
                                                           #经常要修改此处设置交叉编译器的路径

# Architecture as present in compile.h
UTS_MACHINE  := $(ARCH)
SRCARCH  := $(ARCH)

# Additional ARCH settings for x86
ifeq ($(ARCH),i386)
       SRCARCH := x86
endif

ifeq ($(ARCH),x86_64)
       SRCARCH := x86
endif

KCONFIG_CONFIG ?= .config #这里是生成的配置文件

# SHELL used by kbuild 这里shel中的if [-x file ]测试file是否可执行
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH;/
   else if [ -x /bin/bash ]; thenecho /bin/bash; /
   else echo sh; fi ; fi)

HOSTCC      = gcc
HOSTCXX     = g++
HOSTCFLAGS   = -Wall-Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTCXXFLAGS = -O2

# Decide whether to build built-in, modular, or both.
# Normally, just do built-in.
KBUILD_MODULES :=
KBUILD_BUILTIN := 1

If we have only "make modules", don't compilebuilt-in objects.编译内置对象
When we're building modules with modversions, weneed to consider
the built-in objects during the descend as well,in order to
make sure the checksums are up to date before werecord them.

#如果执行”make modules”则这里在这里重新处理KBUILD_BUILTIN :=1
ifeq ($(MAKECMDGOALS),modules)
  KBUILD_BUILTIN := $(if$(CONFIG_MODVERSIONS),1)
endif


If we have "make<whatever> modules", compilemodules
in addition to whatever we do anyway.
Just "make" or "make all" shall build modules aswell


#如果执行"make all","make _all","make modules","make"中任一个命令
#则在这里重新处理KBUILD_MODULES
ifneq ($(filter all _allmodules,$(MAKECMDGOALS)),)#filter过滤出指定的字符串
          #这里表示如果不为空则编译模块
  KBUILD_MODULES := 1
endif

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. Bymaking
# that echo $($(quiet)$(cmd)), we now have the possibility toset
# $(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 beprinted.表示如果为空则完全回显
# 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'suseful..$(Q)用作前缀,如果$(Q)=@表示
# for commands that shall be hidden in non-verbosemode.   不回显,为空表示回显
#
$(Q)ln $@ :<
#
# If KBUILD_VERBOSE equals 0 then the above command will behidden.
# If KBUILD_VERBOSE equals 1 then the above command isdisplayed.

ifeq ($(KBUILD_VERBOSE),1) #这里就是定义是否要回显
  quiet =
  Q=         #不以@开头表示回显
else                   
  quiet=quiet_
  Q =@      #这里以@开头表示不回显
endif

 


# If the user is running make -s (silent mode), suppress echoingof
# 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 thefile).
$(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 itexists)
KERNELRELEASE = $(shell cat include/config/kernel.release2> /dev/null)#
KERNELVERSION =$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)

export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASEKERNELVERSION
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE ASLD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERLUTS_MACHINE
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS

export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGSLDFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE

# When compiling out-of-tree modules, put MODVERDIR in themodule
# 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配置工具fixdepdocproc两个/
PHONY += scripts_basic  #定义一个伪目标
scripts_basic: #该伪目标要执行的操作
 $(Q)$(MAKE) $(build)=scripts/basic
#build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.buildobj 定义在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 emptycommand.
scripts/basic/%: scripts_basic ;

PHONY += outputmakefile
# outputmakefile generates a Makefile in the output directory, ifusing a
# separate output directory. This allows convenient use of make inthe
# 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 *configtargets
# catch them early, and hand them over toscripts/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 secondinvocation
# 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 TAGStags 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:构建目标(buildtargets)主要是使用.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 buildtargets).
# 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) 是一样效果的。

# ============%configtarge配置时执行以下规则===========
#这里是%config target时执行的规则!!!!!!!!!!!!!!!!!!!!!!!!!!
else
ifeq ($(config-targets),1)
#===========================================================================
# *config targets only - make sure prerequisites are updated, anddescend
# in scripts/kconfig to make the *config target

# Read arch specific Makefile to set KBUILD_DEFCONFIG asneeded.
# KBUILD_DEFCONFIG may point out an alternative defaultconfiguration
# used for 'make defconfig'
include$(srctree)/arch/$(SRCARCH)/Makefile  #直接包含平台架构下
                                                                                     #的makefile

export KBUILD_DEFCONFIG

###############执行makemenuconfig的入口点#####################
                                                                                                    #生配置工具,根据我们的kconfig
config %config: scripts_basicoutputmakefile 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

#$@代表规则中目标变量,在多目标的模式规则中,它代表的是哪个触发规则被执行的目标文件名,如上句解释,这里是menuconfig出发的规则
#build := -f $(if$(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
#之所以我们引用$(build)=...每次都要是build带一个等于号的
#的原因就是因为$(build)变量后面带了一个obj,从而得到 ... /Makefile.build obj= xxx用于指定
#我们的obj目录是哪里!!!!!!!!!!!!

#这个规则有三个依赖:scripts_basic、outputmakefile、FORCE


#PHONY +=scripts_basic                     #定义一个伪目标
#scripts_basic:                                   #该伪目标要执行的操作
$(Q)$(MAKE) $(build)=scripts/basic
#build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.buildobj 

#等价于

#@ make -f  scripts/Makefile.buildobj=scripts/basic

#这个命令依然是执行scripts/Makefile.build这个makefile文件。
#并执行它里面$@表示menuconfig的规则。

#@  make -f scripts/Makefile.build obj=scripts/kconfig  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 specifictargets, clean
# targets and others. In general all targets except *configtargets.
else
ifeq ($(KBUILD_EXTMOD),) #
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scriptstwice
# 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 tovisit
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
-includeinclude/config/auto.conf

ifeq ($(KBUILD_EXTMOD),)
# Read in dependencies to all Kconfig* files, make sure torun
# oldconfig if changes are detected.
-include include/config/auto.conf.cmd

# To avoid any implicit rule to kick in, define an emptycommand
$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;

# If .config is newer than include/config/auto.conf, someonetinkered
# with it and forgot to run make oldconfig.
# if auto.conf.cmd is missing then we are probably in a cleanedtree so
# we execute the config step to be sure to catch updated Kconfigfiles
#这里是生成我们的需要的三个文件
include/config/auto.conf: $(KCONFIG_CONFIG)include/config/auto.conf.cmd
 $(Q)$(MAKE) -f $(srctree)/Makefilesilentoldconfig
else
# external modules needs include/linux/autoconf.h andinclude/config/auto.conf
# but do not care if they are up-to-date. Use auto.conf to triggerthe test
PHONY += include/config/auto.conf

include/config/auto.conf:
 $(Q)test -e include/linux/autoconf.h -a -e $@ ||(  /
 echo;        /
 echo "  ERROR: Kernelconfiguration isinvalid.";  /
 echo"        include/linux/autoconf.h or $@ aremissing."; /
 echo"        Run 'make oldconfig && makeprepare' 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 targetsstarts======================
#==============vmlinux all modules and other targets============
# The all: target is the default when no target is given onthe
# command line.
# This allow a user to issue only 'make' to build a kernelincluding modules
# Defaults vmlinux but it is usually overridden in the archmakefile
all: vmlinux   #这个是默认的目标

ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os
else
KBUILD_CFLAGS += -O2
endif

ifneq (CONFIG_FRAME_WARN,0)
KBUILD_CFLAGS += $(callcc-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 Makefileis included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC)-print-file-name=include)
CHECKFLAGS    += $(NOSTDINC_FLAGS)

# warn about C99 declaration after statement
KBUILD_CFLAGS += $(callcc-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 lastassignments
# But warn user when we do so
warn-assign = /
$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(originK$(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 isgiven.
# KBUILD_IMAGE may be overruled on the command line or
# set in the environment
# Also any assignments in arch/$(ARCH)/Makefile take precedenceover
# this default value
export KBUILD_IMAGE ?=vmlinux

#
# INSTALL_PATH specifies where to place the updated kernel andsystem map
# images. Default is /boot, but you can set it to othervalues
export INSTALL_PATH ?= /boot
#默认的安装目录
#
# INSTALL_MOD_PATH specifies a prefix to MODLIB for moduledirectory
# relocations required by build roots.  This isnot 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 causemodules to be
stripped after they areinstalled.  If INSTALL_MOD_STRIP is '1',then
the default option --strip-debug will beused.  Otherwise,
INSTALL_MOD_STRIP will used as the options tothe 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-leveldirectories
# in the kernel tree, others are specified inarch/$(ARCH)/Makefile.
# Ordering when linking is important, and $(vmlinux-init) must befirst.
#
# 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 needto
# update vmlinux.
# Therefore this step is delayed until just before final link ofvmlinux -
# except in the kallsyms case where it is done just before addingthe
# symbols to the kernel.
#
# System.map is generated to document addresses of all kernelsymbols

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 mainbody 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 otheroperation
     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 isconsistent
# Use + in front of the vmlinux_version rule to silent warning withmake -j2
# First command is ':' to allow us to use + in front of therule

#以下是一个命令包,即一组命令可能在多个规则中使用
#相同的一组命令,通过define来定义这组命令作为一个命令,以后
#在需要的规则中通过变量名直接引用!!!!!!!
definerule_vmlinux__   
#这里是执行vmlinux的规则
 :
 $(if $(CONFIG_KALLSYMS),,+$(callcmd,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 __kallsymsis
  empty
  Running kallsyms on thatgives us .tmp_kallsyms1.o with
  the right size - vmlinuxversion (uname -v) is updated during this step
# o .tmp_vmlinux2 now has a __kallsyms section of the rightsize,
  but due to the added section,some addresses have shifted.
  From here, we generate acorrect .tmp_kallsyms2.o
# o The correct .tmp_kallsyms2.o is linked into the finalvmlinux.
# o Verify that the System.map from vmlinux matches the mapfrom
  .tmp_vmlinux2, just in casewe did not generate kallsyms correctly.
# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra passusing
  .tmp_vmlinux3 and.tmp_kallsyms3.o.  This is only meant as a
  temporary bypass to allow thekernel to be built while the
  maintainers work out whatwent 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 kallsymsdata;                           /
   echo Try settingCONFIG_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 thisrule
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: %.Sscripts 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 updatevmlinux version
.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
 $(call if_changed_rule,ksym_ld)

.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.oFORCE
 $(call if_changed,vmlinux__)

.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.oFORCE
 $(call if_changed,vmlinux__)

# Needs to visit scripts/ before $(KALLSYMS) can be used.
$(KALLSYMS): scripts ;

# Generate some data for debugging strange kallsymsproblems
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 vmlinuxhas
# 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)/Makefileheaders_check
#PHONY += headers_check 当make -f $(srctree)/Makefileheaders_check执行以下命令
#headers_check: headers_install
$(Q)$(MAKE) -f$(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=includeHDRCHECK=1
endif
ifdef CONFIG_SAMPLES 
#配置样本即调用Makefile.build 到Samples目录下make生成样本
 $(Q)$(MAKE) $(build)=samples
endif  
 $(callvmlinux-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 errorsearly
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
 $(callif_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. Limitlocale
# tweaks to this spot to avoid wrong language settings whenrunning
# make menuconfig etc.
# Error messages still appears in the original language

 

###############真正执行动作!!!!!!####################
PHONY += $(vmlinux-dirs)  #伪目标
$(vmlinux-dirs): prepare scripts
 $(Q)$(MAKE) $(build)=$@
#(1)build=-f scripts/Makefile.buildobj=<dir> 进行实际的编
#等价于make -f scripts/Makefile.buildobj=$@
#在Makefile.build中第一个真正的依赖规则是__build 大概在93行进入这里我们
#__build又依赖于各个目录下的build-in.o或者lib.a等
#$@表示vmlinux-dirs变量中的各个目标用于传给obj
#vmlinux-dirs := $(patsubst %/,%,$(filter %/,$(init-y) $(init-m) /
     $(core-y) $(core-m) $(drivers-y) $(drivers-m) /
     $(net-y) $(net-m) $(libs-y) $(libs-m)))

#(2)这里的依赖目标有两个prepare:和scripts
# L1180  prepare: prepare0
# L646   PHONY += scripts
# scripts: scripts_basic include/config/auto.conf

 

 

# Build the kernel release string
#
# The KERNELRELEASE value built here is stored in the file
# include/config/kernel.release, and is used when executingseveral
# make targets, such as "make install" or "makemodules_install."
#
# The eventual kernel release string consists of the followingfields,
# shown in a hierarchical format to show how smaller parts areconcatenated
# to form the larger and final value, with values coming fromplaces like
# the Makefile, kernel config options, make command line optionsand/or
# SCM tag information.
#
$(KERNELVERSION)
 $(VERSION)   eg,2
 $(PATCHLEVEL)   eg,6
 $(SUBLEVEL)   eg,18
 $(EXTRAVERSION)  eg, -rc6
$(localver-full)
  $(localver)
   localversion*  (files withoutbackups, containing '~')
   $(CONFIG_LOCALVERSION) (from kernel configsetting)
 $(localver-auto)  (only ifCONFIG_LOCALVERSION_AUTO is set)
   ./scripts/setlocalversion (SCM tag, if oneexists)
   $(LOCALVERSION)  (from makecommand line if provided)
#
Note how the final $(localver-auto) string isincluded *only* if the
# kernel config option CONFIG_LOCALVERSION_AUTO isselected.  Also, at the
# moment, only git is supported but other SCMs can edit thescript
# scripts/setlocalversion and add the appropriate checks asneeded.

pattern = ".*/localversion[^~]*"
string  = $(shell cat /dev/null /
    `find$(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`)

localver = $(subst $(space),, $(string) /
        $(patsubst "%",%,$(CONFIG_LOCALVERSION)))

# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion iscalled
# and if the SCM is know a tag from the SCM is appended.
# The appended tag is determined by the SCM used.
#
# Currently, only git is supported.
# Other SCMs can edit scripts/setlocalversion and add theappropriate
# checks as needed.
ifdef CONFIG_LOCALVERSION_AUTO
 _localver-auto = $(shell $(CONFIG_SHELL) /
                  $(srctree)/scripts/setlocalversion $(srctree))
 localver-auto  =$(LOCALVERSION)$(_localver-auto)
endif

localver-full = $(localver)$(localver-auto)

# Store (new) KERNELRELASE string ininclude/config/kernel.release
kernelrelease = $(KERNELVERSION)$(localver-full)
include/config/kernel.release: include/config/auto.conf FORCE
 $(Q)rm -f $@
 $(Q)echo $(kernelrelease) > $@


# Things we need to do before we recursively start building thekernel
# or the modules are listed in "prepare".
# A multi level approach is used. prepareN is processed beforeprepareN-1.
# archprepare is used in arch Makefiles and when processed asmsymlink,
# version.h and scripts_basic is processed / created.

# Listed in dependency order
PHONY += prepare archprepare prepare0 prepare1 prepare2prepare3
#定义多个伪目标
# prepare3 is used to check if we are building in a separate outputdirectory,
#第三步主要检查我们是否为自定义了输出目录
# and if so do:
# 1) Check that make has not been executed in the kernel src$(srctree)
# 2) Create the include2 directory, used for the second asmsymlink
prepare3: include/config/kernel.release
ifneq ($(KBUILD_SRC),)
 @echo '  Using $(srctree) assource for kernel'
 $(Q)if [ -f $(srctree)/.config -o -d$(srctree)/include/config ]; then /
  echo " $(srctree) is not clean, please run 'make mrproper'";/
  echo "  in the'$(srctree)' directory.";/
  /bin/false; /
 fi;
 $(Q)if [ ! -d include2 ]; then mkdir -p include2;fi;
 $(Q)ln -fsn $(srctree)/include/asm-$(SRCARCH)include2/asm
endif

# prepare2 creates a makefile if using a separate outputdirectory
prepare2: prepare3 outputmakefile

prepare1: prepare2 include/linux/version.hinclude/linux/utsrelease.h /
                  include/asm include/config/auto.conf
 $(cmd_crmodverdir)

archprepare: prepare1 scripts_basic

prepare0: archprepare FORCE
 $(Q)$(MAKE) $(build)=.
 $(Q)$(MAKE) $(build)=. missing-syscalls

# All the preparing..
prepare: prepare0

 


# Leave this as default for preprocessing vmlinux.lds.S, which isnow
# done in arch/$(ARCH)/kernel/Makefile

export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)

# The asm symlink changes when $(ARCH) changes.
# Detect this and ask user to run make mrproper
#set -e 是设置一种shell状态即如果它执行的任何一条命令的退出码非零
#都立刻终止

include/asm: FORCE
 $(Q)set -e; asmlink=`readlink include/asm | cut-d '-' -f 2`;   /
 if [ -L include/asm ];then                                    /
  if [ "$$asmlink" !="$(SRCARCH)" ];then               /
   echo "ERROR:the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) wasexpected"; /
   echo"      set ARCH or save .config and run 'make mrproper' to fixit";            /
   exit1;                                        /
  fi;                                                    /
 else                                                           /
  echo ' SYMLINK $@ ->include/asm-$(SRCARCH)';         /
  if [ ! -d include ];then                              /
   mkdir -pinclude;                              /
  fi;                                                    /
  ln -fsn asm-$(SRCARCH)$@;                             /
 fi

# Generate some files
#---------------------------------------------------------------------------

# KERNELRELEASE can change from a few different places, meaningversion.h
# needs to be updated, so this check is forced on all builds

uts_len := 64
define filechk_utsrelease.h
 if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt$(uts_len) ]; then /
   echo '"$(KERNELRELEASE)"exceeds $(uts_len) characters'>&2;   /
   exit1;                                                        /
 fi;                                                              /
 (echo /#define UTS_RELEASE/"$(KERNELRELEASE)/";)
endef

define filechk_version.h
 (echo /#define LINUX_VERSION_CODE$(shell                            /
 expr $(VERSION) Kbuild)))

PHONY += headers_install_all
headers_install_all: include/linux/version.h scripts_basicFORCE
 $(Q)$(MAKE) $(build)=scriptsscripts/unifdef
 $(Q)for arch in $(HDRARCHES); do /
  $(MAKE) ARCH=$$arch -f$(srctree)/scripts/Makefile.headersinst obj=includeBIASMDIR=-bi-$$arch ;/
  done

PHONY += headers_install
headers_install: include/linux/version.h scripts_basic FORCE
 @if [ ! -r$(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then /
   echo '*** Error: Headers notexportable for this architecture ($(SRCARCH))'; /
   exit 1 ; fi
 $(Q)$(MAKE) $(build)=scriptsscripts/unifdef
 $(Q)$(MAKE) -f$(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH)obj=include

PHONY += headers_check_all
headers_check_all: headers_install_all
 $(Q)for arch in $(HDRARCHES); do /
  $(MAKE) ARCH=$$arch -f$(srctree)/scripts/Makefile.headersinst obj=includeBIASMDIR=-bi-$$arch HDRCHECK=1 ;/
  done

PHONY += headers_check
headers_check: headers_install
 $(Q)$(MAKE) -f$(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=includeHDRCHECK=1

#---------------------------------------------------------------------------
# Modules

ifdef CONFIG_MODULES

# By default, build modules as well

all: modules

Build modules
#
A module can be listed more than once in obj-mresulting in
duplicate lines in modules.orderfiles.  Those are removed
using awk while concatenating to the finalfile.

PHONY += modules
modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
 $(Q)$(AWK) '!x[$$0]++'$(vmlinux-dirs:%=$(objtree)/%/modules.order) >$(objtree)/modules.order
 @echo '  Building modules, stage2.';
 $(Q)$(MAKE) -f$(srctree)/scripts/Makefile.modpost


# Target to prepare building external modules
PHONY += modules_prepare
modules_prepare: prepare scripts

# Target to install modules
PHONY += modules_install
modules_install: _modinst_ _modinst_post

PHONY += _modinst_
_modinst_:
 @if [ -z "`$(DEPMOD) -V2>/dev/null | grep module-init-tools`" ]; then/
  echo "Warning: you may need toinstall module-init-tools"; /
  echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";/
  sleep 1; /
 fi
 @rm -rf $(MODLIB)/kernel
 @rm -f $(MODLIB)/source
 @mkdir -p $(MODLIB)/kernel
 @ln -s $(srctree) $(MODLIB)/source
 @if [ ! $(objtree) -ef $(MODLIB)/build ]; then /
  rm -f $(MODLIB)/build ; /
  ln -s $(objtree)$(MODLIB)/build ; /
 fi
 @cp -f $(objtree)/modules.order $(MODLIB)/
 $(Q)$(MAKE) -f$(srctree)/scripts/Makefile.modinst

# This depmod is only for convenience to give the initial
# boot a modules.dep even before / is mountedread-write.  However the
# boot script depmod is the master version.
PHONY += _modinst_post
_modinst_post: _modinst_
 $(call cmd,depmod)

else # CONFIG_MODULES

# Modules not configured
#---------------------------------------------------------------------------

modules modules_install: FORCE
 @echo
 @echo "The present kernel configuration hasmodules disabled."
 @echo "Type 'make config' and enable loadablemodule support."
 @echo "Then build a kernel with module supportenabled."
 @echo
 @exit 1

endif # CONFIG_MODULES

###
# Cleaning is done on three levels.
# makeclean    Delete most generated files
              Leave enough to build external modules
# make mrproper  Delete the current configuration,and all generated files
# make distclean Remove editor backup files, patch leftover filesand the like

# Directories & files removed with 'makeclean'


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值