[笔记] linux 4.19 版本 Kbuild 编译流程解析

目录

  • 写在前面与一些说明
    • linux 编译工程框架 Kbuild
    • Top-Makefile 文件
  • linux 编译命令
    • make help
    • distclean 目标
    • defconfig 目标
      • build 变量与 $(build)=dir 赋值
      • 使用 obj 变量实现包含目标模块下的 makefile
      • defconfig 规则展开
      • defconfig 的生成命令解析
    • make 默认目标生成 image.gz 镜像与 .dtb 设备树文件
      • vmlinux 编译生成流程
      • 子模块目录的指定(阅读 Kbuild 框架可知)
      • 编译目标文件的指定(阅读 Kbuild 框架可知)
      • 目标文件是编译进内核还是编译为 .ko 模块(阅读 Kbuild 框架可知)

写在前面与一些说明

之前一直在搞 RTOS 与 ARM 底层,对 linux 用的不多,现在是时候学习 linux 下的驱动框架与内核了,感谢网上那么多的学习资料(正点原子、知乎、CSDN...

linux 编译工程框架 Kbuild

linux 使用的编译工程框架为 Kbuild, 如果对 Kbuild 一无所知,在阅读本篇文章之前,建议阅读一遍 linux 内核工程中的下列文件(路径为 ./Documentation/kbuild/):
在这里插入图片描述

Top-Makefile 文件

top Makefile 为 liunx 内核根目录下的 Makefile 文件:
在这里插入图片描述

linux 编译命令

搭建交叉编译环境就不说了,直接在 SOC 原厂提供的 linux 工程根目录下运行如下命令:

# 清除工程
make  CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=arm64 distclean# defconfig 为 linux 特有的工程配置文件,控制哪些模块需要编译(编译进镜像或编译成 .ko)
# 并会在工程根目录下生成 .config 文件
make  CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=arm64 defconfig# 编译生成 linux 镜像, 在工程根目录下会生成 vmlinux 可执行文件
# 在 arch/(ARCH)/boot/ 目录下会生成 image.gz, 可由 uboot 下载启动
make  CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=arm64 -j4

make help

help 命令可以帮助我们查看基本的编译目标与命令,如果对 makefile 工程不熟悉,建议先运行此命令,熟悉主要的编译目标与作用:

make help

在这里插入图片描述

distclean 目标

作用为清除工程,包括所有中间文件,临时文件,目标文件,可执行文件:

make  CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=arm64 distclean

在这里插入图片描述

defconfig 目标

defconfig 文件为 linux 特有的工程配置文件,控制哪些模块需要编译(编译进镜像或编译成 .ko),并会在工程根目录下生成 .config 文件。
defconfig 文件在 arch/(ARCH)/config/ 目录下:
在这里插入图片描述
执行该命令时,对应 Top-Makefile 的如下规则:

# 该规则会根据 defconfig 文件,在工程根目录下生成 .config 文件
%config: scripts_basic outputmakefile FORCE$(Q)$(MAKE) $(build)=scripts/kconfig $@

在这里插入图片描述

build 变量与 $(build)=dir 赋值

build 变量为 Kbuild 框架里的一个非常重要的变量,用于调用 Kbuild 编译框架,并指定编译模块的路径.
该变量定义在 scripts/Kbuild.include 文件中:
在这里插入图片描述

###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
# Usage:
# $(Q)$(MAKE) $(build)=dir
build := -f $(srctree)/scripts/Makefile.build obj

对 build 变量解析如下:

  1. 首先使用 -f 选项指定 make 要运行的 makefile 文件为 $(srctree)/scripts/Makefile.build(一般为 ./scripts/makefile.build). 这个 makefile 是 Kbuild 框架的总入口文件,所有模块的编译都需要通过这个 makefile 文件进行编译。
  2. build 变量 包含一个 obj 变量, obj 变量用来指示目标模块的路径,并实现包含目标模块下的makefile。

使用 obj 变量实现包含目标模块下的 makefile

在此只做简述,后续会详解 linux 的 Kbuild 编译框架。
对应的代码在 makefile.build 文件中:
在这里插入图片描述
通过如下代码实现包含目标模块下的 makefile:

# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)

如果目标模块下存在 Kbuild 文件,那么会使用 Kbuild 作为要执行的 makefile。

defconfig 规则展开

根据上述信息,可展开 defconfig 目标对应的规则:

# 该规则会根据 defconfig 文件,在工程根目录下生成 .config 文件
defconfig: scripts_basic outputmakefile FORCEmake -f ./scripts/Makefile.build obj=scripts/kconfig defconfig

其中,依赖的 scripts_basicoutputmakefile 对应其他的目标规则,但这两个依赖主要用于生成辅助工具,暂不细究。

defconfig 的生成命令解析

命令展开为:

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

即执行 scripts/kconfig/Makefile 文件,并生成 defconfig 目标,对应的命令如下:
在这里插入图片描述

defconfig: $(obj)/conf
ifeq ($(KBUILD_DEFCONFIG),)$< $(silent) --defconfig $(Kconfig)
else
ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),)@$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
else@$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'"$(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG)
endif
endif

