Linux内核源代码顶层目录下的Makefile文件分析二

来源:互联网 发布:网络报警qq 编辑:程序博客网 时间:2024/06/05 10:52
# 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 arch/* for the possibilities).
# ARCH can be set during invocation of make:
# make ARCH=ia64
# Another way is to have ARCH set in the environment.
# The default ARCH is the host where make is executed.

# CROSS_COMPILE specify the prefix used for all executables used
# during compilation. Only gcc and related bin-utils executables
# are prefixed with $(CROSS_COMPILE).
# CROSS_COMPILE can be set on the command line
# make CROSS_COMPILE=ia64-linux-
# Alternatively CROSS_COMPILE can be set in the environment.
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
# 上面已经说了,下面的这些是用于交叉编译(嵌入式linux的编译环境就是交叉编译)。
# 如果你不清楚嵌入式linux是什么,但是你又想知道它,记住:
www.baidu.com

ARCH   ?= $(SUBARCH)
CROSS_COMPILE ?=
# 变量ARCH用来指明目标cpu的构架
# 设置变量ARCH的方法有两种,
# 一是:在命令行中 如:make ARCH=ia64;
# 二是:设置环境变量,在环境变量中默认的ARCH的值是执行make的cpu构架
# 不论怎么弄,目的就是使编译出来的目标文件(可执行文件)面向的是你的目标平台(在嵌入式开发中)。
#
# 操作符“?= ”的作用是:如果ARCH未被定义过,那么将变量SUBARCH的值赋给变量ARCH,
# 如果变量ARCH已经被定义过,那么这条语句什么也不做。
#
# ARCH指定在嵌入式开发中你的目标板上的cpu类型(构架),如:arm,ppc,powerpc等
# 变量CROSS_COMPILE指定交叉编译用的交叉编译器,这里的CROSS_COMPILE就是让你指定交叉编译器的路径。
# 如果你设置好了PATH那么直接把这句加上就可以,如果没有那么请指定路径,

# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
# 将变量ARCH直接展开给变量UTS_MACHINE。

KCONFIG_CONFIG ?= .config
# 在变量KCONFIG_CONFIG没赋值的情况下,将.config赋给变量KCONFIG_CONFIG;如果已经赋值,那么什么也不做。

# SHELL used by kbuild
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
   else if [ -x /bin/bash ]; then echo /bin/bash; \
   else echo sh; fi ; fi)
# 将生成shell程序来执行if函数后返回的结果展开给变量CONFIG_SHELL;
# if函数中,在else中又嵌套了if函数。

HOSTCC       = gcc
HOSTCXX      = g++
HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTCXXFLAGS = -O2
# 分别为变量HOSTCC 、HOSTCXX 、HOSTCFLAGS 、HOSTCXXFLAGS赋值。

# Decide whether to build built-in, modular, or both.
# Normally, just do built-in.

KBUILD_MODULES :=
KBUILD_BUILTIN := 1
# 分别为变量KBUILD_MODULES、KBUILD_BUILTIN 赋值。

# 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
# ifeq判断变量MAKECMDGOALS的值与modules是否相同;
# 第二行将调用if后返回的值展开给变量KBUILD_BUILTIN;
# if函数判断变量CONFIG_MODVERSIONS的值是否为非空字符串,如果是非空字符串,则执行逗号后面的1
# 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

ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
KBUILD_MODULES := 1
endif
# ifneq判断调用函数filter的返回值与空字符串是否相同。
# 如果相同,那么执行第二行,即把1赋给变量 KBUILD_MODULES

ifeq ($(MAKECMDGOALS),)
KBUILD_MODULES := 1
endif
# ifeq判断变量MAKECMDGOALS的值是否与空字符相同。如果相同,则执行第二行;
# 第二行是把1赋给变量KBUILD_MODULES。
export KBUILD_MODULES KBUILD_BUILTIN
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
# 用关键词export声明变量KBUILD_MODULES KBUILD_BUILTIN、KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD。
# 如果用关键词export声明了变量,那么被声明的变量将会被传递到下级Makefile中。

# Beautify output
# ---------------------------------------------------------------------------
#
# Normally, we echo the whole command before executing it. By making
# that echo $($(quiet)$(cmd)), we now have the possibility to set
# $(quiet) to choose other forms of output instead, e.g.
#
#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
#
# If $(quiet) is empty, the whole command will be printed.
# If it is set to "quiet_", only the short version will be printed.
# 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.

ifeq ($(KBUILD_VERBOSE),1)
quiet =
Q =
else
quiet=quiet_
Q = @
endif
# 函数ifeq判断变量KBUILD_VERBOSE的值与1是否相同。如果相同则执行第二三行,否则执行五六行。
# 二三五六行都是为变量赋值。

# If the user is running make -s (silent mode), suppress echoing of
# commands

ifneq ($(findstring s,$(MAKEFLAGS)),)
quiet=silent_
endif
# 函数ifneq判断函数findstring返回值与空字符是否相同,如果相同则执行第二行(将silent_赋给变量quiet)。
# 函数findstring的语法是:$(findstring <find>;,<in>;)
# 函数findstring的功能是:如果在$(MAKEFLAGS)中能找到字符s,那么返回字符s;否则返回空字符。

