目录
Linux内核Makefile作用
Linux内核Makefile文件分类
Makefile解析
详细的解释可以看/Documentation/kbuild/makefiles.txt
子目录的Makefile
子目录的makefile形式简单,诸如下:
obj-$(CONFIG_DM9000) += dm9dev9000c.o
然后 CONFIG_DM9000
是在auto.conf
中定义,他是由.config
中定义为y(内核文件)或者m(编译为.ko模块),所以也就是形如
obj-y += xxx.o
obj-m += xxx.o
如果没有被定义则是
obj - +=xxx.o 不被处理
架构下面的Makefile
arch/arm/Makefile
我们执行命令make uImage并不在顶层的makefile,而是在架构下面的makefile,所以它一定会被顶层的makefile包含
zImage Image xipImage bootpImage uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
顶层Makefile
搜索下arch
,在顶层的Makefile中找到包含了架构下的Makefile
include $(srctree)/arch/$(ARCH)/Makefile
export KBUILD_DEFCONFIG
可以继续搜发现同时定义了arm架构,这是在补丁文件修改的
#ARCH ?= $(SUBARCH)
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
同时搜索下.config
文件生成的auto.conf
,也在顶层包含
ifeq ($(dot-config),1)
# Read in config
-include include/config/auto.conf
Make解析
总结:最终在各个目录下生成built-in.o
,根据arch/$(ARCH)/kernel/vmlinux.lds
的链接脚本链接
uiamge
依赖于vmlinux
,uImage实际就是头部信息加上一个真正的内核,也就是vmlinux
就是真正的内核
zImage Image xipImage bootpImage uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
可以发现在顶层makefile存在以下,也就是说这也是默认的目标文件
all: vmlinux
继续搜索目标vmlinux
的依赖
# vmlinux image - including updated kernel symbols
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
$(call if_changed_rule,vmlinux__)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
$(Q)rm -f .old_version
其中相关变量继续搜索如下
vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds
# vmlinux-lds:链接脚本。
# vmlinux-init:一些初始化代码。
# vmlinux-main:一些主要的代码(与内核核心相关的)。
vmlinux-init
#顶层 /makefile
init-y := init/
init-y := $(patsubst %/, %/built-in.o, $(init-y))
# 相当于 init-y = init/built-in.o
#架构 arch/arm/makefile
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
#这里MMUEXT 并没有被定义,也就是最终就是 arch/arm/kernel/head.o arch/arm/kernel/init_task.o
patsubst分析
格式:$(patsubst <pattern>,<replacement>,<text> )
名称:模式字符串替换函数——patsubst。
功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。
pattern=%/
在这里应该是匹配所有的意思replacement=%/built-in.o
text=init/
也就是说在init/
下的所有文件名都被替换为+built-in.o
,视频讲的是最后会被编译为built-in.o
,也就是相当于init-y = init/built-in.o
vmlinux-main
core-y 内核
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
# core-y
core-y := usr/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
core-y := $(patsubst %/, %/built-in.o, $(core-y))
这里也用到了patsubst
替换,也就是将上述目录下的文件编译为built-in.o
,最终相当于
core-y = usr/built-in.o
+= kernel/built-in.o
+= mm/built-in.o
+= fs/built-in.o
+= ipc/built-in.o
+= security/built-in.o
+= crypto/built-in.o
+= block/built-in.o
libs-y 库
libs-y := lib/
# 在lib/中查找 替换为lib.a
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
# 在lib/中查找 替换为built-in.o
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
# 最终生成 built-in.o 和 lib.a
libs-y := $(libs-y1) $(libs-y2)
同样的,也就是在最终生成built-in.o
和 替换为lib.a
drivers-y
驱动
drivers-y := drivers/ sound/ #(依赖了这两个目录)
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
同样的,也就是在最终生成built-in.o
net-y
网络
net-y := net/
net-y := $(patsubst %/, %/built-in.o, $(net-y))
同样的替换,生成built-in.o
总结
从以上分析makefile可以两大结果:第一个文件和链接脚本,以后分析内核流程可以根据第一个文件顺藤摸瓜一路跟踪下去,链接脚本决定了内核里的各个段是如何分布的,而每个段的文件顺序就是上面文件顺序。