linux kernel 4.18.16 Makefile注释

前言:

本人的操作系统作业,要求注释最新版本的GNU Linux kernel 的Makefile文件,我还没用过Linux,一打开这个Makefile真的是下了一跳……好多东西要注释啊,忙活了一个下午,成果就写个博客吧。

参考:

GNU Linux kernel下载地址
Kernel顶层Makefile文件分析
跟我一起写Makefile

Makefile:
# SPDX-License-Identifier: GPL-2.0
# SPDX-许可证-识别符:GPL-2.0
# 版本 = 4
# 修补版本号 = 18
# 次级版本号 = 15
# 附加信息,一般默认为空,可以自行设置
# 此版本的名字
VERSION = 4
PATCHLEVEL = 18
SUBLEVEL = 15
EXTRAVERSION =
NAME = Merciless Moray

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

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

# o Do not use make's built-in rules and variable
#   (this increases performance and avoids hard-to-debug behaviour);
# o Look for make include files relative to root of kernel src
# o 禁止使用内置的规则和变量
#	(这提高了性能并避免了难以调试的行为);
# o 查找与内核src有关的生成包含文件

MAKEFLAGS += -rR --include-dir=$(CURDIR)

# 非传递环境变量,不会传递到下一级Makefile
# Avoid funny character set dependencies
unexport LC_ALL
LC_COLLATE=C
LC_NUMERIC=C
export LC_COLLATE LC_NUMERIC

# 传递环境变量,环境变量会传递到下一级Makefile
# 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.a 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	//格式化的回显控制
# ---------------------------------------------------------------------------
#
# 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.	//$(quiet)=quiet_表示只有版本显示
# If it is set to "silent_", nothing will be printed at all, since	//表示完全不回显
# the variable $(silent_cmd_cc_o_c) doesn't exist.
#
# 下面是$(Q)用作前缀,如果$(Q)=@表示不回显,为空表示回显
# 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.
#
# 如果$(quiet)为空,则输出原版编译命令
# 如果$(quiet)为quiet_,则输出简化版本的
# 如果$(quiet)为silent_,则任何都不输出,因为slient_cmd_cc_o_cc根本不存在
# 不过有个全局的控制,如果KBUILD_VERBOSE为0,则输出简化版本,如果为1,则输出简化版本
#
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands

# 设置打印消息级别,通过调用 make 时添加的参数 V 来修改
ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
# 默认的KBUILD_VERBOSE的值被设置为0,也就意味着在编译过程中,只输出
# 默认我们是不回显的,回显即在命令执行前显示要执行的命令
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

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

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

ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),)
# 如果MAKEFLAGS中带了-s表示完全不要回显
  quiet=silent_
  tools_silent=s
endif

# 输出quiet给子make
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过程中的输出文件目的地址,有两种方式:
# 第一种是在 make 参数中设置(make -O dir")
# 第二种方式是设置环境变量(export KBUILD_OUTPU=dir)

# KBUILD_SRC is not intended to be used by the regular user (for now),
# it is set on invocation of make with KBUILD_OUTPUT or O= specified.
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?
# 如果命令行中定义了O变量来修改输出目录,就用用户定义的这个目录
ifeq ("$(origin O)", "command line")
  KBUILD_OUTPUT := $(O)
# 用于指定我们的输出文件的输出目录
endif

# Cancel implicit rules on top Makefile
# 取消隐式推导规则
$(CURDIR)/Makefile Makefile: ;
# CURDIR值为当前的内核源码目录current.dir
# 上面操作是查看当前目录的Makefile是否为最新

ifneq ($(words $(subst :, ,$(CURDIR))), 1)
  $(error main directory cannot contain spaces nor colons)
endif

# 如果输出目录值不为空,正常情况下进入
ifneq ($(KBUILD_OUTPUT),)
# check that the output directory actually exists
# 上面说在输出目录中执行第二个make命令,传入相关变量,并且检查输出目录是否存在
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
								&& pwd)
$(if $(KBUILD_OUTPUT),, \
     $(error failed to create output directory "$(saved-output)"))

# MAKECMDGOALS 是make的一个环境变量,保存所有目标列表
# 下面这个命令将所有指明的目标列表和sub-make加入到PHONY中
PHONY += $(MAKECMDGOALS) sub-make

# 下面这个命令很是不明白,大概是用来过滤,太复杂了
# 简单分析下,过滤掉MAKECMDGOALS中的_all sub-make和$(CURDIR)/Makefile,并将它们都赋值为sub-make
$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
	@:

# Invoke a second make in the output directory, passing relevant variables
# 这个就是sub-make的值,大致就是将顶层Makefile定义的规则传给下层文件夹中的Makefile中
sub-make:
	$(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \
	-f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS))

# Leave processing to above invocation of make
# 表示执行完了子makefile,返回顶层make
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),) #结束ifneq
endif # ifeq ($(KBUILD_SRC),) #结束ifeq

