Linux Makefile学习(二)

来源:互联网 发布:性价比 实木家具 知乎 编辑:程序博客网 时间:2024/04/30 08:53
# Use LINUXINCLUDE when you must reference the include/ directory.
# Needed to be compatible with the O= option


# 当你需要设计include/目录时,使用LINUXINCLUDE
# 需要配合O=选项一起使用
LINUXINCLUDE    := -Iinclude \
                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
                   -I$(srctree)/arch/$(hdr-arch)/include               \
                   -include include/linux/autoconf.h


KBUILD_CPPFLAGS := -D__KERNEL__


KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
  -fno-strict-aliasing -fno-common \
  -Werror-implicit-function-declaration \
  -Wno-format-security \
  -fno-delete-null-pointer-checks
KBUILD_AFLAGS   := -D__ASSEMBLY__


# Read KERNELRELEASE from include/config/kernel.release (if it exists)
# 从include/config/kernel.release中读取KERNELRELEASE变量(如果include/config/kernel.release存在)
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
export MAKE AWK GENKSYMS INSTALLKERNEL 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 CFLAGS_GCOV
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.


# 当编译目录树外的模块时,将MODVERDIR放在模块树下而非内核树下。内核树可能只是只读的。
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
# *config目标和build目标之间的共享规则。


# Basic helpers built in scripts/
# 在scripts目录下的基本辅助对象构建
PHONY += scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic//$(build)在scripts/Kbuild.include文件中定义。
//build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj


# 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在输出目录创建一个Makefile。这使在输出目录使用make很方便。
outputmakefile:
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree) source
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \//$(CONFIG_SHELL)上文定义过,获取本地shell
   $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)//会在$(objtree)目录下创建一个Makefile
//具体分析在mkmakefile文件讲解中
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).



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


ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)//过滤掉不符合$(no-dot-config-targets)
//模式的内容
ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)//过滤掉符合$(no-dot-config-targets)
//模式的内容
dot-config := 0
endif
endif


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


ifeq ($(mixed-targets),1)
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.
# 如果是混合目标,重新一个一个目标递归调用一次该Makefile。


%:: FORCE
$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@


else
ifeq ($(config-targets),1)
# ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend
# in scripts/kconfig to make the *config target
# 只有*config目标 - 确定依赖被更新后,进入scripts/kconfig中去构造*config目标。


# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'
# 读arch特定的Makefile去按照需要设置KBUILD_DEFCONFIG变量。KBUILD_DEFCONFIG可以在使用'make defconfig'
# 时指出一个备选的默认configuration。
include $(srctree)/arch/$(SRCARCH)/Makefile
export KBUILD_DEFCONFIG KBUILD_KCONFIG


config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@


%config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@

else
# ===========================================================================
# Build targets only - this includes vmlinux, arch specific targets, clean
# targets and others. In general all targets except *config targets.
# 只有构建目标 - 这包括vmlinux,和arch特定目标,clean目标和别的。通常除了*config目标都是构建目标。


ifeq ($(KBUILD_EXTMOD),)
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
# in parallel
# 额外的帮助内建在scripts/下
# 仔细列出依赖关系,以便我们不用尝试构建两次脚本。
PHONY += scripts
scripts: scripts_basic include/config/auto.conf
$(Q)$(MAKE) $(build)=$(@)


# Objects we will link into vmlinux / subdirs we need to visit
# 我们需要链接进vmlinux中的部分,也是我们需要访问的子目录。
init-y := init/
drivers-y := drivers/ sound/ firmware/
net-y := net/
libs-y := lib/
core-y := usr/
endif # KBUILD_EXTMOD


ifeq ($(dot-config),1) //符合no_dot_config_targets的集合不为空且不符合no_dot_config_targets集合为空
//时,dot-config-targets为0
# Read in config
-include include/config/auto.conf //后文中创建出来的


ifeq ($(KBUILD_EXTMOD),)
# Read in dependencies to all Kconfig* files, make sure to run
# oldconfig if changes are detected.
# 阅读所有Kconfig*文件的依赖关系,如果检测出变化,确保运行旧配置文件。
-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
# 如果.config比include/config/auto.conf文件新,某些人笨手笨脚,忘记执行make oldconfig。
# 如果在被清理的目录中,auto.conf.cmd文件丢失了,我们要执行配置步骤以确保获取更新后的Kconfig文件。
include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
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
# 外部模块需要include/linux/autoconf.h和include/config/auto.conf,但是不关心是否是最新的。使用auto.config
# 触发检测。
PHONY += include/config/auto.conf


include/config/auto.conf:
$(Q)test -e include/linux/autoconf.h -a -e $@ || (\ //-e表示检测文件是否存在,-a
//表示前后两个条件必须同时满足
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) //以错误码退出