export quiet Q KBUILD_VERBOSE
# 用关键词export声明变量quiet Q KBUILD_VERBOSE,使得它们能被传到下级Makefile。

# Look for make include files relative to root of kernel src
MAKEFLAGS += --include-dir=$(srctree)
# 给变量MAKEFLAGS追加--include-dir=$(srctree)。
# --include-dir是make的参数,用来指定一个被包含makefile的搜索目标。
# 也可以使用多个“-I”参数来指定多个目录。

# We need some generic definitions.
include $(srctree)/scripts/Kbuild.include
# 在Makefile使用include关键字可以把别的Makefile包含进来。
# 这很像C语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。
# include的语法是: include <filename>;

# 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 = -r
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
# 为变量LINUXINCLUDE赋值。

CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)

CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                   -fno-strict-aliasing -fno-common
AFLAGS          := -D__ASSEMBLY__
# 给FLAGS系列变量赋值。

# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELRELEASE = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
# 给变量KERNELRELEASE、KERNELRELEASE赋值。
# >是重定向符号。
# 第一行中cat和>连用的作用是:将文件include/config/kernel.release的内容写入到文件/dev/null中。

export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH 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 CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
# 用关键词export声明变量,使得这些变量能传到下级Makefile中

# 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
# 用关键词export声明变量MODVERDIR,使得变量MODVERDIR能传到下级Makefile中
# 将if函数的返回值展开后与.tmp_versions共同赋给变量MODVERDIR。
# if函数判断变量KBUILD_EXTMOD的值是否为空字符串,如果不为空字符串,执行函数firstword。
# 函数firstword的语法是:$(firstword <text>;)。
# 函数firstword在此处的功能是:取出变量KBUILD_EXTMOD的第一个字符。

# 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
# 分别为变量RCS_FIND_IGNORE、RCS_FIND_IGNORE赋值。
# 第二行中用关键词export声明变量RCS_TAR_IGNORE,使它能够传递到下级Makefile中。
# 反斜杠\在第一行中只有转义的作用,不表示续行。
# 即\后面的“(”和“)”都不表示前括号和后括号,而是两个字符。
# -name是命令find的一个参数,参数-name用来指明要搜索的文件的部分或者全名。
# -o 是 OR 运算符,语法是:表达式-o 表达式、如果第一个表达式是真,就不会对第二个表达式求值。

# ===========================================================================
# Rules shared between *config targets and build targets

# Basic helpers built in scripts/
PHONY += scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
# 为变量PHONY追加scripts_basic。
# 定义了一个伪目标scripts_basic,第三行是针对伪目标scripts_basic要执行的命令。
# 第三行是将变量展开,展开后是一个命令。

# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;
# 定义了一个规则,依赖关系为scripts/basic/%: scripts_basic
# 冒号:的作用是定义一个空命令(正如上面解释所说)。

PHONY += outputmakefile
# 为变量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),)
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
     $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
# 定义一个伪目标outputmakefile。
# 将三四行中所有的变量展开并且合并成一行命令。

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

no-dot-config-targets := clean mrproper distclean \
    cscope TAGS tags help %docs check% \
    include/linux/version.h headers_% \
    kernelrelease kernelversion
# 定义了一个依赖关系,但是没有命令。

config-targets := 0
mixed-targets := 0
dot-config     := 1
# 给变量config-targets、mixed-targets、dot-config 赋值。


ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
   dot-config := 0
endif
endif
# 条件关键词ifneq判断filter函数的返回值与变量MAKECMDGOALS是否相同,如果相同,则执行第二行。
# 第二行,条件关键词ifeq判断函数filter-out返回值与变量MAKECMDGOALS是否相同,如果相同则执行第三行。
# 函数filter的语法是:$(filter <pattern...>;,<text>;)。
# 功能是:返回 $(MAKECMDGOALS)中符合模式$(no-dot-config-targets)的字符串
# 函数filter-out与函数filter在语法是相似,在功能上恰好相反。
# 函数filter-out返回字符串$(MAKECMDGOALS)中不符合模式$(no-dot-config-targets)的字符串。
# 第三行是给变量dot-config赋值0.


ifeq ($(KBUILD_EXTMOD),)
        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
                config-targets := 1
                ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
                        mixed-targets := 1
                endif
        endif
endif
# 条件关键词ifeq判断KBUILD_EXTMOD的值与空格是否相同,如果是则执行第二行。
# 条件关键词ifneq判断函数filter的返回值与空格是否不相同,如果不相同,则执行第三行。
# 函数filter返回字符串$(MAKECMDGOALS))中符合模式config %config的字符串。
# 第三行为变量config-targets赋值1
# 条件关键词ifneq判断函数filter-out返回值与空格是否不相同,如果不过不相同则执行第五行。
# 函数filter-out返回字符串$(MAKECMDGOALS)中不符合模式config %config的字符串。
# 第五行为变量mixed-targets赋值1.


ifeq ($(mixed-targets),1)
# 条件关键词ifeq判断变量mixed-targets的值与1是否相同,即是否为1
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.

%:: FORCE
$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@
# 定义了目标“%:”,依赖文件FORCE
# 第二行,将所有变量展开后组成一行命令。

原创粉丝点击