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, do not
# expect to learn how to build the kernel reading this file.
# Do not:
# o
#
# o
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 little thinking
# to get the ordering right.
#
# Most importantly: sub-Makefiles should only ever modify files in
# their own directory. If in some directory we have a dependency on
# a file in another dir (which doesn't happen often, but it's often
# 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 other dir
# is now up to date.
#
# The only cases where we need to modify files which have global
# effects are thus separated out and done before the recursive
# descending is started. They are now explicitly listed as the
# prepare rule.
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands
ifdef V
endif
ifndef KBUILD_VERBOSE
endif
# 函数origin并不操作变量的值,只是告诉你‘你的这个变量’是哪里来的。
# 语法是: $(origin ;)# origin函数的返回值有:
#"undefined"从来没有定义过、“default”是一个默认的定义、“
#"environment"是一个环境变量、
#"file"这个变量被定义在Makefile中
#"command line"这个变量是被命令行定义的
#"override"是被override指示符重新定义的
#"automatic"是一个命令运行中的自动化变量
# Call a source code checker (by default, "sparse") as part of the
# C compilation.调用一个静态分析工具作为c编译器的
#部分
# Use 'make C=1' to enable checking of only re-compiled files.
# 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
endif
ifndef KBUILD_CHECKSRC
endif
#用M来指定外部模块的目录
# Use make M=dir to specify directory of external module to build
# Old syntax make ... SUBDIRS=$PWD is still supported
# Setting the environment variable KBUILD_EXTMOD take precedence
#识别这里是定义一个外部模块吗??
#当我们定义了M变量或者SUBDIRS时表示编译一个外部模块
# “?=”操作符
#条件赋值的赋值操作符。被称为条件赋值是因为:只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。例如:
#其等价于:
#含义是:如果变量“FOO”在没有定义过,就给它赋值“bar”。否则不改变它的值。
ifdef SUBDIRS
endif
ifdef M
在使用“:=”
定义变量时,变量值中对另外变量的引用或者函数的引用在定义时被展开(对变量进行替换)
而=是在使用时才进行替换
举例:
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”。
endif
# kbuild supports saving output files in a separate directory.
# To locate output files in a separate directory two syntaxes are supported.
# In both cases the working directory must be the root of the kernel src.
# 1) O=
# Use "make O=dir/to/store/output/files/"
#
# 2) Set KBUILD_OUTPUT
# Set the environment variable KBUILD_OUTPUT to point to the directory
# where the output files shall be placed.
# export KBUILD_OUTPUT=dir/to/store/output/files/
# make
#
# The O= assignment takes precedence over the KBUILD_OUTPUT environment
# variable.
# KBUILD_SRC is set on invocation of make in OBJ directory
# KBUILD_SRC is not intended to be used by the regular user (for now)
###################make 的最开始###################
####################################################
ifeq ($(KBUILD_SRC),)#如果KBUILD_SRC没有定义则进入下面一层即首次进入
# OK, Make called in directory where kernel src resides
# Do we want to locate output files in a separate directory?
ifdef O
endif
# That's our default target when none is given on the command line
PHONY := _all
_all:
# Cancel implicit rules on top Makefile取消隐式推倒规则
$(CURDIR)/Makefile Makefile: ;
ifneq ($(KBUILD_OUTPUT),)
# Invoke a second make in the output directory, passing relevant variables
# check that the output directory actually exists
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
$(if $(KBUILD_OUTPUT),, /
# make的环境变量叫MAKECMDGOALS 这个变量中会存放你所指定的
# 终极目标的列表,如果在命令行上,你没有指定目标,
#那么,这个变量是空值。
PHONY += $(MAKECMDGOALS) sub-make
# 将任何在‘命令行’中给出的‘目标’放入变量MAKECMDGOALS
#这里 filter-out是返回$(MAKECMDGOALS)中除了Makefile _all sub-make以外的
#其他文件; 匹配模式的过滤掉,留下不匹配的
$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
#这里仅仅只是取消回显没有别的意思
#如果要执行的命令行以字符“@”开始,则 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
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)这里是ifneq
endif # ifeq ($(KBUILD_SRC),)#这里是ifeq的结束处
####################################################
####################################################
ifeq ($(skip-makefile),)
# If building an external module we do not care about the all: rule
# but instead _all depend on modules
PHONY += all
ifeq ($(KBUILD_EXTMOD),) #如果外部模块定义为空则_all依赖于all
_all: all
else
_all: modules
endif
srctree
TOPDIR
# FIXME - TOPDIR is obsolete, use srctree/objtree
objtree
src
obj
VPATH:=$(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))#这里是说当前目录找不到源文件时的搜索目录
export srctree objtree VPATH TOPDIR
# SUBARCH tells the usermode build what the underlying arch is.
# first, and if a usermode build is happening, the "ARCH=um" on the command
# line overrides the setting of ARCH below.
# 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/ -e s/sun4u/sparc64/ /
# Cross compiling and selecting different set of gcc/bin-utils
# ---------------------------------------------------------------------------
#
# When performing cross compilation for other architectures ARCH shall be set
# to the target architecture. (See archMakefile
export KBUILD_BUILDHOST := $(SUBARCH) #这里是把宿主机的cpu结构导出到
ARCH
# 设置变量 ARCH 的方法有两种,
# 一:在命令行中 如: make ARCH=ia64 ;
# 二:设置环境变量,在环境变量中默认
#的 ARCH 的值是执行 make 的 cpu 架构
#
#成功,否则不重新赋值
CROSS_COMPILE
# Architecture as present in compile.h
UTS_MACHINE
SRCARCH
# Additional ARCH settings for x86
ifeq ($(ARCH),i386)
endif
ifeq ($(ARCH),x86_64)
endif
KCONFIG_CONFIG
# SHELL used by kbuild 这里shel中的if [ -x file ]测试file是否可执行
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; \
HOSTCC
HOSTCXX
HOSTCFLAGS
HOSTCXXFLAGS = -O2
# Decide whether to build built-in, modular, or both.
# Normally, just do built-in.
KBUILD_MODULES :=
KBUILD_BUILTIN := 1
#
#
#
#
#如果执行”make modules”则这里在这里重新处理KBUILD_BUILTIN :=1
ifeq ($(MAKECMDGOALS),modules)
endif
#
#
#
#如果执行"make all","make _all","make modules","make"中任一个命令
#则在这里重新处理KBUILD_MODULES
ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)#filter过滤出指定的字符串
endif
ifeq ($(MAKECMDGOALS),)
endif
export KBUILD_MODULES KBUILD_BUILTIN
#导出变量给
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.
#
#
#
# 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.
#
#
# 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) #这里就是定义是否要回显
else
endif
# If the user is running make -s (silent mode), suppress echoing of
# commands
ifneq ($(findstring s,$(MAKEFLAGS)),)
#如果MAKEFLAGS中带了-s表示完全不要回显
endif
export quiet Q KBUILD_VERBOSE
# 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).
include
#这里执行remake操作请看GNU make 流程
include $(srctree)/scripts/Kbuild.include #这里是文件包含
# Kbuild.include 这里定义了大量通用的函数和变量
#重点!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Make variables (CC, etc...)
#这里是设置编译连接的默认程序,都是变量赋值操作
AS
LD
CC
CPP
AR
NM
STRIP
OBJCOPY
OBJDUMP
AWK
GENKSYMS
DEPMOD
KALLSYMS
PERL
CHECK
CHECKFLAGS
MODFLAGS
CFLAGS_MODULE
AFLAGS_MODULE
LDFLAGS_MODULE
CFLAGS_KERNEL
AFLAGS_KERNEL
# Use LINUXINCLUDE when you must reference the include/ directory.
# Needed to be compatible with the O= option
LINUXINCLUDE
KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
KBUILD_CFLAGS
KBUILD_AFLAGS
# 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: #该伪目标要执行的操作
#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),)
#这个规则的命令运行一个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 /
#这里是默认值,
config-targets := 0#如果有config %config则为1
mixed-targets
dot-config
#根据输出参数修改
#这一段通过分析command line,判断make的目标是config还是build,或者是mixed-target,即先config再build。
#make后面的目标包括三类:
#(1)和.config无关的目标即(no_dot_config-targets)比如:clean,mrproper,distclean,
#
#(2)和.config相关的目标dot_config
#
#
#(3)single targets
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)#如果我们命令行目标CMDGOALS
endif
ifeq ($(KBUILD_EXTMOD),)
endif
# ============混合模式则则执行以下规则===========
ifeq ($(mixed-targets),1) #如果是混合模式则则执行以下规则
# We're called with mixed targets (*config and build targets).
# Handle them one by one.
#%代表make 后带任何目标都执行该命令
#那就是
%:: FORCE
#从代码中可以看出,这里使用了一个双冒号的模式匹配规则。
#百分号代表任何目标都使用这个规则,其中
#$(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
export KBUILD_DEFCONFIG
###############执行make menuconfig的入口点#####################
#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.build obj#等价于
#@ make -fscripts/Makefile.build obj=scripts/basic
#这个命令依然是执行:scripts/Makefile.build这个makefile文件。
#并执行它里面$@表示menuconfig的规则。
#@
根据上面的分析,
#在Makefile.build会包含scripts/kconfig/Makefile文件!!!!!!!!!!!!!。
#然后执行以menuconfig为目标的规则,
#在scripts/kconfig/Makefile的13行定义
#menuconfig: $(obj)/mconf
#即$<表示依赖集$(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
#这里生成scripts_basic include/config/auto.conf
# Objects we will link into vmlinux / subdirs we need to visit
init-y
drivers-y
net-y
libs-y
core-y
endif # KBUILD_EXTMOD
ifeq ($(dot-config),1)
-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
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:
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
else
KBUILD_CFLAGS
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
else
KBUILD_CFLAGS
endif
ifdef CONFIG_DEBUG_INFO
KBUILD_CFLAGS
KBUILD_AFLAGS
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
# 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),)
endif
ifneq ($(KAFLAGS),)
endif
ifneq ($(KCFLAGS),)
endif
# Use --build-id when available.
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,/
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_MOD_PATH specifies a prefix to MODLIB for module directory
# relocations required by build roots.
# makefile but the argument can be passed to make if needed.
#
MODLIB
export MODLIB
#
#
#
#
#
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
#此时我们的core-y目标需要添加各个模块
#vmlinux-dirs即我们编译内核需要添加的各个模块
#所在的内核目录
vmlinux-dirs
#这里的vmlinux即取目录名称
vmlinux-alldirs
#################重点###############################
################################################
################################################
init-y
core-y
drivers-y
net-y
libs-y1
libs-y2
libs-y
# 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 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)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)#the main body of linux kernel;
vmlinux-all
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
# Generate new vmlinux version
quiet_cmd_vmlinux_version = GEN
# Generate System.map
quiet_cmd_sysmap = SYSMAP
# 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的规则
#cmd = @$(echo-cmd) $(cmd_$(1))
#即被展开为cmd_vmlinux__!!!!!!!!!!!!!!!=======
#而此命令为一个连接命令,如下!!!!!!!!========即我们连接命令
#cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ /
#
#
#
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
#
#
#
# o .tmp_vmlinux2 now has a __kallsyms section of the right size,
#
#
# o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
# o Verify that the System.map from vmlinux matches the map from
#
# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
#
#
#
ifdef CONFIG_KALLSYMS_EXTRA_PASS
last_kallsyms := 3
else
last_kallsyms := 2
endif
kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
#以下是一个命令包,即一组命令可能在多个规则中使用
#相同的一组命令,通过define来定义这组命令作为一个命令,以后
#在需要的规则中通过变量名直接引用!!!!!!!
define verify_kallsyms
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
endef
# Generate .S file with all kernel symbols
quiet_cmd_kallsyms = KSYM
.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
# 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
.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
define rule_vmlinux-modpost: #定义命令包
endef
#==================================================
#==================================================
#vmlinux的依赖目标集,开始真正的做主目录下的映像文件
# vmlinux image - including updated kernel symbols
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
#PHONY += headers_check 当make -f $(srctree)/Makefile headers_check执行以下命令
#headers_check: headers_install
#
endif
ifdef CONFIG_SAMPLES
#配置样本即调用Makefile.build 到Samples目录下make生成样本
endif
#在我们所以依赖目标都生成后我们开始链接!!!!!!!!!!===========
#if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ),
#
#
# 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
# 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
###############真正执行动作!!!!!!####################
PHONY += $(vmlinux-dirs)
$(vmlinux-dirs): prepare scripts
#(1)build=-f scripts/Makefile.build obj=
#等价于 make
#在Makefile.build中第一个真正的 依赖规则 是__build 大概在93行进入这里我们
#__build又 依赖于 各个目录下的build-in.o或者lib.a等
# $@ 表示 vmlinux-dirs变量 中的各个 目标 用于 传给obj
#vmlinux-dirs
#
#
#(2)这里的依赖目标有两个prepare:和scripts
# L1180
# L646
# 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 executing several
# make targets, such as "make install" or "make modules_install."
#
# The eventual kernel release string consists of the following fields,
# shown in a hierarchical format to show how smaller parts are concatenated
# to form the larger and final value, with values coming from places like
# the Makefile, kernel config options, make command line options and/or
# SCM tag information.
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
# kernel config option CONFIG_LOCALVERSION_AUTO is selected.
# moment, only git is supported but other SCMs can edit the script
# scripts/setlocalversion and add the appropriate checks as needed.
pattern = ".*/localversion[^~]*"
string
localver = $(subst $(space),, $(string) /
# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
# 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 the appropriate
# checks as needed.
ifdef CONFIG_LOCALVERSION_AUTO
endif
localver-full = $(localver)$(localver-auto)
# Store (new) KERNELRELASE string in include/config/kernel.release
kernelrelease = $(KERNELVERSION)$(localver-full)
include/config/kernel.release: include/config/auto.conf FORCE
# Things we need to do before we recursively start building the kernel
# or the modules are listed in "prepare".
# A multi level approach is used. prepareN is processed before prepareN-1.
# archprepare is used in arch Makefiles and when processed asm symlink,
# version.h and scripts_basic is processed / created.
# Listed in dependency order
PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
#定义多个伪目标
# prepare3 is used to check if we are building in a separate output directory,
#第三步主要检查我们是否为自定义了输出目录
# 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 asm symlink
prepare3: include/config/kernel.release
ifneq ($(KBUILD_SRC),)
endif
# prepare2 creates a makefile if using a separate output directory
prepare2: prepare3 outputmakefile
prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h /
archprepare: prepare1 scripts_basic
prepare0: archprepare FORCE
# All the preparing..
prepare: prepare0
# Leave this as default for preprocessing vmlinux.lds.S, which is now
# 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
# Generate some files
# ---------------------------------------------------------------------------
# KERNELRELEASE can change from a few different places, meaning version.h
# needs to be updated, so this check is forced on all builds
uts_len := 64
define filechk_utsrelease.h
endef
define filechk_version.h
PHONY += headers_install_all
headers_install_all: include/linux/version.h scripts_basic FORCE
PHONY += headers_install
headers_install: include/linux/version.h scripts_basic FORCE
PHONY += headers_check_all
headers_check_all: headers_install_all
PHONY += headers_check
headers_check: headers_install
# ---------------------------------------------------------------------------
# Modules
ifdef CONFIG_MODULES
# By default, build modules as well
all: modules
#
#
#
#
#
PHONY += modules
modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
# 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_:
# This depmod is only for convenience to give the initial
# boot a modules.dep even before / is mounted read-write.
# boot script depmod is the master version.
PHONY += _modinst_post
_modinst_post: _modinst_
else # CONFIG_MODULES
# Modules not configured
# ---------------------------------------------------------------------------
modules modules_install: FORCE
endif # CONFIG_MODULES
###
# Cleaning is done on three levels.
# make clean
#
# make mrproper
# make distclean Remove editor backup files, patch leftover files and the like
# Directories & files removed with 'make clean'