展开为 $(obj)/conf --defconfig=arch/$(arm64)/configs/defconfig Kconfig ,该命令的作用就是通过 defconfig 文件,生成 .config 文件。

make 默认目标生成 image.gz 镜像与 .dtb 设备树文件

当 make 不指定目标时,会使用 makefile 的第一个目标 _all 作为默认目标:
在这里插入图片描述
_all 目标会被会被覆盖:
在这里插入图片描述
此时默认编译目标为 all, all 目标对应的规则为:
在这里插入图片描述
虽然指定了:

# The all: target is the default when no target is given on the
# command line.
# This allow a user to issue only 'make' to build a kernel including modules
# Defaults to vmlinux, but the arch makefile usually adds further targets
all: vmlinux

但是在 include arch/$(SRCARCH)/Makefile 文件中,会被覆盖为:

all:	Image.gz $(KBUILD_DTBS)

在这里插入图片描述
通过如上的目标规则转换,make 默认目标的编译会生成 image.gz, vmlinux, *.dtb 文件。

主要分析 vmlinux 编译生成流程。

vmlinux 编译生成流程

这部分需要通读一遍 Top-Makefile, 以下依次列出 vmlinux 的目标规则转换路径,并说明:

  1. vmlinux 目标主要依赖 vmlinux-dep 目标:
vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE
ifdef CONFIG_HEADERS_CHECK$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
ifdef CONFIG_GDB_SCRIPTS$(Q)ln -fsn $(abspath $(srctree)/scripts/gdb/vmlinux-gdb.py)
endif+$(call if_changed,link-vmlinux)
  1. vmlinux-dep 变量包含所有的目标文件与目标模块子目录:
# Externally visible symbols (used by link-vmlinux.sh)
export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y)
export KBUILD_VMLINUX_LIBS := $(libs-y1)
export KBUILD_LDS          := arch/$(SRCARCH)/kernel/vmlinux.lds
export LDFLAGS_vmlinux
# used by scripts/package/Makefile
export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) arch Documentation include samples scripts tools)vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) $(KBUILD_VMLINUX_LIBS)
  1. vmlinux-dep 目标依赖 vmlinux-dirs 目标:
# The actual objects are generated when descending,
# make sure no implicit rule kicks in
$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
  1. vmlinux-dirs 变量是一个包含目录各个目录的变量,用于对 build 变量赋值:
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)))
  1. vmlinux-dirs 目标实现对所有子模块的递归编译:
# Handle descending into subdirectories listed in $(vmlinux-dirs)
# Preset locale variables to speed up the build process. Limit locale
# tweaks to this spot to avoid wrong language settings when running
# make menuconfig etc.
# Error messages still appears in the original languagePHONY += $(vmlinux-dirs)
$(vmlinux-dirs): prepare scripts$(Q)$(MAKE) $(build)=$@ need-builtin=1

最终,通过第5步的 $(Q)$(MAKE) $(build)=$@ need-builtin=1, 会调用 Kbuild 编译框架,对目标模块进行编译,而在 Makefile.build 文件中,同样会处理子目录的递归编译。此处暂不细究,需要通读 Kbuild 框架相关的 Makefile.

子模块目录的指定(阅读 Kbuild 框架可知)

通过变量 init-y/m, core-y/m, drivers-y/m,net-y/m, libs-y/m, virt-y 来实现需要编译的子目录

编译目标文件的指定(阅读 Kbuild 框架可知)

通过变量 obj-y/m(以及其他变量),可以控制需要编译生成哪些目标文件

目标文件是编译进内核还是编译为 .ko 模块(阅读 Kbuild 框架可知)

变量obj-y 所指定的目标文件会编译进内核;
变量 obj-m 所指定的目标文件会编译为模块。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/286347.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

万户OA text2Html接口存在任意文件读取漏洞

文章目录 产品简介漏洞概述指纹识别漏洞利用修复建议 产品简介 ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品&#xff0c;统一的基础管理平台&#xff0c;实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网…

