首页 > 系统服务 > 详细

Linux Makefile分析

时间:2020-02-20 21:27:58      阅读:71      评论:0      收藏:0      [点我收藏+]

目的:

  分析Makefile在内核中的作用

 

Makefile的作用总结:

  1)决定编译哪些文件?

  2)怎样编译这些文件?

  3)怎样连接这些文件,最重要的是他们的顺序如何?

 

1、linux内核中Makefile体系

顶层Makefile

所以Makefile的核心,根据不同平台,对各类target分类并调用相应的规则Makefile生成目标

.config

配置文件,配置内核是生成。所有Makefile都是根据 .config 来决定使用哪些文件

arch/$(ARCH)/Makefile

具体平台相关的Makefile,相关决定哪些体系结构相关的文件参与内核的生成

scripts/Makefile.*

通用规则文件,面向所有的Kbuild Makefiles

各子目录下的Makefile 文件

由其上层目录的Makefile调用,执行其上层传递下来的命令

  根据Makefile的3大作用分析这5类文件。

  (1)决定编译哪些文件

    linux内核的编译是从顶层的Makefile开始的,然后递归地进入各级子目录调用各自的Makefile,分为3个步骤:

    a、顶层Makefile决定内核目录下哪些子目录将被编进内核

    b、arch/$(ARCH)/Makefile 决定所在目录下哪些文件、目录编入内核

    c、各级子目录下的Makefile决定所在目录下哪些文件编入内核,哪些文件编成模块(即驱动程序),进入哪些子目录继续调用他们的Makefile。

 

    先看步骤A,在顶层Makefile可看到:

# Objects we will link into vmlinux / subdirs we need to visit
init-y          := init/
drivers-y       := drivers/ sound/
net-y           := net/
libs-y          := lib/
core-y          := usr/
......
core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

    可知,顶层Makefile将内核下的目录分为5类,

    init-y :   drivers-y :   net-y :    libs-y :core-y 

    (arch目录会在arch/$(ARCH)/Makefile 中被包含入内核)

    可以在顶层目录的Makefile修改ARCH变量,如下

//修改前
ARCH           ?= $(SUBARCH)
ARCH            ?= ?

//修改后
ARCH            ?= arm
CROSS_COMPILE   ?= arm-linux-

   对于步骤B的arch/$(ARCH)/Makefile,以ARM体系为例,在arch/arm/Makefile中可看到:

......
core-y                += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y                += $(MACHINE)
...
core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2440/
core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2442/
...
core-$(CONFIG_FPE_NWFPE)    += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE)    += $(FASTFPE_OBJ)
core-$(CONFIG_VFP)        += arch/arm/vfp/
......

  可以看到Makefile对core-y的内容进行了进一步的扩展,在这个Makefile中,出现了另一类:head-y,不过它是直接以文件名出现的。

#Default value
head-y        := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o

  编译内核时,将依次进入init-y :   drivers-y :   net-y :    libs-y :core-y 所列出的目录中执行各自的Makefile,每个子目录都会生成一个build-in.o ,最后head-y所表示的文件将和这些build-in.o一起连接成内核印象文件 vmlinux。

  最后,看看步骤C怎么进行的:

  步骤3的作用:“各级子目录下的Makefile决定所在目录下哪些文件编入内核,哪些文件编成模块(即驱动程序),进入哪些子目录继续调用他们的Makefile“”

  在配置内核时,会生成.config ,在顶层Makefile中会有以下语句间接包含.config文件,以后就根据.config中定义的各变量决定编译时用哪些文件(实际包含的是与.config等效的auto,conf)

# Read in config
-include include/config/auto.conf

  auto.conf内容如下:

# Automatically generated make config: dont edit
# Linux kernel version: 2.6.22.6
# Wed Feb 19 07:48:42 2020
CONFIG_CPU_S3C244X=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_DEBUG_USER=y
CONFIG_FLATMEM=y
...

   这些变量的值主要有两类,"y" , "m"。各级子目录的Makefile使用这些变量决定哪些文件编进内核,哪些文件编成模块,要进入哪些子目录继续决定编译。具体通过以下方法确定:

  1)obj-y 用来决定哪些文件编进内核

  2)obj-m 用来定义哪些文件编成可加载模块

  3)lib-y 用来定义哪些文件编成库文件

  4)obj-y , obj-m 还可以用来指定要进入的下一层目录

 

(2)怎样编译这些文件。

  即编译选项、连接选项是什么。这些选项分为3类:全局的(适用于整个南海代码树);局部的(仅适用某个Makefile中的文件);个体的(仅适用某个文件)

  全局选项在顶层Makefile和arch/$(ARCH)/Makefile 中定义,局部选项在各个子目录的Makefile中。

 

(3) 怎样连接这些文件,它们的顺序如何

  在前面分析哪些文件会编进内核时,知道顶层Makefile和 arch/$(ARCH)/Makefile 定义了6类目录(或文件):

  head-y ,  init-y , drivers-y ,  net-y , libs-y , core-y 。以ARM体系为例,它们的初始值如下:

  在arch/arm/Makefile 中:

head-y        := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
 
core-y                += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y                += $(MACHINE)
...
core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2440/
core-$(CONFIG_ARCH_S3C2410)    += arch/arm/mach-s3c2442/
...
libs-y                := arch/arm/lib/   $(libs-y)

  在顶层Makefile中:

443 - 556行
init-y := init/ drivers-y := drivers/ sound/ net-y := net/ libs-y := lib/ core-y := usr/ ...... core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

 可见,除了head-y之外,其余的init-y , drivers-y等都是目录名。在顶层Makefile中,这些目录名的后面直接加上build-in.o 或 lib.a ,表示要链接进内核的文件,如下所示:

567 - 573行                                       等价于箭头后的表达
init-y        := $(patsubst %/, %/built-in.o, $(init-y)) ---> init/build-in.o
core-y        := $(patsubst %/, %/built-in.o, $(core-y)) ---> core/build-in.o
drivers-y    := $(patsubst %/, %/built-in.o, $(drivers-y))--> drievrs/build-in.o
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)

  在顶层Makefile中,再往下看:

602 - 605 行
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/$(ARCH)/kernel/vmlinux.lds export KBUILD_VMLINUX_OBJS := $(vmlinux-all)

  vmlinux-all 表示所有构成内核印象文件vmlinux的目标文件,带入后等价于以下:

vmlinux-all  := $(head-y) $(init-y)  $(core-y) $(libs-y) $(drivers-y) $(net-y)

  已知上面的这些文件init-y等会生成对应的文件init/build-in.o文件被编译进内核。

  vmlinux-lds表示连接脚本。顶层Makefile会按照一定的顺序组织文件,根据此链接脚本生成内核映像文件。

vmlinux
#   ^
#   |
#   +-< $(vmlinux-init)
#   |   +--< init/version.o + more
#   |
#   +--< $(vmlinux-main)
#   |    +--< driver/built-in.o mm/built-in.o + more
#   |
#   +-< kallsyms.o (see description in CONFIG_KALLSYMS section)

参考:

《linux应用开发完全手册》 --韦东山

https://www.cnblogs.com/lifexy/p/7348534.html

 

Linux Makefile分析

原文:https://www.cnblogs.com/y4247464/p/12334193.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!