UBOOT主makefile注释

整体注释在notepad中完成,复制下来用notepad打开,格式应该会很完美。

#本文档仅做参考,注释随意写的
# SPDX-License-Identifier:	GPL-2.0+
#
#如果 Tab 字符之后使用 # 字符,则会被 make 解释为命令行)。注释行的结尾如果存在反斜线(\),那么下一行也被作为注释行。如果#号以tab开头,makefile虽然不会执行,但是会回显到终端上。

VERSION = 2017
PATCHLEVEL = 03
SUBLEVEL =
EXTRAVERSION =
NAME =
#makefile中变量的定义等号两边可以有空格,而在shell中变量的定义赋值号两边不能有空格

# *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.

# o Do not use make's built-in rules and variables内置的规则和变量。
#   (this increases performance性能 and avoids hard-to-debug behaviour难以调试的行为);
# o Look for make include files relative to root of kernel src
MAKEFLAGS += -rR --include-dir=$(CURDIR) 
#当前工作目录,(makefile所在目录),这是内置变量。在 make 的递归调用中,需要了解一下变量“ CURDIR”,此变量代表 make 的工作目录。当使用“ -C”选项进入一个子目录后,此变量将被重新赋值。总之,如果在Makefile 中没有对此变量进行显式的赋值操作,那么它代表 make 的工作目录。
#这是GNU   make的的环境变量,为了避免覆盖已有值,所以使用+=来追加变量。变量MAKEFLAGS值中的字可以包含‘=’,make将它们按变量定义处理
#“-rR”表示禁止使用内置的隐含规则和变量定义,“--include-dir”指明搜索路径,”$(CURDIR)”表示当前目录。
# 在下一级子目录中执行的make时,这些选项会被附加作为make的命令行参数来执行,
#环境变量可以在Makefile里面定义,也可以在make命令的命令行参数中定义,还可以在操作系统的环境变量中定义。
#。有时候我们需要向子 make 传递变量,这个时候使用“export”来导出要传递给子 make 的变量即可。
#有两个特殊的变量:“SHELL”和“MAKEFLAGS”!!!!这两个变量除非使用“unexport”声明,否则的话在整个make的执行过程中,它们的值始终自动的传递给子make。
##使用“make -s”编译的时候,“-s”会作为 MAKEFLAGS 变量的一部分传递给 Makefile。

# Avoid funny character set dependencies
unexport LC_ALL
##非传递环境变量,不会传递到下一级Makefile
#export用于将上层makefile中定义的变量传递到子makefile中使用。当没有使用指示符“ export”对任何变量进行声明的情况下,上层 make 只将那些已经初始化的环境变量(在执行 make 之前已经存在的环境变量)和使用命令行指定的变量(如命令“ makeCFLAGS +=-g”或者“ make –e CFLAGS +=-g”)传递给子 make 程序。
LC_COLLATE=C
LC_NUMERIC=C
export LC_COLLATE LC_NUMERIC

# Avoid interference with shell env settings
unexport GREP_OPTIONS

# 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 finally
# 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.

# Beautify output上面这段没用,重点是下:
#uboot默认编译时输出短命令,要输出完整命令就 make V=1
# ---------------------------------------------------------------------------
#
# 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.
# If it is set to "silent_", nothing will be printed at all, since
# the variable $(silent_cmd_cc_o_c) doesn't exist!!!!!!
#
# A simple variant is to prefix前缀 commands with $(Q) - that's useful
# 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.
#
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands

ifeq ("$(origin V)", "command line")
#变量 V 的来源。如果变量 V 是在命令行定义的那么它的来源就是"command line"
#origin函数的返回值有:
#   "undefined"从来没有定义过、“default”是一个默认的定义、“
#   "environment"是一个环境变量、
#   "file"这个变量被定义在Makefile中
#   "command line"这个变量是被命令行定义的
#   "override"是被override指示符重新定义的
#   "automatic"是一个命令运行中的自动化变量

  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif
#uboot 默认编译是不会在终端中显示完整的命令,都是短命令。是不利于分析 uboot 的编译过程。可以通过设置变量“V=1“来实现完整的命令输出,这个在调试 uboot 的时候很有用。