endif # KBUILD_EXTMOD


else
# Dummy target needed, because used as prerequisite
# 需要一个假目标作为先决条件
include/config/auto.conf: ;
endif # $(dot-config)


# The all: target is the default when no target is given on the
# command line.
# 当没有在命令行给出明确目标,all是默认目标。
# 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
# 这允许用户只使用‘make’构建包含模块的内核。
# 默认是vmlinux但经常被arch下makefile重写。
all: vmlinux.


ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os//-Os相当于-O2.5。是使用了所有-O2的优化选项,但又不缩减代码尺寸的方法。
else
KBUILD_CFLAGS += -O2
endif


include $(srctree)/arch/$(SRCARCH)/Makefile


//cc-option检测给出的选项$(CC)是否支持,不支持则指定第二个可选参数为$(CC)选项。第二个参数是可选的,
//如果被省略且第一个参数不被支持,KBUILD_CFLAGS被设为空值
//call类似与shell中的函数调用,cc-option在Scripts/Kbuild.include文件中定义。
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
# 强制gcc有正确运行,甚至是对于缺陷分支。
ifndef CONFIG_CC_STACKPROTECTOR
KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
endif


ifdef CONFIG_FRAME_POINTER
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
else
KBUILD_CFLAGS += -fomit-frame-pointer
endif


ifdef CONFIG_DEBUG_INFO
KBUILD_CFLAGS += -g
KBUILD_AFLAGS += -gdwarf-2
endif


ifdef CONFIG_FUNCTION_TRACER
KBUILD_CFLAGS += -pg//产生供gprof剖析用的可执行文件
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
# arch下Makefile可能会重写CC变量,所以在arch Makefile被包含后保存下来。
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS     += $(NOSTDINC_FLAGS)
//-nostdinc 不在标准系统目录中搜索头文件,只在-I指定的目录中搜索
//-isystem
//$(shell $(CC) -print-file-name=include) 编译器的include路径


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


# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)


# revert to pre-gcc-4.4 behaviour of .eh_frame
KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)


# conserve stack if available
KBUILD_CFLAGS   += $(call cc-option,-fconserve-stack)
PS:很多选项不知道什么意思。


# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
# But warn user when we do so
# 添加用户提供的CPPFLAGS,AFLAGS和CFLAGS作为最后的部分。
# 但是当这样做时,提示用户。
warn-assign = \
$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")


ifneq ($(KCPPFLAGS),)
        $(call warn-assign,CPPFLAGS)
        KBUILD_CPPFLAGS += $(KCPPFLAGS)
endif
ifneq ($(KAFLAGS),)
        $(call warn-assign,AFLAGS)
        KBUILD_AFLAGS += $(KAFLAGS)
endif
ifneq ($(KCFLAGS),)
        $(call warn-assign,CFLAGS)
        KBUILD_CFLAGS += $(KCFLAGS)
endif


# Use --build-id when available.
# 可以的时候,使用--build-id选项。
//--build-id是链接器选项。
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
     $(call cc-ldoption, -Wl$(comma)--build-id,))
LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)
LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID)


ifeq ($(CONFIG_STRIP_ASM_SYMS),y)
LDFLAGS_vmlinux += $(call ld-option, -X,)
endif


# 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
# 当没有给出明确的目标时,默认创建内核镜像。
# 在命令行或者环境变量中设置的KBUILD_IMAGE可能会无效。
# arch/$(ARCH)/Makefile下任何任务的优先级都高于这个默认值。
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
#
# INSTALL_PATH指定更新的内核和system map镜像放置位置。默认是/boot,但你可以将它设置成别的值。
export INSTALL_PATH ?= /boot


#
# 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.
#
# INSTALL_MOD_PATH指定MODLIB的前缀,MODLIB是构建根目录请求的模块目录。这个值没有在makefile中定义,但
# 如果需要可以传递给它值。
#


MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB


#
#  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.
#
#  INSTALL_MOD_STRIP,如果被定义,将会在模块安装后被strip(PS:strip作用是除去绑定程序和符号调试程序
#  使用的信息)。如果INSTALL_MOD_STRIP是‘1’,默认选项--strip-debug 将被使用。否则,INSTALL_MOD_STRIP
#  将被用作strip命令的选项。


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 += kernel/ mm/ fs/ ipc/ security/ crypto/ block/


vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
    $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
    $(net-y) $(net-m) $(libs-y) $(libs-m)))


vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
    $(init-n) $(init-) \
    $(core-n) $(core-) $(drivers-n) $(drivers-) \
    $(net-n)  $(net-)  $(libs-n)    $(libs-))))


init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
0 0
原创粉丝点击