Linux Makefile分析-vmlinux生成
2011-05-25 15:47
239 查看
1, 顶层Makefile跟踪:
找到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
@echo
"========================vmlinux============================"
@echo
$(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o)
@cp
vmlinux vmlinux.full
找到vmlinux-init:
vmlinux-init := $(head-y) $(init-y)
head-y是和机器有关的变量,定义在arch内的Makefile里:
head-y := arch/mips/kernel/head.o
arch/mips/kernel/init_task.o
这个是通过include $(srctree)/arch/$(SRCARCH)/Makefile 包含这个Makefile的。
init-y定义在本Makefile:
init-y := init/
...
init-y := $(patsubst %/, %/built-in.o,
$(init-y))
最终结果就是:
init-y := init/built-in.o。这个build-in.o这个中间文件可能听说过,其实这个文件就是有这个目录下所有obj-y来合成的。
此外,下面两变量自己找一下:
vmlinux-main := $(core-y) $(libs-y)
$(drivers-y) $(net-y)
vmlinux-lds
:= arch/$(ARCH)/kernel/vmlinux.lds
vmlinux-dirs
还要注意一下,下面这句:
$(sort $(vmlinux-init) $(vmlinux-main))
$(vmlinux-lds): $(vmlinux-dirs) ;
这句在执行vmlinux目标前由依赖关系产生,我们来看看最关键的vmlinux-dirs。
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-dirs)还是一个目标。
PHONY += $(vmlinux-dirs)
$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
用到了Makefile.kbuild规则。将vmlinux-dirs里面的目录进行了递归处理产生出那些.o的文件,特别是build-in.o, 在执行vmlinux时候,$(vmlinux-dirs)目标肯定会先得到执行。
链接得到vmlinux
在哪里链接的,看看 endif后面:
$(call
if_changed_rule,vmlinux__)
$(Q)$(MAKE)
-f $(srctree)/scripts/Makefile.modpost $@
$(call if_changed_rule,vmlinux__)会调用rule_vmlinux_,即下面内容:
# Link of vmlinux
# If CONFIG_KALLSYMS is set .version is
already updated
# Generate System.map and verify that the
content is consistent
# Use + in front of the vmlinux_version
rule to silent warning with make -j2
# First command is ':' to allow us to use +
in front of the rule
define rule_vmlinux__
:
$(if
$(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
$(call
cmd,vmlinux__)
$(Q)echo
'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
$(Q)$(if
$($(quiet)cmd_sysmap), \
echo '
$($(quiet)cmd_sysmap) System.map'
&&) \
$(cmd_sysmap)
$@ System.map; \
if
[ $$? -ne 0 ]; then \
rm
-f $@;
\
/bin/false;
\
fi;
$(verify_kallsyms)
endef
在这上面有命令vmlinux__, _vmlinux_version和sysmap定义, 其中vmlinux_命令中有LD的链接生成vmlinux.
# Rule to link vmlinux - also used during
CONFIG_KALLSYMS
# May be overridden by
arch/$(ARCH)/Makefile
quiet_cmd_vmlinux__ ?= LD $@
cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
-T $(vmlinux-lds) $(vmlinux-init) \
--start-group $(vmlinux-main) --end-group \
$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
# Generate new vmlinux version
quiet_cmd_vmlinux_version = GEN .version
cmd_vmlinux_version = set -e; \
if
[ ! -r .version ]; then \
rm -f .version; \
echo 1 >.version; \
else \
mv .version .old_version; \
expr 0$$(cat .old_version) + 1 >.version; \
fi; \
$(MAKE)
$(build)=init
# Generate System.map
quiet_cmd_sysmap = SYSMAP
cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
2. Makefile.kbuild规则:
$(Q)$(MAKE) -f $(if$(KBUILD_SRC),$(srctree)/)scripts/Makefile.build \
obj =$(vmlinux-dirs)
找到目标__build:
__build: $(if
$(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m)) \
$(subdir-ym) $(always)
@:
因为KBUILD_BUILTIN在顶层Makefile中被初始化为1,所以这个规则的依赖有一个builtin-target变量:
ifneq ($(strip $(obj-y) $(obj-m) $(obj-n)
$(obj-) $(lib-target)),)
builtin-target := $(obj)/built-in.o
endif
变量obj就是vmlinux-dirs变量指定的目录。所以这里会构建$(vmlinux-dirs)/built-in.o目标:
ifdef builtin-target
quiet_cmd_link_o_target = LD $@
# If the list of objects to link is empty,
just create an empty built-in.o
cmd_link_o_target = $(if $(strip
$(obj-y)),\
$(LD) $(ld_flags) -r -o $@
$(filter $(obj-y), $^),\
rm -f $@; $(AR) rcs $@)
上面由obj-y指定的.o,生成$(vmlinux-dirs)/built-in.o.
$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target)
下面包含了vmlinux-dirs变量指定目录中的Makefile文件,在这些makefile文件中会指定obj-y变量,它指定的都是一些*.o目标文件,
kbuild-dir := $(if $(filter
/%,$(src)),$(src),$(srctree)/$(src))
include $(if $(wildcard
$(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
这些*.o文件的生成方法由scripts/Makefile.build文件的模式规则指定
%.o: %.c FORCE
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
上面会生成obj-y指定的.o
通过上面这一系列的步骤,就编译链接出由变量vmlinux-init指定的目标,vmlinux-main变量指定的目标的构建与此类似.
相关文章推荐
- Linux Makefile分析-vmlinux生成
- Linux Makefile分析-vmlinux生成
- Linux Makefile分析-vmlinux生成
- linux下Makefile的automake生成全攻略
- linux下如何自动生成Makefile文件
- Linux下Makefile 的automake生成详解
- Linux 3.0内核Makefile分析
- 自动生成Linux下Makefile全攻略(下)
- Linux中autoconf和automake生成makefile脚本
- Linux驱动模块生成和加载分析
- Linux下Makefile的automake生成全攻略
- Linux下Makefile的automake生成全攻略
- linux源码Makefile的详细分析
- linux 生成的core文件名被截断问题分析
- linux下的静态库与动态库的区别,Gdb调试段错误,自动生成Makefile
- qmake生成的Makefile分析
- linux 模块 Makefile 分析
- [转贴]Linux下Makefile的automake生成全攻略[-]
- Linux下Makefile的automake生成全攻略
- linux中kconfig-kbuild-makefile分析