# We process the rest of the Makefile if this is the final invocation of make
# 表示如果skip-makefile为空,这按照分类执行,也就是不是整体进行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.	//调用一个静态分析工具作为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/dev-tools/sparse.rst" for more details,
# including where to get the "sparse" utility.

# 设置语法检查级别,默认级别为0
ifeq ("$(origin C)", "command line")
  KBUILD_CHECKSRC = $(C)
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
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
# 下面是为了支持旧语法格式的Makefile的设置
ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS)
endif

ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

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
endif

export KBUILD_CHECKSRC KBUILD_EXTMOD KBUILD_SRC

objtree		:= .
src		:= $(srctree)	# 将src设置为源码根目录
obj		:= $(objtree)	#将obj设定位当前目录

VPATH		:= $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))

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

# 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).
# 下面这里是保证调用make的时候输入了*config目标,这是就不能包含.config文件

version_h := include/generated/uapi/linux/version.h
old_version_h := include/linux/version.h

clean-targets := %clean mrproper cleandocs
no-dot-config-targets := $(clean-targets) \
			 cscope gtags TAGS tags help% %docs check% coccicheck \
			 $(version_h) headers_% archheaders archscripts \
			 kernelversion %src-pkg
no-sync-config-targets := $(no-dot-config-targets) install %install

config-targets  := 0
mixed-targets   := 0
dot-config      := 1
may-sync-config := 1

ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
		dot-config := 0
	endif
endif

ifneq ($(filter $(no-sync-config-targets), $(MAKECMDGOALS)),)
	ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),)
		may-sync-config := 0
	endif
endif

ifneq ($(KBUILD_EXTMOD),)
	may-sync-config := 0
endif

ifeq ($(KBUILD_EXTMOD),)
        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
                config-targets := 1
                ifneq ($(words $(MAKECMDGOALS)),1)
                        mixed-targets := 1
                endif
        endif
endif

# For "make -j clean all", "make -j mrproper defconfig all", etc.
ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),)
        ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),)
                mixed-targets := 1
        endif
endif

# install and modules_install need also be processed one by one
ifneq ($(filter install,$(MAKECMDGOALS)),)
        ifneq ($(filter modules_install,$(MAKECMDGOALS)),)
	        mixed-targets := 1
        endif
endif

ifeq ($(mixed-targets),1)
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.

PHONY += $(MAKECMDGOALS) __build_one_by_one

$(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one
	@:

__build_one_by_one:
	$(Q)set -e; \
	for i in $(MAKECMDGOALS); do \
		$(MAKE) -f $(srctree)/Makefile $$i; \
	done

else

# We need some generic definitions (do not try to remake the file).
# 这里是定义了一些通用的srctree变量定义,这里执行remake操作
scripts/Kbuild.include: ;
# 这里的文件包含了大量通用的函数和变量,已经为这个文件创建了笔记,抽个时间进行分析,
# 还是先对那个进行分析吧,因为下面会用到它定义的很多变量
include scripts/Kbuild.include

# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
# 设置版本号
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION

include scripts/subarch.include

# 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.
# 当执行交叉编译的时候,要将ARCH的值设置为目标的架构,支持的交媾可以在arch目录下看到
# ARCH可以在执行make命令时设置,如make ARCH=arm
# 默认的ARCH是和Host相同

# 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
# 下面是处理交叉编译这块的,交叉编译需要知道Host的架构和Target的架构吧
# CROSS_COMPILE是编译时所有命令的前缀,可以在执行make的时候指定如make CROSS_COMPILE=ia64-linux-
# CROSS_COMPILE也可以通过环境变量来设定
# 默认情况下是不需要CROSS_COMPILE来执行的,也就是不交叉编译
ARCH		?= $(SUBARCH)	# 默认Host的架构与Target架构相同

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

# 下面是对x86结构的特殊照顾,不明白原因
# Additional ARCH settings for x86
ifeq ($(ARCH),i386)
        SRCARCH := x86
endif
ifeq ($(ARCH),x86_64)
        SRCARCH := x86
endif

# Additional ARCH settings for sparc
ifeq ($(ARCH),sparc32)
       SRCARCH := sparc
endif
ifeq ($(ARCH),sparc64)
       SRCARCH := sparc
endif

# Additional ARCH settings for sh
ifeq ($(ARCH),sh64)
       SRCARCH := sh
endif

# 声称的配置文件名
KCONFIG_CONFIG	?= .config
export KCONFIG_CONFIG

# 设定kbuild使用的Shell
# 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)

HOST_LFS_CFLAGS := $(shell getconf LFS_CFLAGS 2>/dev/null)
HOST_LFS_LDFLAGS := $(shell getconf LFS_LDFLAGS 2>/dev/null)
HOST_LFS_LIBS := $(shell getconf LFS_LIBS 2>/dev/null)

# 设定编译器,和全局编译FLAGS
HOSTCC       = gcc
HOSTCXX      = g++
HOSTCFLAGS   := -Wall -
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值