#编译的时候使用“make -s”即可实现静默输出。
#设置 V=0 或者在命令行中不定义 V 的话,编译 uboot 的时候终端中显示的短命令,但是还是会有命令输出,有时候我们在编译 uboot 的时候不需要输出命令,这个时候就可以使用 uboot 的静默输出功能
# If the user is running make -s (silent mode), suppress抑制 echoing回声,回显 of
# commands  尚上面V是决定短命令和长命令,但一定会输出,这里决定输出与否。
#使用“make -s”编译的时候,“-s”会作为 MAKEFLAGS 变量的一部分传递给 Makefile。

ifneq ($(filter 4.%,$(MAKE_VERSION)),)	# make-4    Makefile 中内置的标准变量
#是在字符串“MAKE_VERSION”中找出符合“4.%”的字符(%为通配符), MAKE_VERSION 是make工具的版本号,ubuntu16.04里面默认自带的make工具版本号为4.1,大家可以输入“make -v”查看
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)   #取首单词
#$(filter PATTERN…,TEXT) 过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。
  quiet=silent_
endif
else					# make-3.8x
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
  quiet=silent_
endif
endif

export quiet Q KBUILD_VERBOSE

# 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(OBJ目录调用make时设置KBUILD_SRC)
#应该是make KBUILD_SRC=***这样。
# KBUILD_SRC is not intended to be used by the regular user (for now)
ifeq ($(KBUILD_SRC),)

# OK, Make called in directory where kernel src resides
# Do we want to locate output files in a separate directory?
ifeq ("$(origin O)", "command line") #O来自命令行
  KBUILD_OUTPUT := $(O)  #"make O=dir/to/store/output/files/"
endif

# That's our default target when none is given on the command line
PHONY := _all  #本文档最后一行有.PHONY: $(PHONY)
#在Makefile中,.PHONY后面的target表示的也是一个伪造的target, 而不是真实存在的文件target,注意Makefile的target默认是文件。


_all: #在这里好像就是没有什么意义的。
#这是默认目标,第一个目标!!!!make编译的时候就执行这个目标。后面还会出现这个目标,是会合并的。
#这里出现个空的目的应该就是抢第一个目标的位置。

# Cancel implicit隐含的 rules on top Makefile?
$(CURDIR)/Makefile Makefile: ;  #操作查看当前目录Makefile是否为最新
#makefile的规则中命令可以和目标:依赖写在一行,用分号隔开!!!!不写在同一行的时候必须TAB开头。
#这是一条"空指令",Makefile中使用空命令行来阻止make使用隐含规则构建指定目标!!但目标:依赖后面没有命令的时候,就会使用makefile的隐含规则进行处理。加上一个空命令,就不会套用隐含规则了。
插入:分号是什么时候用,什么时候不用,可以参考经典示例代码如下:
var=3                       # a
target:
       echo $(var)          # b
       var=4                # c
       echo $(var)          # d
       echo $$var           # e
a:定义Makefile中的变量var,值为3
b:打印Makefile中的变量,值为3
c:定义shell命令中的变量var,值为4,Makefile的变量var不受影响
d:打印Makefile中的变量,值为3!!!!!!!!!!!!!!!
e:打印shell命令中的变量。此时var为未定义的变量。

读者可能会奇怪,shell命令中的var明明已经定义了,为什么是未定义呢?
原因:在Makefile的规则命令,如果相互之间没有使用';\'连接起来的话,相互之间是不能共享变量的!!!!!
修改示例代码,使用';\'连接shell规则命令行。
var=3                         # a
target:
       echo $(var);\          # b
       var=4;\                # c
       echo $(var);\          # d
       echo $$var             # e
此时,b、d、e行的输出结果分别为334,符合用户的预期。

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 mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
								&& /bin/pwd)
#调用 mkdir 命令,创建 KBUILD_OUTPUT 目录,并且将创建成功以后的绝对路径赋值给 KBUILD_OUTPUT。至此,通过 O 指定的输出目录就存在了。
#makefile中每一行命令会用一个进程来处理,所以,需要一起执行的命令用\连起来,不要另起一行。否则,pwd就不是上面cd的目录了,相当于重新开了一个终端。
$(if $(KBUILD_OUTPUT),, \
     $(error failed to create output directory "$(saved-output)"))
