Kbuild

本文概述了Linux内核构建系统kbuild的发展历程,从最初的简单Makefile到引入kbuild以提高灵活性,以及kbuild如何支持模块化、跨架构编译等功能,展示了其在Linux内核构建中的重要角色。
摘要由CSDN通过智能技术生成

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
20230903日 星期日 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
20230903日 星期日 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
20230903日 星期日 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

参考资料

拆解出来的 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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值