Linux移植之子目录下的built

Stella981
• 阅读 408

Linux移植之make uImage编译过程分析中罗列出了最后链接生成vmlinux的过程。可以看到在每个子目录下都有一个built-in.o文件。对于此产生了疑问built-in.o文件是根据什么产生的。

arm-linux-ld -EL  -p --no-undefined -X -o vmlinux -T arch/arm/kernel/vmlinux.lds
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-s3c2410/built-in.o  arch/arm/mach-s3c2400/built-in.o  
arch/arm/mach-s3c2412/built-in.o  arch/arm/mach-s3c2440/built-in.o  arch/arm/mach-s3c2442/built-in.o  arch/arm/mach-s3c2443/built-in.o  
arch/arm/nwfpe/built-in.o  arch/arm/plat-s3c24xx/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  net/built-in.o --end-group .tmp_kallsyms2.o

1、测试,在linux目录下添加一个test文件夹,在文件夹里面添加了test.c 和 Makefile。测试是否也会生成built-in.o文件

2、从顶层Makefile文件开始分析built-in.o原理

3、递归规则

1、测试,在linux目录下添加一个test文件夹,在文件夹里面添加了test.c 和 Makefile。测试是否也会生成built-in.o文件

a、mkdir test,创建test文件夹

b、cd test,进入test文件夹

d、vim Makefile,在里面创建Makefile

#
#Makefile for the linux kernel makefile experiment.
#
obj-y := test.o

e、vim test.c,在里面创建C文件

#include <linux/export.h>

int test_global = 0;

f、修改顶层Makefile,在core-y后面增加test/目录

-core-y         += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+core-y         += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ test/

g、make uImage后观察到在链接的过程中多出了test/built-in.o 文件。测试成功

arm-linux-ld -EL  -p --no-undefined -X -o .tmp_vmlinux1 -T arch/arm/kernel/vmlinux.lds 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-s3c2410/built-in.o  arch/arm/mach-s3c2400/built-in.o  arch/arm/mach-s3c2412/built-in.o  arch/arm/mach-s3c2440/built-in.o  arch/arm/mach-s3c2442/built-in.o  arch/arm/mach-s3c2443/built-in.o  arch/arm/nwfpe/built-in.o  arch/arm/plat-s3c24xx/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  test/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  net/built-in.o --end-group

2、从顶层Makefile文件开始分析built-in.o原理,****在测试成功后,要分析是怎么做到更改了几个文件就能产生test/built-in.o并且编译进内核的。

从顶层Makefile开始分析,vmlinux-dirs包含了所有的linux子目录

vmlinux-dirs    := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
             $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
             $(net-y) $(net-m) $(libs-y) $(libs-m)))

$(patsubst <pattern>,<replacement>,<text> )
名称:模式字符串替换函数——patsubst。
功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“ 换行”分隔)是否符合模
式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,
表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的这个“%”
将是<pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“\%”来表示真实含
义的“%”字符)
返回:函数返回被替换过后的字符串。

$(filter <pattern...>,<text> )
名称:过滤函数——filter。
功能:以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。可以有
多个模式。
返回:返回符合模式<pattern>的字串。

另外在arch/arm/Makefile下也定义了一些文件夹:

171    core-y                += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
172    core-y                += $(MACHINE)
173    core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2400/
174    core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2412/
175    core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2440/
176    core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2442/
177    core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2443/
178    core-$(CONFIG_FPE_NWFPE)    += arch/arm/nwfpe/
179    core-$(CONFIG_FPE_FASTFPE)    += $(FASTFPE_OBJ)
180    core-$(CONFIG_VFP)        += arch/arm/vfp/
181
182    # If we have a common platform directory, then include it in the build.
183    core-$(CONFIG_PLAT_IOP)        += arch/arm/plat-iop/
184    core-$(CONFIG_ARCH_OMAP)    += arch/arm/plat-omap/
185    core-$(CONFIG_PLAT_S3C24XX)        += arch/arm/plat-s3c24xx/
186
187    drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
188    drivers-$(CONFIG_ARCH_CLPS7500)    += drivers/acorn/char/
189    drivers-$(CONFIG_ARCH_L7200)    += drivers/acorn/char/
190
191    libs-y                := arch/arm/lib/ $(libs-y)

展开得到

vmlinux-dir = init usr \
arch/arm/kernel arch/arm/mm arch/arm/common arch/arm/mach-s3c2410 arch/arm/mach-s3c2400 arch/arm/mach-s3c2412 arch/arm/mach-s3c2440  \
arch/arm/mach-s3c2442 arch/arm/mach-s3c2443 arch/arm/nwfpe arch/arm/plat-s3c24xx   \
kernel mm fs ipc security crypto block test  \
arch/arm/lib lib arch/arm/lib  \
drivers sound net  \

