kbuild实际如何工作? [英] How does kbuild actually work?
问题描述
在开发linux驱动程序时,我已经阅读了有关如何通过文档
When i'm developing a linux driver, i've read about how to write linux kbuild makefile through this document
我知道kbuild系统会使用诸如obj-y obj-m之类的makefile变量来确定要构建什么以及如何构建.
I know kbuild system use makefile variables such as obj-y obj-m to determine what to build and how to build.
但是我很困惑的是kbuild系统真正在哪里执行构建过程.总之,如果我有obj-m = a.o
,那么kbuild系统在哪里解析obj-m
并执行gcc a.c
?
But what i'm confused about is where does kbuild system really execute build process.In a word, if i have obj-m = a.o
, then where does kbuild system parse obj-m
and execute gcc a.c
?
推荐答案
Kbuild的Makefile并不是最容易阅读的,但这是一个高级解开(使用4.0-rc3内核):
Kbuild's Makefiles aren't the easiest to read, but here's a high-level untangling (using the 4.0-rc3 kernel):
-
顶级Makefile做
The top-level Makefile does
include $(srctree)/scripts/Kbuild.include
,其中$(srctree)
是顶级内核目录.
, where $(srctree)
is the top-level kernel directory.
Kbuild.include
定义了各种常见的东西和帮手.其中有build
:
Kbuild.include
defines various common stuff and helpers. Among these is build
:
###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
# Usage:
# $(Q)$(MAKE) $(build)=dir
build := -f $(srctree)/scripts/Makefile.build obj
build
与类似$(MAKE) $(build)=dir
的命令一起使用,以执行目录dir
的构建.它使用scripts/Makefile.build
.
build
is used with a command like $(MAKE) $(build)=dir
to perform the build for the directory dir
. It makes use of scripts/Makefile.build
.
返回到顶级Makefile,有以下内容:
Returning to the top-level Makefile, there's the following:
$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
vmlinux-dirs
包含要构建的子目录列表( init , usr ,内核等). $(Q)$(MAKE) $(build)=<subdirectory>
将在每个子目录中运行.
vmlinux-dirs
contains a list of subdirectories to build (init, usr, kernel, etc.). $(Q)$(MAKE) $(build)=<subdirectory>
will be run for each subdirectory.
上面的规则为内核映像和模块编译目标文件.在顶层Makefile中,还有一些其他特定于模块的内容:
The rule above compiles object files for both the kernel image and modules. Further down in the top-level Makefile, there's some additional module-specific stuff:
ifdef CONFIG_MODULES
...
modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
# Do additional module-specific stuff using
# scripts/Makefile.modpost among other things
# (my comment).
...
...
endif # CONFIG_MODULES
现在看一下scripts/Makefile.build
($(build)
使用的Makefile),它首先初始化obj-*
列表和各种其他列表:
Looking into scripts/Makefile.build
(the Makefile used by $(build)
) now, it begins by initializing the obj-*
lists and various other lists:
# Init all relevant variables used in kbuild files so
# 1) they have correct type
# 2) they do not inherit any value from the environment
obj-y :=
obj-m :=
lib-y :=
lib-m :=
再往下一点,它将加载到设置了obj-y
,obj-m
等的Kbuild文件中:
A bit further down, it loads in the Kbuild file where obj-y
, obj-m
, etc., are set:
include $(kbuild-file)
进一步是默认规则,该规则具有$(obj-y)
和$(obj-m)
列表作为先决条件:
Further down is the default rule, which has the $(obj-y)
and $(obj-m)
lists as prerequisites:
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
@:
$(obj-y)
的先决条件来自$(builtin-target)
,其定义如下:
The $(obj-y)
prerequisites come from $(builtin-target)
, which is defined as follows:
builtin-target := $(obj)/built-in.o
...
$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target)
实际的建筑似乎是由以下规则完成的:
The actual building seems to be performed by the following rule:
# Built-in and composite module parts
$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
if_changed_rule
来自Kbuild.include
.该规则最终在Makefile.build
中运行以下命令:
if_changed_rule
is from Kbuild.include
. The rule ends up running the following commands in Makefile.build
:
define rule_cc_o_c
$(call echo-cmd,checksrc) $(cmd_checksrc) \
$(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
...
endef
$(cmd_cc_o_c)
似乎是实际的编译命令.通常的定义(在Makefile.build
中有两种可能性,AFAICS)似乎如下:
$(cmd_cc_o_c)
seems to be the actual compilation command. The usual definition (there are two possibilities in Makefile.build
, AFAICS) seems to be the following:
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
除非使用显式设置make CC=clang
,CC
默认为gcc
,如在顶层Makefile中所示:
Unless set explicitly using e.g. make CC=clang
, CC
defaults to gcc
, as can be seen here in the top-level Makefile:
ifneq ($(CC),)
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
COMPILER := clang
else
COMPILER := gcc
endif
export COMPILER
endif
我要解决的方法是在内核构建过程中执行 CTRL-C ,然后查看make
报告错误的位置.另一种方便的make
调试技术是使用$(warning $(variable))
打印variable
的值.
The way I untangled this was by doing a CTRL-C during a kernel build and seeing where make
reported the error. Another handy make
debugging technique is to use $(warning $(variable))
to print the value of variable
.
这篇关于kbuild实际如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!