uboot移植之Makefile分析概述篇2

uboot移植之前期准备篇1

uboot移植之init_sequence_f函数数组分析(番外篇)

uboot移植之源码流程分析篇3(超详细!)

uboot移植之修改支持SDRAM篇4

uboot移植之修改支持NorFlash篇5

uboot移植之修改支持NandFlash识别篇6(超详细)


分析uboot,先要分析顶层Makefile,熟悉整体的编译流程。

1、make smdk2410_config

smdk2410_config是Makefile文件中定义的目标之一。当执行make smdk2410_config,会按顺序读取匹配Makefile中的规则,并找到对应的目标,根据其依赖关系,决定哪些目标需要更新,根据规则链不断地重复这个过程,直到找到最原始的依赖关系,并最终生成.config配置文件,供顶层Makefile读取。

定位目标:

% 符号为通配符,%config表明所有以 config 结尾的目标,其依赖于scripts_basic outputmakefile FORCE三者。但是,该规则置于ifeq中,需分析config-targets变量,发现于

make 的环境变量叫“MAKECMDGOALS”,这个变量中会存放你所指定的终极目标的列表,如果在命令行上,你没有指定目标,那么,这个变量是空值。比如make smdk2410_config,那个MAKECMDGOALS的值等于smdk2410_config。

$(filter $(no-dot-config-targets), $(MAKECMDGOALS))表示调用Makefile的filter函数,过滤掉 $(MAKECMDGOALS)中所有不符合$(no-dot-config-targets)模式的单词。比如 $(filter %.c %.s, foo.c bar.c bax.s uar.h),结果为 bax.s uar.h。而filter-out函数的作用则刚好相反,去除所有符合的单词。

执行ifneq后,过滤后为空,空==空,所以ifneq分支不执行。dot-config还等于1,查找 KBUILD_EXTMOD 变量定义位置

由注释可知,由于我们make时并没有传入参数指定路径,所以,SUBDIRS变量为空;$(origin M):origin 函数通过返回一个字符串来告诉你 M 变量的定义情况。(file:在Makefile中定义;command line:在命令行中定义;undefined:从来没有定义....)不过,我们并没有以 make M=dir 的方式编译,所以此处ifeq也不执行。KBUILD_EXTMOD变量为空。

所以440行的条件判断成立,$(filter config %config,$(MAKECMDGOALS))结果还是smdk2410_config,不为空,config-targets := 1,至此,已经确定466行分支条件成立。(words函数返回值是$(MAKECMDGOALS)变量的单词数目,所以,不执行ifneq)

在478行,Q = @  MAKE=make 。@就是控制命令的输出流信息,比如:

A:=abc      @echo $(A)            输出结果:abc

A:=abc          echo $(A)            输出结果:echo abc        abc

编译的时候可以通过输入参数V=1决定,详情:https://blog.csdn.net/qwaszx523/article/details/53218014

编译的时候定义了很多默认变量,MAKE变量的定义可以通过命令查看:

至于build变量,在当前Makefile中并没有找到其定义,何不妨搜索一下,看看是否包含在其他头文件中?

后面的不用看,撑死了最大范围也就当前行(478),到include scripts/Kbuild.include找,果真发现

build := -f $(srctree)/scripts/Makefile.build obj

所以make smdk2410_config最终要478行,即:

make -f ./scripts/Makefile.build obj=scripts/kconfig smdk2410_config

但是该目标依赖于scripts_basic outputmakefile FORCE三者,后两者为空,scripts_basic目标依赖于:

将其展开即为:

make -f ./scripts/Makefile.build obj=scripts/basic

rm -f .tmp_quiet_recordmcount

在bash中输入编译命令,校验分析结果:

2、make

当我们make但并没有指定生成目标的时候,那么默认是生成_all,从头往下找,发现_all被定义为伪目标:

129       # That's our default target when none is given on the command line

130       PHONY := _all
131       _all:

伪目标又称为假象目标,仅仅是一个标签,并不会在编译的过程中产生目标文件,而且伪目标一般没有依赖文件,所以目标被认为是最新的。但是,也可以为伪目标指定所依赖的对象。比如:

all: first second third

.PHONY: all

first: XXX

second: XXX

third: XXX

上述的all目标依赖于first second third,由于伪目标的特性是总会被执行的,所以其依赖的三个目标就总是不如all这个目标新,每次都会检查依赖的目标是否最新。

195        # If building an external module we do not care about the all: rule
196        # but instead _all depend on modules
197        PHONY += all
198        ifeq ($(KBUILD_EXTMOD),)
199        _all: all
200        else
201        _all: modules
202        endif

由1分析我们已经可以知道,$(KBUILD_EXTMOD)为空,所以伪目标 _all 依赖于 all ,而all又依赖于$(ALL-y)。

804       all:        $(ALL-y)

所以,最终统揽全文件的重任就落到$(ALL-y)手上了,根据ALL-$(valiable)决定对应的文件是否编译进终极文件。

还有把各种库文件打包,比如驱动,设备树,net等等

最后,把所有生成的目标文件链接在一起,连接过程如下:

直接执行make V=1命令,在最后的输出信息很容易找到其详细链接过程:

两个横框之间的就是组成输出-o uboot 的原材料,也就是各种的obj文件。通过链接脚本u-boot.lds和链接地址 -Ttext 0x0 可以知道u-boot代码的组织排放,也就是各种段,还有文件先后的排放次序。

也就是说,后面的text段,data段等等,都放在(当前地址 .=0x0 + 链接地址-Ttext 0x0的位置) 0x0 ,因为 . =0x0这只是个代码地址偏移值,真正的起始地址是由编译时指定的。

最开始排放的是代码段中的*(.__image_copy_start) ,*(.vectors)以及arch/arm/cpu/arm920t/start.o (.text*)。

通常,在调用代码重定位的时候,就是要把__image_copy_start到__image_copy_end之间的数据进行拷贝,放到链接地址,关于链接地址本篇暂不讨论。而*(.vectors)存放的是中断向量表。

很明显,要想分析启动流程,应从arch/arm/cpu/arm920t/start.o入手,也就是该目录下的start.s汇编源码。

请戳链接:uboot移植之源码流程分析篇3

水平有限,草草分析,很多地方都没有深入去探究,有什么分析的不恰当,还望告知。

关于make过程更详尽的分析请看:https://blog.csdn.net/q_z_r_s/article/details/80719298

参考资料:

《ARM9嵌入式系统设计与应用开发》 熊茂华 杨震伦 主编

《嵌入式Linux应用开发完全手册》 韦东山著

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值