继续看顶层Makefile生成vmlinux-dirs的规则如下:

764    $(vmlinux-dirs): prepare scripts
765        $(Q)$(MAKE) $(build)=$@

以创建的test目录为例:展开得到。它的意思是调用scripts/Makefile.build。令参数obj=test,然后make。

make -f scripts/Makefile.build obj=test

接着进入scripts/Makefile.build继续分析,它的默认目标是__build:

07    PHONY := __build
08    __build:

83    __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
84         $(if $(KBUILD_MODULES),$(obj-m)) \
85         $(subdir-ym) $(always)
86        @:

接着看builtin-target、lib-target,它们被定义的条件是obj-%、lib-%不能为空

73    ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
74    lib-target := $(obj)/lib.a
75    endif
76
77    ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),)
78    builtin-target := $(obj)/built-in.o
79    endif

名称:去空格函数——strip。
功能:去掉<string>字串中开头和结尾的空字符。
返回:返回被去掉空格的字符串值。

接着看生成builtin-target的规则,lib-target的规则类似,还是在scripts/Makefile.build里找到如下规则

254    # To build objects in subdirs, we need to descend into the directories
255    $(sort $(subdir-obj-y)): $(subdir-ym) ;
256
257    #
258    # Rule to compile a set of .o files into one .o file
259    #
260    ifdef builtin-target
261    quiet_cmd_link_o_target = LD      $@
262    # If the list of objects to link is empty, just create an empty built-in.o
263    cmd_link_o_target = $(if $(strip $(obj-y)),\
264                  $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\
265                  rm -f $@; $(AR) rcs $@)
266
267    $(builtin-target): $(obj-y) FORCE
268        $(call if_changed,link_o_target)
269
270    targets += $(builtin-target)
271    endif # builtin-target

调用if_changed函数,进入scripts/Kbuild.include中

167    if_changed = $(if $(strip $(any-prereq) $(arg-check)),                       \
168        @set -e;                                                             \
169        $(echo-cmd) $(cmd_$(1));                                             \
170        echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)

可以看到最后调用的是cmd_link_o_target 脚本,回到scripts/Makefile.build中:

257    #
258    # Rule to compile a set of .o files into one .o file
259    #
260    ifdef builtin-target
261    quiet_cmd_link_o_target = LD      $@
262    # If the list of objects to link is empty, just create an empty built-in.o
263    cmd_link_o_target = $(if $(strip $(obj-y)),\
264                  $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\
265                  rm -f $@; $(AR) rcs $@)

其中obj-y=test.o定义在test目录下的Makefile中,如下在scripts/Makefile.build中include了$(kbuild-dir)/Makefile,即test/Makefile

16    kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
17    include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)

将规则展开得到:最终得到了test/built-in.o  

cmd_link_o_target = arm-linux-ld -EL -r -o test/built-in.o test.o arm-linux-ar rcs test/built-in.o

3、递归规则。如果在子目录下还有子目录编译系统会怎么操作呢,下面就讲述递归的规则:

继续看scripts/Makefile.build,它包含了scripts/Makefile.lib

19 include scripts/Makefile.lib

接着看到scripts/Makefile.lib,里面定义了subdir-ym 这个变量表示的是如果obj-y含有文件夹则将文件夹放到subdir-ym中

24    __subdir-y    := $(patsubst %/,%,$(filter %/, $(obj-y)))
25    subdir-y    += $(__subdir-y)
26    __subdir-m    := $(patsubst %/,%,$(filter %/, $(obj-m)))
27    subdir-m    += $(__subdir-m)
28    obj-y        := $(patsubst %/, %/built-in.o, $(obj-y))
29    obj-m        := $(filter-out %/, $(obj-m))
30
31    # Subdirectories we need to descend into
32
33    subdir-ym    := $(sort $(subdir-y) $(subdir-m))

继续回到scripts/Makefile.build,看到有关subdir-y的规则

322    $(subdir-ym):
333        $(Q)$(MAKE) $(build)=$@

可以看到这个规则与第二部分的规则很类似,这是一个递归调用,scripts/Makefile.build调用自己生成subdir-ym/built-in.o。具体分析与第二部分一样。下面截图自第二部分分析

Linux移植之子目录下的built

子目录下的built-in.o 就是这么生成的。参考自https://www.ibm.com/developerworks/community/blogs/5144904d-5d75-45ed-9d2b-cf1754ee936a/entry/kernel-build-system?lang=en

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这