makefile解读 2

Makefile 对应内核版本:2.6.35.13

在构建混合目标(如 make defconfig all )时会将 mixed-targets 变量设置为 1 ,这样在顶层 Makefile 的 438 行的判断条件成立:

ifeq ($(mixed-targets),1)

从 438 行到 464 行的代码片段如下:

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

% :: 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

# 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/$(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 $@


从下面这段代码的注释可以知道:

引用
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.

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


这里构建的是混合目标,会一个个的进行处理。
上面使用了一个双冒号规则,在双冒号前面使用了 % 号,说明匹配任何一个目标,$(srctree) 变量表示内核源代码所在目录,而且 KBUILD_SRC= 定义为空。如果像上面执行 make defconfig all 命令时,deconfig 和 all 这两个目标会分别被处理成:

引用
$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= defconfig
$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= all


效果和在命令行中手动的敲入这两行命令是一样的。

如果我们不是在构建混合目标,那么 ifeq ($(mixed-targets),1) 判断不成立,那么代码会直接跳到 447 行 ifeq ($(config-targets),1) 判断是否是构建配置目标(就是 defconfig , menuconfig 一类目标)。若是,则执行 455-464 代码块。

从 448 - 454 行的注释可以了解到:
此处仅处理配置目标(*config) -- 确保所有的必要需求已经最新,然后会进入到 scripts/kconfig 目录下构建目标。

在 455 行这里将平台相关的 Makefile 文件包含进来,这里 $(SRCARCH) 是平台相关标志,由 $(ARCH) 变量来确定,如:

引用
ifeq ($(ARCH),x86_64)
        SRCARCH := x86
endif



由 458 和 462 行可以看到,config 和 *config 这类目标都有两个共同的依赖,它们分别是 scripts_basicoutputmakefile

scrpts_basic 依赖的实现代码见 383 到 393 行,代码如下:

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

# Basic helpers built in scripts/
PHONY += scripts_basic
scripts_basic:
     $( Q )$( MAKE) $( build) = scripts/basic
     $( Q) rm -f .tmp_quiet_recordmcount

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


最主要的是在 389 行 $(Q)$(MAKE) $(build)=scripts/basic ,以前有讨论过,$(Q)$(MAKE) $(build)= 是对一个目录进行编译,它会将 '=' 符号后面的内容作为参数传递到 script/Makefile.build 文件中,这里相当于执行 make -f scripts/Makefile.build obj=scripts/basic ,因为没有指定目标,所以在 script/Makefile.build 中会处理默认的目标 __build ,代码如下:

引用
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) /
         $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) /
         $(subdir-ym) $(always)
        @:


这里,如果是构建 builtin 这样的内核目标,那么需要实现 $(builtin-target),$(lib-target)  和 $(extra-y) 这些依赖,否则此处 if 函数返回为空;如果是构建模块,那么需要实现 $(obj-m) 和 $(modorder-target) 这两个依赖,否则 if 函数返回为空。

( 实际上,由于 393 行的 scripts/basic/%: scripts_basic ; 这条语句,它后面的一个分号提示依赖总是最新,从而需要去更新 scripts_basic,所以总是使得 388-390 这几条语句得到执行)

$(subdir-ym) 这个变量定义在 scripts/Makefile.lib 中,它是用来处理编译目录下各子目录的目标的一个变量,它的值由 Makefile.build 的第 44 行的 include $(kbuild-file) 所包含进来的要编译的子目录下的 Makefile 所传递,如在这些 Makefile 中的形如 obj-y=Z/ 或者 obj-m=Z/ 的内容,只要是以 / 结尾的都作为目录存放在 subdir-ym 这个变量中。

看一下 scripts/basic 目录下有什么:

引用
$ ls
docproc.c fixdep.c hash.c  Makefile


是几个 *.c 文件,还有一个 Makefile 文件,并没有子目录,再看一下 Makefile 内容:

引用
###
# Makefile.basic lists the most basic programs used during the build process.
# The programs listed herein are what are needed to do the basic stuff,
# such as fix file dependencies.
# This initial step is needed to avoid files to be recompiled
# when kernel configuration changes (which is what happens when
# .config is included by main Makefile.
# ---------------------------------------------------------------------------
# fixdep:      Used to generate dependency information during build process
# docproc:     Used in Documentation/DocBook

hostprogs-y     := fixdep docproc hash
always        : = $( hostprogs-y)

# fixdep is needed to compile other host programs
$( addprefix $( obj) /, $( filter-out fixdep, $( always))) : $( obj) /fixdep


这里的几个 *.c 文件将被编译成相应的可执行文件,它们分别是 fixdep, docproc 和 hash ,而 docproc 和 hash 的编译又依赖于 fixdep (最后一句指出)。

像上面的 fixdep , docproc 和 hash 这些程序被称为 host program 。host program 一般认为是和内核无关,但是要在编译过程中使用的工具。这些程序的编译,还需要 scripts/Makefile.host 的辅助,这在 Makefile.build 的第 61-64 行指出:

引用
# Do not include host rules unless needed
ifneq ($(hostprogs-y)$(hostprogs-m),)
include scripts/Makefile.host
endif


关于 host program 在Documentation/kbuild/makefile.txt 文件中也有阐述。

在 scripts/basic/Makefile 中,还看到了 $(always) 这个变量,它实际上就是 “fixdep docproc hash” 。

对于 $(subdir-ym) 这个变量,在 scripts/Makefile.build 中的 361-166 行里看到:

引用
# Descending
# ---------------------------------------------------------------------------

PHONY += $(subdir-ym)
$(subdir-ym):
    $(Q)$(MAKE) $(build)=$@



所以,它是一种递归式的编译要编译目录下的各个子目录。

最后的 @: 表示一个空语句,实际上就是说,只要实现上面了上面的依赖后,这个 __build 目标便可完成了。至于 @: 的含义可以参考:http://www.groad.net/bbs/read.php?tid-3403-fpage-2.html

对于 outputmakefile 实际上只有在执行 make 命令时指定了 O 选项(关于 O 选项可参考:http://www.groad.net/bbs/read.php?tid-3844.html)才有用,在顶层 Makefile 中的 396-404 行中可以看到它的注释及相关代码:

引用
# 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)ln -fsn $(srctree) source
    $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile /
        $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif


注释里总的意思是,outputmakefile 会在输出目录(O 选项指定的目录)里创建一个 Makefile 文件。因为如果指定了 O 选项,那么 $(KBUILD_SRC) 就不会为 0,所以会执行 ifneq-endif 块里的语句。在输出目录里创建的新的 Makefile 文件调用 scripts/mkmakefile 这个脚本文件来完成,$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) 这 4 个变量是传递到脚本文件中的 4 个参数。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值