#if函数:$(if <condition>,<then-part>,<else-part>)

PHONY += $(MAKECMDGOALS) sub-make
#有一个 make 的环境变量叫“MAKECMDGOALS”,这个变量中会存放你所指定的终极目标的列表,如果在命令行上,你没有指定目标,那么,这个变量是空值。make ***_defconfig,这个***_defconfig就会给MAKECMDGOALS

$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
	@:  
#命令中仅有一个:是什么意思?:冒号在shell中为空命令。
#命令前加@表示禁止回显。filter函数是扔掉不符合的,filter-out是挑出不符合的用。

sub-make: FORCE
	$(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \
	-f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS))
#最后有FORCE:只有一个目标没依赖没命令。这样的目标在作为一个规则的依赖时,因为依赖总被认为被更新过,因此作为依赖所在的规则中定义的命令总会被执行。
#-C表示进入那个文件夹读取那里的makefile.-f指定要执行的make的文件名。
#Makefile的文件名 默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件。如果要指定特定的Makefile,你可以使用make的“- f”和“--file”参数。
#??????????????

# Leave processing to above invocation of make
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)
endif # ifeq ($(KBUILD_SRC),)

# We process the rest of the Makefile if this is the final invocation of make
ifeq ($(skip-makefile),)

# Do not print "Entering directory ...",
# but we want to display it when entering to the output directory
# so that IDEs/editors are able to understand relative filenames.
MAKEFLAGS += --no-print-directory

# Call a source code checker (by default, "sparse") as part of the
# C compilation.
#
# Use 'make C=1' to enable checking of only re-compiled files.
#使用命令“make C=1”使能代码检查,检查那些需要重新编译的文件。
# 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效用,实用程序.

ifeq ("$(origin C)", "command line")
  KBUILD_CHECKSRC = $(C)
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
endif


# Use make M=dir to specify指定,明确 directory of external module to build
#uboot可以编译模块,一般不用。
# Old syntax make ... SUBDIRS=$PWD is still supported
# Setting the environment variable KBUILD_EXTMOD take precedence
#SUBDIRS 这个变量是通过执行 make 的时候传进来的,我们没有定义。
ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS)
endif

ifeq ("$(origin M)", "command line") #判断是否在命令行定义了 M
  KBUILD_EXTMOD := $(M)
endif

# 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。看另一个makefile吧,这个文件中被我删了,因为我们make **_defconfig	的时候有很多没用的。下面都是为了make ***defconfig注释的。
else
_all: modules
endif
#判断 KBUILD_EXTMOD 时为空,如果为空的话目标_all 依赖 all,因此要先编译出 all。否则的话默认目标_all 依赖 modules,要先编译出 modules,也就是编译模块。一般情况下我们不会在 uboot 中编译模块,所以此处会编译 all 这个目标。

ifeq ($(KBUILD_SRC),) 
        # building in the source tree
        srctree := .
else
        ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))
                # building in a subdirectory of the source tree
                srctree := ..
        else
                srctree := $(KBUILD_SRC)
        endif
#判断 KBUILD_SRC 是否为空,如果为空的话就设置变量 srctree 为当前目录,即srctree 为“.”,一般不设置 KBUILD_SRC。
endif
objtree		:= .
src		:= $(srctree)
obj		:= $(objtree)
#两个都是当前目录
#以上,使用变量立即展开方式分别设置源码树目录,顶层目录,目标数目录,源文件目录、目标目录。

VPATH		:= $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
# “VPATH”是Makefile文件中的特殊变量。通过变量“ VPATH”可以指定makefile中所有文件(包括依赖文件和目标文件)的搜索路径。
# 如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。
# 如果定义了这个变量,那么,make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件了。
#变量大写的一般都是特殊的变量,比如环境变量。

export srctree objtree VPATH
#关键词export用来声明变量,被声明的变量要被传递到下级Makefile中。

