Linux makefile分析

 

编译内核最后一行的信息:
arm-none-linux-gnueabi-ld -EL  -r -o vmlinux.o
arch/arm/kernel/head.o
arch/arm/kernel/init_task.o 
init/built-in.o
--start-group
usr/built-in.o 
arch/arm/kernel/built-in.o 
arch/arm/mm/built-in.o 
arch/arm/common/built-in.o 
arch/arm/mach-s5p6450/built-in.o 
arch/arm/plat-s5p/built-in.o 
arch/arm/plat-samsung/built-in.o 
arch/arm/nwfpe/built-in.o 
arch/arm/vfp/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 
arch/arm/lib/lib.a 
lib/lib.a 
arch/arm/lib/built-in.o 
lib/built-in.o 
drivers/built-in.o 
sound/built-in.o 
firmware/built-in.o 
net/built-in.o
--end-group
编译内核最后一行结束 ,上面好多行本来是一行,用回车隔开了

顶层Maiefile里面关建行

include $(srctree)/scripts/Kbuild.include   //定义变量 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
include $(srctree)/arch/$(SRCARCH)/Makefile //扩展变量core-y  定义变量head-y

head-y  := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o  //定义在arch/arm/makefile中 MMUEXT为空

init-y  := init/
drivers-y := drivers/ sound/ firmware/
net-y  := net/
libs-y  := lib/

core-y  := usr/

//定义在arch/arm/makefile中 CONFIG_*=y
machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
platdirs := $(patsubst %,arch/arm/plat-%/,$(plat-y))
core-y    += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y    += $(machdirs) $(platdirs)
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
core-$(CONFIG_VFP)  += arch/arm/vfp/

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))   //通过patsubst init-y=init/built-in.o
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)

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/$(SRCARCH)/kernel/vmlinux.lds

vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE

modpost-init := $(filter-out init/built-in.o, $(vmlinux-init))
vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE
 $(call if_changed_rule,vmlinux-modpost)  //也就是编译的最后一行信息,这一行没看懂
 
$(vmlinux-dirs): prepare scripts  //通过这一行递归各各子目录,生成子目录的built-in.o
 $(Q)$(MAKE) $(build)=$@
 
zImage Image xipImage bootpImage uImage: vmlinux  //arch/arm/makefile  boot=arch/arm/boot
 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE  //arch/arm/boot/makefile
 $(call if_changed,objcopy)
 @echo '  Kernel: $@ is ready'
分析编译信息:
make -n  | grep “make -f”

make -f scripts/Makefile.build obj=arch/arm/tools include/asm-arm/mach-types.h
make -f scripts/Makefile.build obj=scripts/basic
make -f scripts/Makefile.build obj=.
make -f scripts/Makefile.build obj=. missing-syscalls
make -f scripts/Makefile.build obj=scripts
make -f scripts/Makefile.build obj=scripts/mod
make -f scripts/Makefile.build obj=init
make -f scripts/Makefile.build obj=usr
make -f scripts/Makefile.build obj=arch/arm/kernel
make -f scripts/Makefile.build obj=arch/arm/mm
make -f scripts/Makefile.build obj=arch/arm/common
make -f scripts/Makefile.build obj=arch/arm/mach-s5p6450
.........................................

然后依次递归地调用源代码中的Makefile
由于scripts/Makefile.build后面没跟目标,所以默认为第一个目标:
.PHONY: __build
__build:
010 # Read .config if it exist, otherwise ignore
011 -include .config
013 include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile)
015 include scripts/Makefile.lib
这里可以看到,scripts/Makefile.build执行时会include .config文件。.config是make menuconfig后生成的内核配置文件。
里面有如下语句:
CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_ASUS=m
CONFIG_ACPI_IBM=m
.........
以前我一直对它的格式表示奇怪,现在很清楚了,它们是作为makefile的一部分,通过读取CONFIG_XXX的值就可以知道他们是作为模块还是作为内核
的一部分而编译的。此外,还包含了$(obj)/Makefile。这就是通过在make时传递目录名$(obj)间接调用Makefile的手法。对于内核普通代码所对应的
Makefile而言,里面只是对obj-m obj-y,-objs等变量进行赋值操作。接下去是include scripts/Makefile.lib。正如它的文件名所示,这类似于一个
库文件。它负责对obj-m obj-y,-objs等变量进行加工处理。从中提取出subdir-ym等变量,这是个很重要的变量,记录了需要递归调用的子目录。以
后递归调用Makefile全靠它了。这里也充分体现了GNU make对字符串进行操作的强大功能。回到Makefile.build。这时,重要变量$(builtin-target),
$(subdir-ym)等都已经计算完毕。开始列依赖关系和具体操作了。
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
         $(if $(KBUILD_MODULES),$(obj-m)) \
          $(subdir-ym) $(always)
         @:
$(builtin-target)是指当前目录下的目标文件,即$(obj)/built-in.o
如前文所说,$(subdir-ym)用来递归调用子目录的Makefile
# Descending
# ---------------------------------------------------------------------------
.PHONY: $(subdir-ym)
$(subdir-ym):
         $(Q)$(MAKE) $(build)=$@
通过这种方式,实现了对某个目录及其子目录的编译。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值