Kbuild 历史
kbuild 是 Linux 内核构建系统的一部分,其历史可以追溯到 Linux 内核最早的版本。以下是关于 kbuild 的历史概述:
1991 年:最早的 Linux 内核版本使用了一个简单的 Makefile 系统来构建内核。这个系统只是一个简单的脚本,用于编译和链接内核代码。
1996 年:Linux 内核的构建系统得到了改进,引入了一个名为 Makefile 的文件,其中包含了构建内核所需的规则和指令。
这个 Makefile 是一个相对简单的脚本,但已经具备了一些基本的功能,如指定编译器、编译选项和目标文件等。
1999 年:随着 Linux 内核的不断发展,构建系统的复杂性也逐渐增加。为了应对这一挑战,一个新的构建系统,即 kbuild,被引入到 Linux 内核中。
kbuild 使用 Makefile 来描述构建过程,并在此基础上添加了许多新功能,以提高构建系统的灵活性和可扩展性。
2002 年:Linux 内核的构建系统进一步改进,引入了更多的功能和工具,以支持更复杂的构建过程。
这些新功能包括支持不同架构的交叉编译、模块化构建、依赖关系管理等。
随着时间的推移,kbuild 继续演进和改进,以适应不断变化的 Linux 内核。
今天的 kbuild 系统已经成为一个非常强大和灵活的工具,被广泛用于构建 Linux 内核和相关的驱动程序和模块。
Kbuild 系统 组成
我们以 https://github.com/EmulateSpace/Kbuild.git 为例,瞅瞅过程
Kbuild 最先出现在 linux 中, 但也可以将其抽出来用于其他项目.
示例
$ tree -a
.
├── .config // 2
├── configs
│ └── defconfig
├── include
│ ├── config
│ │ ├── auto.conf
│ │ ├── auto.conf.cmd
│ │ ├── biscuitos
│ │ │ └── rbtree.h
│ │ ├── cross
│ │ │ └── compile.h
│ │ └── tristate.conf
│ ├── generated
│ │ └── autoconf.h
│ └── linux
│ └── rbtree.h
├── Kconfig
├── lib
│ ├── Kconfig
│ ├── lib.a
│ ├── .lib.a.cmd
│ ├── Makefile // 5
│ ├── rbtree.c
│ ├── rbtree.o
│ └── .rbtree.o.cmd
├── main
│ ├── built-in.o
│ ├── .built-in.o.cmd
│ ├── main.c
│ ├── main.o
│ ├── .main.o.cmd
│ └── Makefile // 5
├── Makefile // 1
├── README.md
├── scripts
│ ├── basic
│ │ ├── fixdep
│ │ ├── fixdep.c
│ │ ├── .fixdep.cmd
│ │ ├── .gitignore
│ │ └── Makefile
│ ├── Kbuild.include
│ ├── kconfig
│ │ ├── check.sh
│ │ ├── conf
│ │ ├── conf.c
│ │ ├── .conf.cmd
│ │ ├── confdata.c
│ │ ├── conf.o
│ │ ├── .conf.o.cmd
│ │ ├── expr.c
│ │ ├── expr.h
│ │ ├── gconf.c
│ │ ├── gconf.glade
│ │ ├── .gitignore
│ │ ├── images.c
│ │ ├── kconfig_load.c
│ │ ├── kxgettext.c
│ │ ├── lex.zconf.c
│ │ ├── lex.zconf.c_shipped
│ │ ├── lkc.h
│ │ ├── lkc_proto.h
│ │ ├── lxdialog
│ │ │ ├── BIG.FAT.WARNING
│ │ │ ├── checklist.c
│ │ │ ├── check-lxdialog.sh
│ │ │ ├── dialog.h
│ │ │ ├── .gitignore
│ │ │ ├── inputbox.c
│ │ │ ├── menubox.c
│ │ │ ├── textbox.c
│ │ │ ├── util.c
│ │ │ └── yesno.c
│ │ ├── Makefile
│ │ ├── mconf.c
│ │ ├── menu.c
│ │ ├── nconf.c
│ │ ├── nconf.gui.c
│ │ ├── nconf.h
│ │ ├── POTFILES.in
│ │ ├── qconf.cc
│ │ ├── qconf.h
│ │ ├── streamline_config.pl
│ │ ├── symbol.c
│ │ ├── util.c
│ │ ├── zconf.gperf
│ │ ├── zconf.hash.c
│ │ ├── zconf.hash.c_shipped
│ │ ├── zconf.l
│ │ ├── zconf.tab.c
│ │ ├── zconf.tab.c_shipped
│ │ ├── zconf.tab.o
│ │ ├── .zconf.tab.o.cmd
│ │ └── zconf.y
│ ├── Makefile
│ ├── Makefile.build // 4
│ ├── Makefile.clean
│ ├── Makefile.host
│ ├── Makefile.lib
│ └── mkmakefile
├── vmlinux
└── .vmlinux.cmd
生成过程
// make defconfig 做了什么
pop@pd:~/work/3_demo/kbuild/Kbuild$ date
2023年 09月 03日 星期日 19:04:39 CST
pop@pd:~/work/3_demo/kbuild/Kbuild$ find . -newermt "2023-09-03 19:04:39"
pop@pd:~/work/3_demo/kbuild/Kbuild$ make defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
scripts/kconfig/conf --defconfig Kconfig
#
# configuration written to .config
#
pop@pd:~/work/3_demo/kbuild/Kbuild$ find . -newermt "2023-09-03 19:04:39"
.
./scripts/kconfig
./scripts/kconfig/.conf.cmd
./scripts/kconfig/conf.o
./scripts/kconfig/.zconf.tab.o.cmd
./scripts/kconfig/zconf.tab.o
./scripts/kconfig/conf
./scripts/kconfig/.conf.o.cmd
./scripts/basic
./scripts/basic/fixdep
./scripts/basic/.fixdep.cmd
./.config
// make 做了什么
pop@pd:~/work/3_demo/kbuild/Kbuild$ date
2023年 09月 03日 星期日 19:07:24 CST
pop@pd:~/work/3_demo/kbuild/Kbuild$ find . -newermt "2023-09-03 19:07:24"
pop@pd:~/work/3_demo/kbuild/Kbuild$ make
scripts/kconfig/conf --silentoldconfig Kconfig
CC main/main.o
LD main/built-in.o
CC lib/rbtree.o
AR lib/lib.a
LD vmlinux
pop@pd:~/work/3_demo/kbuild/Kbuild$ find . -newermt "2023-09-03 19:07:24"
.
./lib
./lib/rbtree.o
./lib/.lib.a.cmd
./lib/lib.a
./lib/.rbtree.o.cmd
./include/generated
./include/generated/autoconf.h
./include/config
./include/config/auto.conf.cmd
./include/config/auto.conf
./include/config/tristate.conf
./main
./main/.built-in.o.cmd
./main/main.o
./main/.main.o.cmd
./main/built-in.o
./.vmlinux.cmd
./vmlinux
// make 中的 scripts/kconfig/conf --silentoldconfig Kconfig 做了什么
pop@pd:~/work/3_demo/kbuild/Kbuild$ date
2023年 09月 03日 星期日 19:08:42 CST
pop@pd:~/work/3_demo/kbuild/Kbuild$ scripts/kconfig/conf --silentoldconfig Kconfig
pop@pd:~/work/3_demo/kbuild/Kbuild$ find . -newermt "2023-09-03 19:08:42"
.
./include/generated
./include/generated/autoconf.h
./include/config
./include/config/auto.conf.cmd
./include/config/auto.conf
./include/config/tristate.conf
拆解
- 工具
scripts/kconfig/conf
scripts/basic/fixdep
- Kbuild 管理的工程中的 makefile 分类(以linux为例)
The Makefiles have five parts:
Makefile the top Makefile.
.config the kernel configuration file.
arch/$(SRCARCH)/Makefile the arch Makefile.
scripts/Makefile.* common rules etc. for all kbuild Makefiles.
kbuild Makefiles exist in every subdirectory
- Kconfig
Kconfig the top Kconfig
Kconfig exist in every subdirectory
参考资料
- linux Kbuild 官方文档
- linux Kbuild详解系列
- Kbuild 实现分析 x.yin@hotmail.com Jun 1,2009
- Kbuild 系统原理分析
拆解出来的 Kbuild 简单示例
-
基于 linux-6.3.0 拆解出来的一个最简单的Kbuild 框架
$ tree
.
├── arch
│ ├── Kconfig
│ └── x86
│ ├── configs
│ │ └── x86_64_defconfig
│ ├── Kbuild
│ ├── Kconfig
│ ├── kernel
│ │ ├── Makefile
│ │ └── vmlinux.lds.S
│ ├── Makefile
│ └── start.S
├── include
├── init
│ ├── main.c
│ └── Makefile
├── Kbuild
├── Kconfig
├── Makefile
└── scripts
├── as-version.sh
├── basic
│ ├── fixdep.c
│ └── Makefile
├── cc-version.sh
├── check-local-export
├── Kbuild.include
├── kconfig
├── Kconfig.include
├── ld-version.sh
├── link-vmlinux.sh
├── Makefile
├── Makefile.asm-generic
├── Makefile.build
├── Makefile.clang
├── Makefile.clean
├── Makefile.compiler
├── Makefile.debug
├── Makefile.defconf
├── Makefile.dtbinst
├── Makefile.extrawarn
├── Makefile.gcc-plugins
├── Makefile.headersinst
├── Makefile.host
├── Makefile.kasan
├── Makefile.kcov
├── Makefile.kcsan
├── Makefile.kmsan
├── Makefile.lib
├── Makefile.modfinal
├── Makefile.modinst
├── Makefile.modpost
├── Makefile.package
├── Makefile.randstruct
├── Makefile.ubsan
├── Makefile.userprogs
├── Makefile.vmlinux
├── Makefile.vmlinux_o
├── min-tool-version.sh
├── misc-check
├── mksysmap
├── pahole-flags.sh
└── subarch.include
11 directories, 94 files
linux-6.3.0 Kbuild
目标config 和%config 依赖关系
688 config: outputmakefile scripts_basic FORCE
689 $(Q)$(MAKE) $(build)=scripts/kconfig $@
690
691 %config: outputmakefile scripts_basic FORCE
692 $(Q)$(MAKE) $(build)=scripts/kconfig $@
目标all依赖关系
__all : all // 在 M=xxx时 KBUILD_EXTMOD 为xxx , 则 _all 的 依赖为 modules
all : vmlinux
vmlinux : vmlinux.o
vmlinux.o : vmlinux_o
vmlinux_o : vmlinux.a
vmlinux.a : $(KBUILD_VMLINUX_OBJS) // KBUILD_VMLINUX_OBJS 为 ./built-in.a
$(KBUILD_VMLINUX_OBJS) : . // 注意: 这里是 一个 dot (即.)
$(build-dir) : prepare // build-dir 是 .
make -f ./scripts/Makefile.build obj=. need-builtin=1 need-modorder=1
prepare : prepare0
prepare0 : archprepare
archprepare : outputmakefile archheaders archscripts scripts include/config/kernel.release \
asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h \
include/generated/compile.h include/generated/autoconf.h remove-stale-files
scripts/Makefile.build
1.scripts/Makefile.build 被调用的第一种情况 : 默认目标
- 顶层 Makefile 如何调用 scripts/Makefile.build
$(Q)$(MAKE) $(build)=scripts/dtc
等价于
make -f ./scripts/Makefile.build obj=scripts/dtc
- scripts/Makefile.build 的默认目标
./scripts/Makefile.build
472 # Build
473 # ---------------------------------------------------------------------------
474
475 $(obj)/: $(if $(KBUILD_BUILTIN), $(targets-for-builtin)) \
476 $(if $(KBUILD_MODULES), $(targets-for-modules)) \
477 $(subdir-ym) $(always-y)
478 @:
2.scripts/Makefile.build 被调用的第二种情况 : 指定目标
make -f ./scripts/Makefile.build obj=. prepare
- scripts/Makefile.build 的目标 prepare
来自顶层Kbuild
3.scripts/Makefile.build 被调用的第三种情况 : 定义了need-builtin
这是 顶层的 ./built-in.a 和 ./modules.order 被产生的导火索!!!
make -f ./scripts/Makefile.build obj=. need-builtin=1 need-modorder=1
// 还是走的 scripts/Makefile.build , 此时 由于传入了变量 "need-builtin=1 need-modorder=1" 默认目标的依赖变化了
// 依赖增加了 ./built-in.a 和 ./modules.order
- 目标 $(obj)/built-in.a
$(obj)/built-in.a 可 对应 每一层的 文件 built-in.a
// 定义了每层路径生成built-in.a 的 依赖 和 过程!!
$(obj)/built-in.a: $(real-obj-y) FORCE
$(call if_changed,ar_builtin)