# Make sure CDPATH settings don't interfere干涉
unexport CDPATH

#########################################################################
#sed 是一种在线编辑器,它一次处理一行内容。
# Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

#顶层 Makefile 会获取主机架构和系统,也就是我们电脑的架构和系统
HOSTARCH := $(shell uname -m | \
	sed -e s/i.86/x86/ \
	    -e s/sun4u/sparc64/ \
	    -e s/arm.*/arm/ \
	    -e s/sa110/arm/ \
	    -e s/ppc64/powerpc/ \
	    -e s/ppc/powerpc/ \
	    -e s/macppc/powerpc/\
	    -e s/sh.*/sh/)
#HOSTARCH是主机架构
#uname -m是shell命令,显示电脑类型。-s或--sysname 显示操作系统名称。|是管道。
#一次更改多替换文本中多个值,点是正则表达式中的单字符通配符。
#对于386架构而言,SUBARCH将会被展开成i386
#sed -e 是替换命令,“sed -e s/i.86/x86/”表示将管道输入的字符串中的“i.86”替换为“x86”

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
	    sed -e 's/\(cygwin\).*/cygwin/')
# uname -s得到Linux.   最终得到就是全部变成小写,成了linux.
#tr命令可以对来自标准输入的字符进行替换、压缩和删除。它可以将一组字符变成另一组字符

export	HOSTARCH HOSTOS
 #导出 HOSTARCH=x86_64,HOSTOS=linux。

#########################################################################

# set default to nothing for native builds
#编 译 uboot 的 时 候 需 要 设 置 目 标 板 架 构 和 交 叉 编 译 器
#这么看ARCH是需要在命令行当做选项输入的。又或者是已经在环境变量中。
#make 在运行时,系统中的所有环境变量对它都是可见的。
#正因为如此,我们就可以设置一个命名为“CFLAGS”的环境变量,用它来指定一个默认的编译选项。就可以在所有的Makefile 中直接使用这个变量来对 c 源代码就行编译。

ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif
#判断 HOSTARCH 和 ARCH 这两个变量是否相等,主机架构(变量 HOSTARCH)是 x86_64,而我们编译的是 ARM 版本 uboot,肯定不相等,所以 CROS_COMPILE= arm-linuxgnueabihf-。从示例代码 31.3.9.1 可以看出,每次编译 uboot 的时候都要在 make 命令后面设置ARCH 和 CROS_COMPILE,使用起来很麻烦,可以直接修改顶层 Makefile,在里面加入 ARCH和 CROSS_COMPILE 的定义(摘自原子)
#但是韦东山老师这里也没有加入呀,为什么编译的时候不指定选项ARCH、CROSS_COMPILE 也可以呢?????
#在ubuntu中echo $ARCH或者直接env查看所有环境变量,可以看到环境变量已经设置成了:ARCH=arm;CROSS_COMPILE=arm-linux-gnueabihf-
#不过并没有人明确的说make中这两个变量会采用系统环境变量的,只是我的猜测,不知道为什么。


KCONFIG_CONFIG	?= .config
export KCONFIG_CONFIG
#如果没有指定配置文件则使用默认配置文件,.config为默认的配置文件,赋值给KCONFIG_CONFIG变量供后面的规则使用。
#uboot 是可以配置的,这里设置配置文件为.config,.config 默认是没有的,需要使用命令“make xxx_defconfig” 对 uboot 进行配置,配置完成以后就会在 uboot 根目录下生成.config。默认情况下.config 和xxx_defconfig 内容是一样的,因为.config 就是从 xxx_defconfig 复制过来的。如果后续自行调整了 uboot 的一些配置参数,那么这些新的配置参数就添加到了.config 中,而不是 xxx_defconfig。相当于 xxx_defconfig 只是一些初始配置,而.config 里面的才是实时有效的配置。

# SHELL used by kbuild 设定kbuild使用的Shell
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
	  else if [ -x /bin/bash ]; then echo /bin/bash; \
	  else echo sh; fi ; fi)
