Makefile 语法分析 第三部分
# 条件关键词ifeq判断变量mixed-targets的值与1是否相同,即是否为1
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.
else
ifeq ($(config-targets),1)
# 如果变量mixed-targets的值与1不相同,则执行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/$(ARCH)/Makefile
export KBUILD_DEFCONFIG
# 如果变量config-targets的值与1相同,则执行从第一行开始直到遇到下面的else结束。
# 关键词include将文件$(srctree)/arch/$(ARCH)/Makefile包含进来,
# 文件$(srctree)/arch/$(ARCH)/Makefile被原模原样的放在当前文件的包含位置。
# 关键词export声明变量KBUILD_DEFCONFIG使得变量KBUILD_DEFCONFIG能传到下级Makefile中。
config %config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
# 定义了一个规则,目标位config %config其中有个通配符%。
# 通配符%只能代表一个字符,config %config可以表示xconfig和gconfig、menuconfig和oldconfig等。
# 二三行将变量展开后就规则得到要执行的命令。
else
# 如果变量config-targets的值与1不相同,则执行下面的
# ===========================================================================
# Build targets only - this includes vmlinux, arch specific targets, clean
# targets and others. In general all targets except *config targets.
ifeq ($(KBUILD_EXTMOD),)
# 条件关键词ifeq判断变量KBUILD_EXTMOD的值与空是否相同。
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
# in parallel
PHONY += scripts
scripts: scripts_basic include/config/auto.conf
$(Q)$(MAKE) $(build)=$(@)
# 第一行给变量PHONY追加scripts。
# 定义了一个规则。目标是scripts,依赖文件是scripts_basic include/config/auto.conf
# 将第三行的所有命令展开就得到规则的命令。
# Objects we will link into vmlinux / subdirs we need to visit
init-y := init/
drivers-y := drivers/ sound/
net-y := net/
libs-y := lib/
core-y := usr/
endif # KBUILD_EXTMOD
# 为变量赋值。
# 上面的endif与ifeq ($(KBUILD_EXTMOD),)相对应。
ifeq ($(dot-config),1)
# Read in config
-include include/config/auto.conf
# 条件关键词ifeq判断变量dot-config的值与1是否相同,如果相同这执行上面这一条。
# 关键词include将文件include/config/auto.conf包含进来,该文件会原模原样的放在当前文件的包含位置。
# 关键词include前面的减号的作用是让make不理那些无法读取的文件,而继续执行。
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
# 条件关键词ifeq判断变量KBUILD_EXTMOD的值与0是否相同,如果相同这执行上面这一条。
# 关键词include将文件include/config/auto.conf.cmd包含进来,该文件会原模原样的放在当前文件的包含位置。
# 关键词include前面的减号的作用是让make不理那些无法读取的文件,而继续执行。
# To avoid any implicit rule to kick in, define an empty command
$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
# 定义了一个规则,目标是$(KCONFIG_CONFIG) include/config/auto.conf.cmd,没有依赖文件,命令。
# If .config is newer than include/config/auto.conf, someone tinkered
# with it and forgot to run make oldconfig.
# if auto.conf.cmd is missing then we are probably in a cleaned tree so
# we execute the config step to be sure to catch updated Kconfig files
include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
else
# 第一二行定义了一个规则。
# 目标是include/config/auto.conf,依赖文件是$(KCONFIG_CONFIG) include/config/auto.conf.cmd
# 将第二行的变量展开就得到命令。
# 上面的else与ifeq ($(KBUILD_EXTMOD),)对应
# 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
# 为变量PHONY追加值include/config/auto.conf
include/config/auto.conf:
# 定义了一个伪目标
$(Q)test -e include/linux/autoconf.h -a -e $@ || ( \
echo; \
echo " ERROR: Kernel configuration is invalid."; \
echo " include/linux/autoconf.h or $@ are missing."; \
echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \
echo; \
/bin/false)
# 自动变量$@表示当前规则的目标变量名。
# echo是shell中的显示命令,显示echo后面的字符串。
endif # KBUILD_EXTMOD
# 上面的endif与ifeq ($(KBUILD_EXTMOD),)对应。
else
# Dummy target needed, because used as prerequisite
include/config/auto.conf: ;
endif # $(dot-config)
# 定义了一个伪目标include/config/auto.conf,该规则没有依赖文件和命令。
# 上面的endif与ifeq ($(dot-config),1)对应。
# 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
# 定义了一个依赖关系,目标是all,依赖文件是vmlinux。
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
CFLAGS += -Os
else
CFLAGS += -O2
endif
# 条件关键字ifdef只检验变量CONFIG_CC_OPTIMIZE_FOR_SIZE是否被赋值(非空)。
# 分别在两种情况下为变量CFLAGS追加不同的值。
include $(srctree)/arch/$(ARCH)/Makefile
# 用关键字声明文件$(srctree)/arch/$(ARCH)/Makefile,使得该文件能传递到下级Makefile
ifdef CONFIG_FRAME_POINTER
CFLAGS += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
else
CFLAGS += -fomit-frame-pointer
endif
# 条件关键字ifdef只检验变量CONFIG_FRAME_POINTER是否被赋值(非空)。
# 分别在两种情况下为变量CFLAGS追加不同的值。
ifdef CONFIG_DEBUG_INFO
CFLAGS += -g
endif
# 条件关键字ifdef只检验变量CONFIG_DEBUG_INFO是否被赋值(非空)。
# 为变量CFLAGS追加-g
# Force gcc to behave correct even for buggy distributions
CFLAGS += $(call cc-option, -fno-stack-protector)
# 为变量CFLAGS追加$(call cc-option, -fno-stack-protector)。
# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
# 分别为变量追加值
# 函数shell新生成一个Shell程序来执行由变量CC展开后形成的命令。
# warn about C99 declaration after statement
CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
# 为变量CFLAGS追加call函数返回的函数call的返回值。
# 函数call的语法:$(call <expression>;,<parm1>;,<parm2>;,<parm3>;...)。
# 函数call的功能是:参数cc-option中的变量被字符串-Wdeclaration-after-statement和逗号后面的空格依次取代。
# 函数call的返回值是:被取代后的参数。
# disable pointer signed / unsigned warnings in gcc 4.0
CFLAGS += $(call cc-option,-Wno-pointer-sign,)
# 为变量CFLAGS追加call函数返回的函数call的返回值。
# 函数call的语法:$(call <expression>;,<parm1>;,<parm2>;,<parm3>;...)。
# # 函数call的功能是:参数cc-option中的变量被字符串-Wno-pointer-sign和逗号后面的空格依次取代。
# 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
# 用关键字声明了变量KBUILD_IMAGE,使得该变量能传递到下级Makefile中。
# 符号“?=”在变量KBUILD_IMAGE没有赋值的情况下给变量KBUILD_IMAGE赋值,如果已经赋值了则什么也不做。
#
# INSTALL_PATH specifies where to place the updated kernel and system map
# images. Default is /boot, but you can set it to other values
export INSTALL_PATH ?= /boot
# 用关键字声明了变量INSTALL_PATH,使得该变量能传递到下级Makefile中。
# 符号“?=”在变量INSTALL_PATH没有赋值的情况下给变量INSTALL_PATH赋值,如果已经赋值了则什么也不做。
#
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
# relocations required by build roots. This is not defined in the
# makefile but the argument can be passed to make if needed.
#
MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
# 给变量MODLIB赋值
# 用关键字声明变量MODLIB使得变量能够传到下级Makefile
#
# INSTALL_MOD_STRIP, if defined, will cause modules to be
# stripped after they are installed. If INSTALL_MOD_STRIP is '1', then
# the default option --strip-debug will be used. Otherwise,
# INSTALL_MOD_STRIP will used as the options to the strip command.
ifdef INSTALL_MOD_STRIP
ifeq ($(INSTALL_MOD_STRIP),1)
mod_strip_cmd = $(STRIP) --strip-debug
else # 这个else与ifeq ($(INSTALL_MOD_STRIP),1)对应。
mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
endif # INSTALL_MOD_STRIP=1
else # 这个else与ifdef INSTALL_MOD_STRIP对应。
mod_strip_cmd = true
endif # INSTALL_MOD_STRIP
export mod_strip_cmd
# 条件关键字ifdef判断变量INSTALL_MOD_STRIP是否被赋值,
# 条件关键字ifeq判断变量INSTALL_MOD_STRIP与1是否相同。
# 如果相同或被赋值则执行紧接着的命令,否则执行同一级的else后的命令。
# 上面命令就是在不同情况下给变量mod_strip_cmd赋值。