Linux Kernel Makefile解析(一)
来源:互联网 发布:南邮软件下载 编辑:程序博客网 时间:2024/05/11 19:45
闲置了这么久的博客,也要拾起来了(为自己的懒惰感到羞愧)。最近一段时间一直和linux的核心代码打交道,也积累了一些经验,现在想把自己对linux的理解写下来,也欢迎朋友指正。
我认为对linux代码的阅读首先要读懂她的Makefile,Makefile是代码的外部框架,熟悉她会让我们对Linux的代码层次有一定的了解,这对我们深读代码很有帮助。工作过程中接手一个新项目的维护工作时,我也会首先读她的Makefile,因为这在一定程序上代表了项目开发者的架构思路,这也是我要学习的地方。
好了,现在我们开始我们的代码之旅。。。
编译内核首先要执行make menuconfig,那我们就从这条命令开始。(P.S. 内核版本 3.8.0)
1. Makefile变量的初始化
KBUILD_EXTMOD 为空,因为命令行中没有”M= xxx“,KBUILD_SRC为空,因为没有“O = xxx“。
no-dot-config-targets := clean mrproper distclean \ cscope gtags TAGS tags help %docs check% coccicheck \ $(version_h) headers_% archheaders archscripts \ no-dot-config-targets kernelversion %src-pkgconfig-targets := 0mixed-targets := 0dot-config := 1ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) # MAKECMDGOALS 中仅包含no-dot-config-targets提供的命令 dot-config := 0 endifendififeq ($(KBUILD_EXTMOD),) ifneq ($(filter config %config,$(MAKECMDGOALS)),) # MAKECMDGOALS 包含config config-targets := 1 ifneq ($(filter-out config %config,$(MAKECMDGOALS)),) # MAKECMDGOALS 还包含其他命令 mixed-targets := 1 endifendif
由上面代码可以得出如下几个变量的值:
config-targets = 1
mixed-targets = 0
dot-config = 1
2. 确定执行规则
根据前面得到的几个变量,那么就可以确定执行Makefile line487~505的代码了。
include $(srctree)/arch/$(SRCARCH)/Makefileexport KBUILD_DEFCONFIG KBUILD_KCONFIGconfig: 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 $@
我们要先执行依赖规则 scripts_basic 和 outputmakefile,而后执行target。查找代码可以确认依赖规则如下:
# Makefile line 418scripts_basic: $(Q)$(MAKE) $(build)=scripts/basic $(Q)rm -f .tmp_quiet_recordmcount# Makefile line 429outputmakefile:ifneq ($(KBUILD_SRC),) # 不执行 $(Q)ln -fsn $(srctree) source $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)endif
3. 执行依赖规则
scripts_basic
$(Q)$(MAKE) $(build)=scripts/basic
build定义在scripts/Kbuild.include中,含义如下build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
那么这行代码展开即是make -f scripts/Makefile.build obj=scripts/basic
,跳到scripts/Makefile.build中执行,条件是obj=scripts/basic那我们把目光转向scripts/Makefile.build
src := $(obj) kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)include $(kbuild-file)
查找scripts/basic目录下所有的Kbuild或者Makefile,include 它们,然后编译其中的小模块,在这里编译出可执行程序fixdep.
outputmakefile
无执行代码。
4. 执行目标规则
$(Q)mkdir -p include/linux include/config
# 创建目录$(Q)$(MAKE) $(build)=scripts/kconfig $@
命令展开为make -f scripts/Makefile.build obj=scripts/kconfig menuconfig
跳到scripts/Makefile.build中执行,条件是obj=scripts/kconfig,目标是menuconfig。
继续解析,执行执行scripts/kconfig中的Makefile,目标规则menuconfig。menuconfig: $(obj)/mconf
$< $(Kconfig)其中$(obj)/mconf的创建是Kernel Makefile中最基础也是非常精彩的部分,linux中大部分子模块均是按照这样的方式组织的。
在scripts/kconfig/Makefile中有如下定义:
mconf-objs := mconf.o zconf.tab.o $(lxdialog)
lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
hostprogs-y += mconf
注意这里的mconf-objs和hostprogs-y
进入scripts/Makefile.host
__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
host-cmulti := $(foreach m,$(__hostprogs),\
$(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
__hostprogs := $(addprefix $(obj)/,$(__hostprogs))
host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
这里
__hostprogs := scripts/kconfig/mconf
host-cmulti := scripts/kconfig/mconf
host-cobjs := mconf.o zconf.tab.o lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o(不用关心这些.o文件是什么,我们只关心makefile的执行流程,这里在每个前面要加上前缀$(obj),即”scripts/kconfig/”)通过如下代码编译成可执行文件
cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
$(addprefix $(obj)/,$($(@F)-objs)) \
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE
$(call if_changed,host-cmulti)
上面第二个规则匹配目标mconf,而$(host-cobjs)的匹配规则如下
cmd_host-cobjs = $(HOSTCC) $(hostc_flags) -c -o $@ $<
$(host-cobjs): $(obj)/%.o: $(src)/%.c FORCE
$(call if_changed_dep,host-cobjs)
实质上是将.c 文件编译成 .o文件,而后调用cmd_host-cobjs生成$(host-cobjs)
各个目标文件。返回$(host-cmulti)
规则,调用cmd_host-cmulti生成最终的可执行文件mconf,叹为观止啊。最后返回最初的menuconfig规则,现在只剩下最后一条命令:
$< $(Kconfig)
,展开为scripts/Kconfig/mconf Kconfig,这是一条shell命令,使用刚编出来的可执行文件mconf来完成make menuconfig的最后步骤,即我们看到的图形化内核配置菜单,至此全部完成。
后面介绍Linux Makefile的其他编译目标,上文中如有不正确的部分欢迎指正。
- Linux Kernel Makefile解析(一)
- Linux kernel makefile 文档
- The Linux Kernel Makefile
- Linux Kernel Makefile
- Linux kernel Makefile
- linux kernel makefile analysis
- linux kernel 笔记(一)
- Linux Kernel Makefile默认目标
- linux kernel makefile整体分析
- Linux Kernel Makefile之一概况
- Linux2.6.x Kernel Makefiles (Linux内核Makefile文件 )
- linux kernel的makefile的组织结构(转载)
- Linux Makefile学习(一)
- Linux kernel Kobjects解析
- pintos项目的makefile解析(一)
- 嵌入式 Linux开发Kernel移植(三)——Kernel工程Makefile分析
- 构造嵌入式Linux(一):Kernel编译
- Linux Kernel读书笔记(一)---预备知识
- Git 实用命令总结
- Python自省(反射)----inspect module
- CSS基础知识一(CSS的应用方式、CSS选择器、选择器的声明、文字CSS效果、)
- android高级UI—ExpandableListview
- 【AKOJ】1032-水仙花数
- Linux Kernel Makefile解析(一)
- CSS基础知识二(段落设置CSS效果、图片边框、div和span区别、CSS控制背景、CSS控制链接)
- PHP实现分页效果
- 空指针和野指针
- 学习SpringMVC(二)之RequestMapping
- 谈谈Android中的OOM
- iOS键盘弹出 视图向上滚动键盘高度
- 集合的类型与各自的特性
- 布隆过滤器