#使用make的shell函数来执行shell程序!!!!shell函数也不像其它的函数,它的参数应该就是操作系统Shell的命令。它和反引号“`”是相同的功能。这就是说,shell函数把执行操作系统命令后的输出作为函数返回。于是,我们可以用操作系统命令以及字符串处理命令awk,sed等等命令来生成一个变量,如:contents := $(shell cat foo)# if [-x]判断文件/程序存在且是可执行。貌似是shell变量用两个$。make的变量用一个。注意这里有两个fi。
#BASH为shell的内部变量,在make中使用双$$来引用shell中的变量
#在Makefile中的规则命令行中:$var:将Makefile中的变量var的值,传给shell命令。
#$$var:访问shell命令中定义的变量var。
#if语句直接就echo了,返回值是什么呢?给这个变量什么呢??应该就是echo什么就给他什么。

HOSTCC       = cc
HOSTCXX      = c++
HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \
		$(if $(CONFIG_TOOLS_DEBUG),-g)
HOSTCXXFLAGS = -O2

ifeq ($(HOSTOS),cygwin)
HOSTCFLAGS	+= -ansi
endif

# Mac OS X / Darwin's C preprocessor is Apple specific.  It
# generates numerous errors and warnings.  We want to bypass it
# and use GNU C's cpp.	To do this we pass the -traditional-cpp
# option to the compiler.  Note that the -traditional-cpp flag
# DOES NOT have the same semantics as GNU C's flag, all it does
# is invoke the GNU preprocessor in stock ANSI/ISO C fashion.
#
# Apple's linker is similar, thanks to the new 2 stage linking
# multiple symbol definitions are treated as errors, hence the
# -multiply_defined suppress option to turn off this error.
#
ifeq ($(HOSTOS),darwin)
# get major and minor product version (e.g. '10' and '6' for Snow Leopard)
DARWIN_MAJOR_VERSION	= $(shell sw_vers -productVersion | cut -f 1 -d '.')
DARWIN_MINOR_VERSION	= $(shell sw_vers -productVersion | cut -f 2 -d '.')

os_x_before	= $(shell if [ $(DARWIN_MAJOR_VERSION) -le $(1) -a \
	$(DARWIN_MINOR_VERSION) -le $(2) ] ; then echo "$(3)"; else echo "$(4)"; fi ;)

# Snow Leopards build environment has no longer restrictions as described above
HOSTCC       = $(call os_x_before, 10, 5, "cc", "gcc")
HOSTCFLAGS  += $(call os_x_before, 10, 4, "-traditional-cpp")
HOSTLDFLAGS += $(call os_x_before, 10, 5, "-multiply_defined suppress")

# since Lion (10.7) ASLR is on by default, but we use linker generated lists
# in some host tools which is a problem then ... so disable ASLR for these
# tools
HOSTLDFLAGS += $(call os_x_before, 10, 7, "", "-Xlinker -no_pie")
endif

# Decide whether to build built-in, modular, or both.
#决定是否编译为内置对象、模块、或者两者同时编译,通常编译为内置对象
# Normally, just do built-in.

KBUILD_MODULES :=
KBUILD_BUILTIN := 1	# 编译built-in

# If we have only "make modules", don't compile built-in objects.
# When we're building modules with modversions, we need to consider
# the built-in objects during the descend as well, in order to
# make sure the checksums are up to date before we record them.

ifeq ($(MAKECMDGOALS),modules)
  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
endif

# If we have "make <whatever> modules", compile modules
# in addition to whatever we do anyway.
# Just "make" or "make all" shall build modules as well

# U-Boot does not need modules!!!!!!!!
#ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
#  KBUILD_MODULES := 1
#endif
#如果make的终极目标列表中有all、_all、modules中任何一个,变量KBUILD_MODULES赋值为1

#ifeq ($(MAKECMDGOALS),)  如果make终极目标列表变量MAKECMDGOALS为空
#  KBUILD_MODULES := 1
#endif

export KBUILD_MODULES KBUILD_BUILTIN
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD

# We need some generic definitions (do not try to remake the file).
scripts/Kbuild.include: ;  #为什么要这句呢????上面说了
include scripts/Kbuild.include
#include”指示符告诉 make 暂停读取当前的 Makefile,而转去读取“ include”指定的一个或者多个文件,完成以后再继续当前 Makefile 的读取。
#文件 scripts/Kbuild.include,此文件里面定义了很多变量。459行附近$(build)就是这里面的变量
#在 uboot 的编译过程中会用到 scripts/Kbuild.include 中的这些变量

# Make variables (CC, etc...)

AS		= $(CROSS_COMPILE)as
# Always use GNU ld
ifneq ($(shell $(CROSS_COMPILE)ld.bfd -v 2> /dev/null),)
LD		= $(CROSS_COMPILE)ld.bfd
else
LD		= $(CROSS_COMPILE)ld
endif
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm
LDR		= $(CROSS_COMPILE)ldr
STRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump
AWK		= awk
PERL		= perl
PYTHON		= python
DTC		= dtc
CHECK		= sparse

CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
		  -Wbitwise -Wno-return-void -D__CHECK_ENDIAN__ $(CF)

#定义 KBuild 编译参数
KBUILD_CPPFLAGS := -D__KERNEL__ -D__UBOOT__

KBUILD_CFLAGS   := -Wall -Wstrict-prototypes \
		   -Wno-format-security \
		   -fno-builtin -ffreestanding
KBUILD_AFLAGS   := -D__ASSEMBLY__

# Read UBOOTRELEASE from include/config/uboot.release (if it exists)
UBOOTRELEASE = $(shell cat include/config/uboot.release 2> /dev/null)
UBOOTVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
#$(if CONDITION,THEN-PART[,ELSE-PART])如果“CONDITION”的展开结果非空,则条件为真,就将第二个参数“THEN_PATR”作为函数的计算表达式

export VERSION PATCHLEVEL SUBLEVEL UBOOTRELEASE UBOOTVERSION
export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR
#这 7 个变量在顶层 Makefile 是找不到的,来自uboot 根目录下有个文件叫做 config.mk
#其中原材料来自顶层的.config文件。
# 最终ARCH = arm
# CPU = armv7
# BOARD = mx6ullevk
# VENDOR = freescale
# SOC = mx6
# CPUDIR = arch/arm/cpu/armv7
# BOARDDIR = freescale/mx6ullevk
export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM LDR STRIP OBJCOPY OBJDUMP
export MAKE AWK PERL PYTHON
export HOSTCXX HOSTCXXFLAGS CHECK CHECKFLAGS DTC DTC_FLAGS

export KBUILD_CPPFLAGS NOSTDINC_FLAGS UBOOTINCLUDE OBJCOPYFLAGS LDFLAGS
export KBUILD_CFLAGS KBUILD_AFLAGS

# 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
#由于内核树或许是只读的,因此在编译内核树外的模块的时候,需要为这些编译的模块指定存储的目录,变量MODVERDIR 就是模块存储目录,如果KBUILD_EXTMOD为空则默认目录为.tmp_versions。

# Files to ignore in find ... statements

export 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/
#下面make ***_defcongfig的依赖就有这个,伪目标,一定执行命令。
PHONY += scripts_basic
#进入scripts/basic目录可以看到有Docproc.c和Fixdep.c两个文件,这里生成基本的scripts配置工具fixdep docproc
scripts_basic:
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount
# Q = @,MAKE = make环境变量,build 变量的定义在 scripts/Kbuild.include 文件中,上面已经包含了。
#build := -f $(srctree)/scripts/Makefile.build obj  = -f ./scripts/Makefile.build obj
#展开即为:make -f ./scripts/Makefile.build obj=scripts/basic(-f执行非makefile命名的makefile.)
#根据传入的 obj 参数显示的执行 ./scripts/Makefile.build 文件
#make 解析执行scripts/Makefile.build文件,且参数obj= scripts/basic。而在解析执行scripts/Makefile.build文件的时候,scripts/Makefile.build又会通过解析传入参数来包含对应文件夹下的Makefile文件(scripts/basic/Makefile),从中获得需要编译的目标。


# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;

#下面make ***_defcongfig的依赖就有这个,伪目标,一定执行命令。
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 ($
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值