喜报!巨蟹数科荣获国家“高新技术企业”认定!

根据《高新技术企业认定管理办法》&#xff08;国科发火〔2016〕32 号&#xff09;和《高新技术企业认定管理工作指引》&#xff08;国科发火〔 2016〕195号&#xff09;有关规定&#xff0c;经省高新技术企业认定管理机构组织企业申请、专家评审等程序&#xff0c;并经全国高新…

Netty应用(七) ----MQTT编解码器

目录 0.前言1. MqttEncoder--编码器1.1 构造方法1.2 encodeConnectMessage -- 连接消息1.3 encodeConnAckMessage - 确认连接1.4 encodePublishMessage -- 发布消息1.5 encodeSubscribeMessage - 订阅主题1.6 encodeUnsubscribeMessage - 取消订阅1.7 encodeSubAckMessage - 订…

关于“Python”的核心知识点整理大全28

目录 11.1.5 添加新测试 11.2 测试类 11.2.1 各种断言方法 unittestModule中的断言方法&#xff1a; ​编辑11.2.2 一个要测试的类 survey.py language_survey.py 11.2.3 测试 AnonymousSurvey 类 test_survey.py 往期快速传送门&#x1f446;&#xff08;在文章最后&…

Redis7--基础篇9(SpringBoot集成Redis)

1. jedis、lettuce、Redistemplate的关系 第一代为jedis&#xff0c;之后推出了lettuce&#xff0c;然后springboot继承了Redistemplate&#xff0c;现推荐使用Redistemplate。 总的来说&#xff0c;jedis、lettuce、Redistemplate都是java操作Redis数据库的驱动。 2. 本地Ja…

3700字!我这样的爬虫架构,如履薄冰

前言 在毕业设计中&#xff0c;用Java写下了第一个爬虫。2019年工作之后&#xff0c;从Python的requests原生爬虫库&#xff0c;学到分布式爬虫框架Scrapy&#xff0c;写了60个左右爬虫。然后写了十几篇有关于爬虫的文章。但大多都是围绕着程序设计、功能模块的角度写的&#…

【记录版】SpringBoot项目自动配置场景下查看Bean的定义

SpringBoot BeanDefinition 背景&#xff1a; 最近在看一些SpringBoot相关的一些源码框架&#xff0c;自从SpringBoot实现自动化配置后&#xff0c;很多框架的适配和实现对我们来说都是黑盒&#xff0c;我们不知道某个框架到底注册了多个容器实例&#xff0c;以及定位的位置在…

时尚炫酷动态图文幻灯片视频素材AE模板

这个After Effects模板以时尚和动态幻灯片为特色。可以编辑和自定义文本占位符、媒体占位符和颜色。用来展示照片或视频剪辑。不需要任何插件。 来自AE模板网&#xff1a;https://aemuban.com/28093.html

NineData成功举办|《国产数据库共话未来趋势》技术沙龙

12月16日周六下午&#xff0c;由NineData、PostgreSQL中文社区、PolarDB开源社区共同举办的《国产数据库共话未来趋势》技术沙龙&#xff0c;在NineData的报告厅成功举办。 《国产数据库共话未来趋势》技术沙龙合影 本次沙龙汇聚阿里云、玖章算术、百度云、飞轮科技、YMatrix、…

云原生系列2-GitLab和Jenkins

1、GitLab类似github&#xff0c;是个私有仓库 1、GitLab安装&#xff0c;至少8G内存4核cpu # 查找Gitlab镜像 docker search gitlab/gitlab-ce # gitlab镜像拉取 docker pull gitlab/gitlab-ce # 查看镜像 docker images # 本机先建3个目录&#xff0c;为了gitlab容器通过挂…

如何编写产品需求文档(PRD)?「附模板」

在数字化时代的快速变革中&#xff0c;产品开发不再是一个单向的、线性的过程。它涉及多方面的互动、多维度的考量&#xff0c;以及多个利益相关者的参与。那么&#xff0c;如何确保每个人都对产品的最终形态有一个清晰、一致的理解&#xff1f;如何确保每个人都在为同一个目标…

构建智慧储能物联网,4G工业路由器远程监测在线管理

物联网技术的发展为智慧储能管理带来了革命性的变化。其中&#xff0c;4G工业路由器IR5000通过丰富的连接能力如串口RS485/232或网口的方式&#xff0c;实现了与储能现场各设备的连接&#xff0c;包括电表、电能检测器、防孤岛装置、BMS电池管理系统、监控服务器、储能控制器、…