0%

linux 内核源码编译过程

linux 内核源码编译过程

1 源码根目录 Makefile

1.1 编译流程

  • 先执行各子目录的 Makefile,生成各自的编译产物 built-in.o 文件,最后再由链接器将二进制文件链接成完整的内核镜像文件 vmlinux

1.2 体系结构相关代码编译

  • 查看根目录 Makefile 文件,
1
2
3
SRCARCH     := $(ARCH)
............
include arch/$(SRCARCH)/Makefile

ARCH 变量是在编译内核源码前通过 export 命令指定的,比如

1
$ export ARCH=x86

源码根目录 Makefile 文件包含了体系结构相关目录的 Makefile 文件

1.3 子模块相关代码编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/

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

vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
$(init-) $(core-) $(drivers-) $(net-) $(libs-) $(virt-))))

init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
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)
virt-y := $(patsubst %/, %/built-in.o, $(virt-y))

各子模块执行对应目录下的 Makefile 文件,生成各自的 built-in.o 文件,最后再根据源码根目录下的 Makefile 文件链接成完整的内核镜像文件 vmlinux

2 子目录 (以 drivers/tty 目录为例)

2.1 Kconfig 文件

  • Kconfig 文件存放编译的配置信息,决定着哪些 .c 文件要被编译,是编译到内核中,还是以独立模块的形式编译
  • 配置 n 表示不编译,y 表示编译到内核中,m 表示以独立模块的形式编译
  • 执行 make memuconfig 命令,可以在命令行可视化查看、编辑 Kconfig 文件中的配置

2.2 Makefile 文件

  • 截取其中的1个片段,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
obj-y               += irqchip/
obj-y += bus/

obj-$(CONFIG_GENERIC_PHY) += phy/

# GPIO must come after pinctrl as gpios may need to mux pins etc
obj-$(CONFIG_PINCTRL) += pinctrl/
obj-$(CONFIG_GPIOLIB) += gpio/
obj-y += pwm/
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_RAPIDIO) += rapidio/
obj-y += video/
obj-y += idle/
............
  • obj-y 表示将指定目录下的代码编译到内核
  • obj-$(变量) 表示根据 Kconfig 文件中的配置决定是否将该目录下的源码编译到内核中,这个变量会在 Kconfig 文件中设置