首页 > 其他分享 >Kernel Build System

Kernel Build System

时间:2022-12-20 16:01:06浏览次数:61  
标签:Kernel obj Makefile System vmlinux kbuild Build arch Example

#GObject

What is Glib ?

glib库是Linux平台下最常用的C语言函数库,它具有很好的可移植性和实用性。

glib的各种实用程序具有一致的接口。它的编码风格是半面向对象,标识符加了一个前缀“g”,这也是一种通行的命名约定。

使用glib库的程序都应该包含glib的头文件glib.h。如果程序已经包含了gtk.h或gnome.h,则不需要再包含glib.h。

What is Gobiect ?

Gobject , 亦称 Glib 对象系统,是一个程序库,它可以帮助我们使用 C 语言编写面向对象程序。它提供了一个通用的动态类型系统( GType )、一个基本类型的实现集(如整型、枚举等)、一个基本对象类型 - Gobject 、一个信号系统以及一个可扩展的参数 / 变量体系。

GObject 仅依赖于 GLiblibc , 通过它可使用纯 C 语言设计一整套面向对象的软件模块。

Since GStreamer adheres to the GObject programming model, this guide also assumes that you understand the basics of GObject and glib programming. Especially,

  • GObject instantiation
  • GObject properties (set/get)
  • GObject casting
  • GObject referencing/dereferencing
  • glib memory management
  • glib signals and callbacks
  • glib main loop

# Kernel Build System

内核的源码树目录下一般都会有两个文件:Kconfig和Makefile。

分布在各目录下的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录***相关的内核配置菜单。在内核配置make menuconfig(或xconfig等)时,从Kconfig中读出配置菜单,用户配置完后保存到.config(在顶层目录下生成)中。在内核编译时,主Makefile调用这个.config,就知道了用户对内核的配置情况。

上面的内容说明:Kconfig就是对应着内核的配置菜单。假如要想添加新的驱动到内核的源码中,可以通过修改Kconfig来增加对我们驱动的配置菜单,这样就有途径选择我们的驱动,假如想使这个驱动被编译,还要修改该驱动所在目录下的Makefile。

因此,一般添加新的驱动时需要修改的文件有两种(注意不只是两个)

*Kconfig

*Makefile

要想知道怎么修改这两种文件,就要知道两种文档的语法结构。

1、Kconfig Language

config BUILD_AMBARELLA_UNIT_TESTS_CV_FMA

depends on CONFIG_ARCH_CV2

bool "Build FMA unit tests"

default n

select BUILD_AMBARELLA_CAVALRY_MEM_PACKAGE

select BUILD_AMBARELLA_SMARTFB_PACKAGE

select CONFIG_AMBARELLA_FREETYPE_SUPPORT

help

Build Ambarella Private FMA unit tests

type definition: “bool”/”tristate”/”string”/”hex”/”int”

bool "Build FMA unit tests"

and:

bool

prompt "Build FMA unit tests"

input prompt: “prompt” <prompt> [“if” <expr>]

Every menu entry can have at most one prompt, which is used to display to the user. Optionally dependencies only for this prompt can be added with “if”.

default value: “default” <expr> [“if” <expr>]

The default value deliberately defaults to ‘n’ in order to avoid bloating the build.

dependencies: “depends on” <expr>

This defines a dependency for this menu entry. If multiple dependencies are defined, they are connected with ‘&&’. Dependencies are applied to all other options within this menu entry (which also accept an “if” expression), so these two examples are equivalent:

bool "foo" if BUILD_AMBARELLA_UNIT_TESTS_CV_FMA

default y if BUILD_AMBARELLA_UNIT_TESTS_CV_FMA

and:

depends on BUILD_AMBARELLA_UNIT_TESTS_CV_FMA

bool "foo"

default y

reverse dependencies: “select” <symbol> [“if” <expr>]

While normal dependencies reduce the upper limit of a symbol, reverse dependencies can be used to force a lower limit of another symbol. The value of the current menu symbol is used as the minimal value <symbol> can be set to. If <symbol> is selected multiple times, the limit is set to the largest selection. Reverse dependencies can only be used with boolean or tristate symbols.

help text: “help”

2、Kconfig macro language

Concept

基本想法的灵感来自Make。当我们查看Make时,我们注意到两种语言合二为一。一种语言描述了由目标和先决条件组成的依赖关系图。另一种是用于执行文本替换的宏语言。

这两个语言段之间有明显的区别。例如,您可以编写一个makefile文件,如下所示:

APP := foo

SRC := foo.c

CC := gcc

$(APP): $(SRC)

$(CC) -o $(APP) $(SRC)

宏语言将变量引用替换为其扩展形式,并像输入源文件一样进行处理,如下所示:

foo: foo.c

gcc -o foo foo.c

然后,Make 分析依赖关系图并确定要更新的目标。

这个想法在Kconfig中非常相似 - 可以这样描述Kconfig文件:

CC := gcc

config CC_HAS_FOO

def_bool $(shell, $(srctree)/scripts/gcc-check-foo.sh $(CC))

Kconfig 中的宏语言将源文件处理为以下中间文件:

config CC_HAS_FOO

def_bool y

然后,Kconfig 进入评估阶段,以解决符号间依赖关系,如Kconfig Language中所述。

Variables

与 Make 中一样,Kconfig 中的变量充当宏变量。宏变量"“in place "展开以生成一个文本字符串,然后可以进一步展开该字符串。

若要获取变量的值,请将变量名称括在 $( ) 中。即使对于单字母变量名称,括号也是必需的。$X是语法错误。也不支持 ${CC} 中的大括号形式。

有两种类型的变量:简单展开变量递归展开变量

  • 简单展开的变量是使用 := 赋值运算符定义的。从 Kconfig 文件中读取该行后,其右侧会立即展开。
  • 递归扩展变量是使用 = 赋值运算符定义的。它的右侧只是存储为变量的值,而不以任何方式扩展它。而是在使用变量时执行扩展。
  • 还有另一种类型的赋值运算符 += 用于将文本追加到变量。如果 += 的右侧最初被定义为简单变量,则会立即展开右侧。否则,将推迟其评估。

变量引用可以采用以下形式的参数:

$(name,arg1,arg2,arg3)

可以将参数化引用视为一个函数。(更准确地说,"用户定义函数"与下面列出的"内置函数"形成对比)。

使用有用函数时必须展开,因为如果传递了不同的参数,则同一函数的展开方式不同。因此,用户定义函数是使用 = 赋值运算符定义的。参数在正文定义中与 $(1)、$(2) 等一起引用。

实际上,递归扩展变量和用户定义函数在内部是相同的。(换句话说,"变量"是"参数为零的函数"。当我们说广义上的"变量"时,它包括"用户定义的函数"。

Built-in functions

与Make一样,Kconfig提供了几个内置函数。每个函数都采用特定数量的参数。

在 Make 中,每个内置函数至少需要一个参数。Kconfig 允许对内置函数使用零参数,例如$(filename), $(lineno)。你可以把它们看作是"内置变量",但归根结底,这只是我们如何称呼它的问题。这里假设"内置函数"是指本机支持的功能。

Kconfig目前支持以下内置函数。

  • $( shell , command )

    "shell"函数接受单个参数,该参数被展开并传递给子shell进行执行。然后读取命令的标准输出,并将其作为函数的值返回。输出中的每行换行符都替换为空格。任何尾随换行符都将被删除。不会返回标准错误,也不会返回任何程序退出状态。

  • $( info , text )

    "info"函数采用单个参数并将其打印到 stdout。它的计算结果为空字符串。

  • $( warning-if , condition , text )

    "warning-if"函数采用两个参数。如果条件部分是"y",则文本部分将发送到 stderr。该文本以当前 Kconfig 文件的名称和当前行号为前缀。

  • $( error-if , condition , text )

    "error-if"函数类似于"warning-if",但如果条件部分是"y",它会立即终止解析。

  • $( filename )

    "文件名"不带任何参数,$(filename) 扩展为要解析的文件名。

  • $( lineno )

    "lineno"不带任何参数,$(lineno) 扩展为正在解析的行号。

Make vs Kconfig

Kconfig采用类似Make的宏语言,但函数调用语法略有不同。

Make 中的函数调用如下所示:

$(func-name arg1,arg2,arg3)

函数名(func-name)和第一个参数(arg1)之间至少用一个空格分隔。

然后,从第一个参数中修剪前导空格,同时保留其他参数中的空格。您需要使用一种技巧来启动带有空格的第一个参数。例如,如果要使"info"函数打印"hello",则可以这样写:

empty :=

space := $(empty) $(empty)

$(info $(space)$(space)hello)

Kconfig 仅使用逗号作为分隔符,并在函数调用中保留所有空格。有些人喜欢在每个逗号分隔符后放一个空格:

$(func-name, arg1, arg2, arg3)

在这种情况下,"func-name"将接收"arg1","arg2","arg3"。前导空格的存在可能取决于函数。这同样适用于 Make - 例如,$(subst .c, .o, $(sources)) 是一个典型的错误;它将".c"替换为".o"。

在 Make 中,通过使用内置函数"call"来引用用户定义函数,如下所示:

$(call my-func,arg1,arg2,arg3)

Kconfig以相同的方式调用用户定义函数和内置函数。省略"call"使语法更短。

在 Make 中,某些函数逐字处理逗号而不是参数分隔符。

例如,$(shell echo hello, world) 运行命令"echo hello, world"。

同样,$(info hello, world) 将 "hello, world" 打印为 stdout。你可以说这是_useful_ inconsistency。

在 Kconfig 中,为了更简单的实现和语法一致性,出现在 $( ) 这个括号里面的逗号始终是分隔符。这意味着:

$(shell, echo hello, world)

是一个错误,因为它传递了两个参数,其中 "shell" 函数只接受一个参数。要在参数中传递逗号,可以使用以下技巧:

comma := ,

$(shell, echo hello$(comma) world)

Caveats(警告)

变量(或函数)不能跨标记展开。因此,不能将变量用作由多个标记组成的表达式的简写。以下起作用:

RANGE_MIN := 1

RANGE_MAX := 3

config FOO

int "foo"

range $(RANGE_MIN) $(RANGE_MAX)

但是,以下方法不起作用:

RANGES := 1 3

config FOO

int "foo"

range $(RANGES)

变量不能扩展到 Kconfig 中的任何关键字。以下情况不起作用:

MY_TYPE := tristate

config FOO

$(MY_TYPE) "foo"

default y

显然,从设计的角度来看,$(shell command) 在文本替换阶段进行了扩展。不能将符号传递给 "shell" 函数。

以下内容无法按预期工作:

config ENDIAN_FLAG

string

default "-mbig-endian" if CPU_BIG_ENDIAN

default "-mlittle-endian" if CPU_LITTLE_ENDIAN

config CC_HAS_ENDIAN_FLAG

def_bool $(shell $(srctree)/scripts/gcc-check-flag ENDIAN_FLAG)

相反,您可以执行以下操作,以便静态扩展任何函数调用:

config CC_HAS_ENDIAN_FLAG

bool

default $(shell $(srctree)/scripts/gcc-check-flag -mbig-endian) if CPU_BIG_ENDIAN

default $(shell $(srctree)/scripts/gcc-check-flag -mlittle-endian) if CPU_LITTLE_ENDIAN

3、Linux Kernel Makefiles

内核的Makefile分为5个组成部分:

Makefile 最顶层的Makefile

.config 内核的当前配置文档,编译时成为顶层Makefile的一部分

arch/$(ARCH)/Makefile 和体系结构相关的Makefile

s/ Makefile.* 一些Makefile的通用规则

kbuild Makefile 各级目录下的大概约500个文档,编译时根据上层Makefile传下来的宏定义和其他编译规则,将源代码编译成模块或编入内核。

顶层的Makefile文档读取 .config文档的内容,并总体上负责build内核和模块。Arch Makefile则提供补充体系结构相关的信息。 s目录下的Makefile文档包含了任何用来根据kbuild Makefile 构建内核所需的定义和规则。

(其中.config的内容是在make menuconfig的时候,通过Kconfig文档配置的结果)

3 The kbuild files

内核中的大多数Makefiles都是使用 kbuild 基础结构kbuild Makefiles。本章介绍 kbuild Makefiles中使用的语法。kbuild 文件的首选名称是"Makefile",但可以使用"Kbuild",如果同时存在 "Makefile" 和 "Kbuild" 文件,则将使用 "Kbuild" 文件。

第3.1节"目标定义"是一个快速介绍;后面的章节提供了更多细节,并提供了真实的例子。

3.1 Goal definitions

目标定义是 kbuild Makefile 的主要部分(核心)。这些行定义要生成的文件、任何特殊编译选项以及要以递归方式输入的任何子目录。

最简单的 kbuild makefile 包含一行:

Example:

obj-y += foo.o

这告诉 kbuild 该目录中有一个对象,名为 foo.o。foo.o将从foo.c或foo.S构建。

如果 foo.o 应构建为一个模块,则使用变量 obj-m。因此,通常使用以下模式:

Example:

obj-$(CONFIG_FOO) += foo.o

$(CONFIG_FOO) 设置为 y(对于内置)或 m(对于模块)。如果CONFIG_FOO既不是 y 也不是 m,则不会编译链接该文件。

3.2 Built-in object goals - obj-y

kbuild Makefile 在 $(obj-y) 列表中指定 vmlinux 的对象文件。这些列表取决于内核配置。

Kbuild 编译所有 $(obj-y) 文件。然后,它调用"$(AR) rcSTP"将这些文件合并为一个内置文件。这是一个没有符号表的精简存档。它稍后将通过脚本/link-vmlinux.sh 链接到vmlinux中。

$(obj-y) 中文件的顺序非常重要。允许列表中的重复项:第一个实例将链接到内置实例中,后续实例将被忽略。

链接顺序很重要,因为某些函数module_init() / __initcall)将在启动期间按其出现的顺序调用。因此,请记住,更改链接顺序可能会更改检测SCSI控制器的顺序,从而更改磁盘的重新编号。

Example:

#drivers/isdn/i4l/Makefile

# Makefile for the kernel ISDN subsystem and device drivers.

# Each configuration option enables a list of files.

obj-$(CONFIG_ISDN_I4L) += isdn.o ## $(CONFIG_ISDN_I4L)is y or m

obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

3.3 Loadable module goals - obj-m

$(obj-m) 指定作为可加载内核模块构建的对象文件。

一个模块可以从一个源文件或多个源文件构建。对于一个源文件,kbuild makefile 只需将该文件添加到 $(obj-m) 中即可。

Example:

#drivers/isdn/i4l/Makefile

obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

注意:在此示例中,$(CONFIG_ISDN_PPP_BSDCOMP) 被设置为"m"

如果内核模块是从多个源文件构建的,则指定要以与上述相同的方式构建模块;但是,kbuild需要知道要从哪些对象文件构建模块,因此您必须通过设置$(<module_name>-y)变量来告诉它。

Example:

#drivers/isdn/i4l/Makefile

obj-$(CONFIG_ISDN_I4L) += isdn.o ## module_name is isdn

isdn-y := isdn_net_lib.o isdn_v110.o isdn_common.o

在此示例中,模块名称为 isdn.o。Kbuild 将编译 $(isdn-y) 中列出的对象,然后在这些文件的列表上运行 "$(LD) -r" 以生成 isdn.o。

由于 kbuild 可识别复合对象的 $(<module_name>-y),因此可以使用CONFIG_符号的值来选择性地将对象文件作为复合对象的一部分包括在内。

Example:

#fs/ext2/Makefile

obj-$(CONFIG_EXT2_FS) += ext2.o

ext2-y := balloc.o dir.o file.o ialloc.o inode.o ioctl.o \

namei.o super.o symlink.o

ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o \

xattr_trusted.o

## 这样的设置,选择性的将xattr文件作为复合对象的一部分

在此示例中,如果 $(CONFIG_EXT2_FS_XATTR) 设置为 'y',则 xattr.o、xattr_user.o 和 xattr_trusted.o 只是复合对象 ext2.o 的一部分。

注意:当您在内核中构建对象时,当然,上面的语法也可以工作。因此,如果您有CONFIG_EXT2_FS=y,kbuild将为您构建一个ext2.o文件,然后将其链接到内置.a中,如您所料。

3.6 Descending down in directories

Makefile仅负责在其自己的目录中构建对象。子目录中的文件应由这些子目录中的 Makefile 处理。构建系统将自动在子目录中递归调用 make,前提是您让构建系统知道它们。

为此,使用了 obj-y 和 obj-m。ext2 位于一个单独的目录中,fs/ 中存在的 Makefile 告诉 kbuild 使用以下赋值下降。

Example:

#fs/Makefile

obj-$(CONFIG_EXT2_FS) += ext2/ ## 注意这个尾部 斜杠 “/”

如果CONFIG_EXT2_FS设置为"y"(内置)或"m"(模块化),则将设置相应的obj-变量,并且kbuild将在ext2目录中下降。

Kbuild使用这些信息不仅决定它需要访问目录,而且还决定是否将对象从目录链接到vmlinux。当 Kbuild 使用 "y" 下降到目录中时,该目录中的所有内置对象都会合并到内置的.a文件中,最终将链接到 vmlinux 中。

相反,当 Kbuild 使用 "m" 下降到子目录中时,该子目录中的任何内容都不会链接到 vmlinux 中。如果该子目录中的 Makefile 指定了 obj-y,则这些对象将保持为孤立对象。它很可能是Makefile或Kconfig中的依赖关系的错误。

Kbuild 还支持专用语法 subdir-y 和 subdir-m,用于降入子目录。当您知道它们根本不包含内核空间对象时,这是一个很好的选择。一个典型的用法是让 Kbuild 下降到子目录来构建工具。

Examples:

# scripts/Makefile

subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins

subdir-$(CONFIG_MODVERSIONS) += genksyms

subdir-$(CONFIG_SECURITY_SELINUX) += selinux

与 obj-y/m 不同,subdir-y/m 不需要尾部斜杠,因为此语法始终用于目录。

在分配目录名称时,最好使用CONFIG_ variable。这允许 kbuild 完全跳过目录,如果相应的CONFIG_ option既不是'y'也不是'm'。

3.5 Library file goals - lib-y

obj-* 列出的对象用于模块,或组合在特定目录的内置.a 文件中。

还可以将包含在库 lib.a 中的对象列出。

lib-y列出的所有对象都合并到该目录的单个库中。

在 obj-y 中列出的对象和在 lib-y另外列出的对象将不会包含在库中,因为它们无论如何都是可访问的。

为了保持一致性(For consistency),lib-m 中列出的对象将包含在 lib.a 中。

请注意,相同的kbuild makefile可能会列出要内置的文件以及要成为库一部分的文件。因此,同一目录可能同时包含内置文件(built-in.a)和 lib.a 文件。

Example:

#arch/x86/lib/Makefile

lib-y := delay.o

这将创建一个基于 delay.o 的库 lib.a。为了使 kbuild 真正认识到有一个 lib.a 正在构建中,该目录应列在 libs-y 中。

另请参阅"7.4 列出降序时要访问的目录"。

lib-y的使用通常仅限于lib/和arch/*/lib。

3.7 Non-builtin vmlinux targets - extra-y

extra-y 指定了构建 vmlinux 所需的目标,但未合并到built-in.a文件中。

Examples are:

  1. head objects

    有些对象必须放在 vmlinux 的开头。它们直接链接到 vmlinux,而无需经过built-in.a文件。 典型的用例是包含入口点的对象。

    arch/$(SRCARCH)/Makefile 应该指定诸如 head-y 之类的对象。

    讨论:

    既然我们可以控制链接器脚本中的节顺序,为什么我们需要 head-y?

  2. vmlinux linker script

    vmlinux 的链接器脚本位于 arch/$(SRCARCH)/kernel/vmlinux.lds

    Example:

    # arch/x86/kernel/Makefile

    extra-y := head_$(BITS).o

    extra-y += head$(BITS).o

    extra-y += ebda.o

    extra-y += platform-quirks.o

    extra-y += vmlinux.lds

    $(extra-y) 应该只包含 vmlinux 所需的目标。

    Kbuild 跳过了 extra-y,当 vmlinux 显然不是最终目标时。(例如,‘make modules’或building external modules)

    如果您打算无条件地构建目标,则 always-y(将在下一节中介绍)是正确的语法。

3.8 Always built goals - always-y

always-y 指定了在 Kbuild 访问 Makefile 时始终构建的目标。

Example::

# ./Kbuild offsets-file := include/generated/asm-offsets.h always-y += $(offsets-file)

3.9 Compilation flags(编译标志)

  1. ccflags-y 、 asflags-y 、 ldflags-y

    这三个标志仅适用于kbuild makefile,在其中分配它们。它们用于发生在递归构建期间所有正常的 cc,as 和 ld 调用。

    注意:具有相同行为的标志之前已命名为:EXTRA_CFLAGS、EXTRA_AFLAGS和EXTRA_LDFLAGS。它们仍然受支持,但其用法已弃用。

  • ccflags-y 指定使用 $(CC) 进行编译的选项。

    Example:

    # drivers/acpi/acpica/Makefile

    ccflags-y := -Os -D_LINUX -DBUILDING_ACPICA

    ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT

    此变量是必需的,因为顶部的 Makefile 拥有变量 $(KBUILD_CFLAGS),并将其用于整个树的编译标志。

  • asflags-y 指定汇编程序选项。

    Example:

    #arch/sparc/kernel/Makefile

    asflags-y := -ansi

  • ldflags-y 指定用于与 $(LD) 链接的选项。

    Example:

    #arch/cris/boot/compressed/Makefile

    ldflags-y += -T $(srctree)/$(src)/decompress_$(arch-y).lds

  1. subdir-ccflags-y 、 subdir-asflags-y

    The two flags listed above are similar to ccflags-y and asflags-y. The difference is that the subdir- variants have effect for the kbuild file where they are present and all subdirectories. Options specified using subdir-* are added to the commandline before the options specified using the non-subdir variants.

    上面列出的两个标志类似于 ccflags-y 和 asflags-y。

    不同之处在于,subdir- variants对 它存在的和所有子目录所在的 这一个kbuild文件有影响。在使用non-subdir variants指定的选项之前,使用 subdir-* 指定的选项将添加到命令行中。

    Example:

    subdir-ccflags-y := -Werror

  2. ccflags-remove-y 、 asflags-remove-y

    这些标志用于删除编译器、汇编程序调用的特定标志。

    Example:

    ccflags-remove-$(CONFIG_MCOUNT) += -pg

  3. CFLAGS_$@ 、 AFLAGS_$@

    CFLAGS_$@ 和 AFLAGS_$@ 仅应用于当前kbuild makefile中的命令。

  • $(CFLAGS_$@) 指定 $(CC) 的每个文件选项。$@ 部分有一个文本值,该值指定它所针对的文件。

    CFLAGS_$@ 具有比 ccflags-remove-y 更高的优先级;CFLAGS_$@ 可以重新添加被 ccflags-remove-y 删除的编译器标志。

    Example:

    # drivers/scsi/Makefile

    CFLAGS_aha152x.o = -DAHA152X_STAT –DAUTOCONF ## $@ is aha152x.o

    此行指定 aha152x.o 的编译标志。

  • $(AFLAGS_$@) 是汇编语言中源文件的类似功能。

    AFLAGS_$@ 具有比 asflags-remove-y 更高的优先级;AFLAGS_$@ 可以重新添加由 asflags-remove-y 删除的汇编程序标志。

    Example:

    # arch/arm/kernel/Makefile

    AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) ## $@ is head.o

    AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312

    AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt

3.10 Dependency tracking(依赖路径)

Kbuild 路径依赖以下内容:

  1. 所有必备文件(*.c和*.h)

  2. 所有必备文件中使用的CONFIG_选项

  3. 用于编译目标的命令行

    因此,如果将选项更改为 $(CC),则将重新编译所有受影响的文件。

3.11 Custom Rules

当 kbuild 基础结构不提供所需的支持时,将使用自定义规则。一个典型的示例是在生成过程中生成的头文件。另一个示例是特定体系结构的 Makefile,它需要自定义规则来准备启动映像等。

自定义规则按常规编写Make规则。Kbuild 不在 Makefile 所在的目录中执行,因此所有自定义规则都应使用必备文件和目标文件的相对路径。

Two variables are used when defining custom rules(定义自定义规则时使用两个变量):

$(src) 是指向 Makefile 所在目录的相对路径。在引用位于 src 树中的文件时,始终使用 $(src)。

$(obj)是指向保存目标的目录的相对路径。在引用生成的文件时始终使用$(obj)

Example:

#drivers/scsi/Makefile

$(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl

$(CPP) -DCHIP=810 - < $< | ... $(src)/script_asm.pl

这是一个自定义规则,遵循 make 所需的正常语法。

目标文件依赖于两个先决条件文件。对目标文件的引用以 $(obj) 为前缀,对先决条件的引用以 $(src) 引用(因为它们不是生成的文件)。

$(kecho)

在规则中向用户回显信息通常是一种很好的做法,但是当执行"make -s"时,除了警告/错误之外,人们不会期望看到任何输出。为了支持这个 kbuild,定义了 $(kecho),它将回显 $(kecho) 后面的文本到 stdout,除非使用 "make -s"。

Example:

# arch/arm/Makefile

$(BOOT_TARGETS): vmlinux

$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@

@$(kecho) ' Kernel: $(boot)/$@ is ready'

当 kbuild 以 KBUILD_VERBOSE=0 执行时,通常只显示命令的简写。要为自定义命令启用此行为,kbuild 需要设置两个变量:

quiet_cmd_<command> - what shall be echoed

cmd_<command> - the command to execute

Example:

# lib/Makefile

quiet_cmd_crc32 = GEN $@

cmd_crc32 = $< > $@

$(obj)/crc32table.h: $(obj)/gen_crc32table

$(call cmd,crc32)

更新 $(obj)/crc32table.h 目标时,该行:GEN lib/crc32table.h

将显示为"使KBUILD_VERBOSE=0"。

3.12 Command change detection(检测的命令)

评估规则时,将比较目标文件及其必备文件(prerequisite files)之间的时间戳(timestamps)。当任何先决条件更新时,GNU Make更新目标。

自上次调用以来,当命令行已更改时,也应重新生成目标文件。Make本身不支持这一点,因此Kbuild通过一种元编程来实现这一点。

if_changed是用于此目的的宏(macro),形式如下:

quiet_cmd_<command> = ...

cmd_<command> = ...

<target>: <source(s)> FORCE ## 对$(targets) 的赋值没有 $(obj)/ 前缀

$(call if_changed,<command>)

任何利用if_changed的目标都必须列在 $(targets) 中,否则命令行检查将失败,并且将始终生成目标。

如果目标已经列在可识别的语法中,例如obj-y/m,lib-y/m,extra-y/m,always-y/m,hostprogs,userprogs,Kbuild会自动将其添加到$(targets)中。否则,必须将目标显式添加到$(targets)中。

对$(targets) 的赋值没有 $(obj)/ 前缀。if_changed可与"3.11 自定义规则"中定义的自定义规则结合使用。

注意:忘记 FORCE 先决条件是一个典型的错误。另一个常见的陷阱是空格有时很重要;例如,以下操作将失败(请注意逗号后面的额外空格):

target: source(s) FORCE

WRONG! $(call if_changed, objcopy)

Note:

每个目标不应多次使用if_changed。它将执行的命令存储在相应的 .cmd 文件中,当目标为最新且仅对已更改命令的测试触发命令执行时,多次调用将导致覆盖和不需要的结果。

3.13 $(CC) support functions

内核可以使用多个不同版本的 $(CC) 构建,每个版本都支持一组独特的功能和选项。kbuild 提供了基本支持来检查 $(CC) 的有效选项。$(CC) 通常是 gcc 编译器,但也有其他替代方案。

  1. as-option

    as-option 用于检查 $(CC) – 当用于编译汇编程序 (*.S) 文件 – 支持给定的选项。如果第一个选项不受支持,则可以指定可选的第二个选项。

    Example:

    #arch/sh/Makefile ## cflags-y 标识 $(CC)

    cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)

    在上面的示例中,

    如果 cflags-y 受 $(CC) 支持,则将为它分配选项-Wa$(comma)-isa=$(isa-y)。

    第二个参数是可选的,如果提供,则在不支持第一个参数时使用。

  2. as-instr

    as-instr 检查汇编程序是否报告特定指令,然后输出选项 1 或选项 2 测试指令中支持的C 转义。(as-instr checks if the assembler reports a specific instruction and then outputs either option1 or option2 C escapes are supported in the test instruction)

    注意:as-instr-option 对汇编程序选项使用KBUILD_AFLAGS

  3. cc-option

    cc-option 用于检查 $(CC) 是否支持给定选项,以及是否支持使用可选的第二个选项。

    Example:

    #arch/x86/Makefile

    cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)

    在上面的示例中,

    如果由 $(CC) 支持,则 cflags-y 将被分配选项 -march=pentium-mmx,

    否则 -march=i586。

    cc-option 的第二个参数是可选的,如果省略,则在不支持第一个选项的情况下,cflags-y 将不被分配任何值。

    注意:cc 选项使用 $(CC) 选项的KBUILD_CFLAGS

  4. cc-option-yn

    cc-option-yn 用于检查 gcc 是否支持给定的选项,如果支持,则返回"y",否则返回"n"。

    Example:

    #arch/ppc/Makefile

    biarch := $(call cc-option-yn, -m32)

    aflags-$(biarch) += -a32

    cflags-$(biarch) += -m32

    在上面的示例中,如果 $(CC) 支持 -m32 选项,则 $(biarch) 设置为 y。当 $(biarch) 等于 'y' 时,扩展变量 $(aflags-y) 和 $(cflags-y) 将分别分配值 -a32 和 -m32。注意:cc-option-yn 使用 KBUILD_CFLAGS $(CC) 选项

  5. cc-disable-warning

    cc-disable-warning 检查 gcc 是否支持给定的警告,并返回命令行开关以禁用它。此特殊函数是必需的,因为 gcc 4.4 及更高版本接受任何未知的 -Wno-* 选项,并且仅在源文件中有其他警告时才发出警告。

    Example:

    KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)

    在上面的示例中,只有当 gcc 真正接受 -Wno-unused-but-set-变量时,才会将其添加到KBUILD_CFLAGS。

  6. cc-ifversion

    cc-ifversion 测试 $(CC) 的版本,如果版本表达式为真,则等于第四个参数;如果版本表达式为 false,则等于第五个参数(如果给定)。

    Example:

    #fs/reiserfs/Makefile

    ccflags-y := $(call cc-ifversion, -lt, 0402, -O1)

    在此示例中,如果 $(CC) 版本小于 4.2,则 ccflags-y 将被分配值 -O1。

    cc-ifversion 采用所有 shell 运算符:-eq、-ne、-lt、-le、-gt 和 -ge 第三个参数可能是文本,如本例所示,但它也可能是扩展变量或宏。

  7. cc-cross-prefix

    cc-cross-prefix用于检查所列前缀之一的路径中是否存在$(CC)。返回存在PATH 中的第一个$(CC)的前缀- 如果未找到$(CC)前缀,则不返回任何内容。

    其它前缀在调用cc-cross-prefix时由单个空格分隔。此功能对于尝试将CROSS_COMPILE设置为已知值,但可能具有多个值可供选择的Makefile体系结构非常有用。建议仅尝试设置CROSS_COMPILE如果它是交叉构建(主机拱与目标拱不同)。如果已经设置了CROSS_COMPILE,则将其保留为旧值。

    Example:

    #arch/m68k/Makefile

    ifneq ($(SUBARCH),$(ARCH))

    ifeq ($(CROSS_COMPILE),)

    CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu-)

    endif

    endif

3.14 $(LD) support functions

ld-option

ld-option 用于检查 $(LD) 是否支持提供的选项。ld-option 采用两个选项作为参数。第二个参数是可选选项,如果 $(LD) 不支持第一个选项,则可以使用该选项。

Example:

#Makefile

LDFLAGS_vmlinux += $(call ld-option, -X)

3.15 Script invocation

制定规则可以调用脚本来构建内核。规则应始终提供适当的解释器来执行脚本。它们不应依赖于所设置的执行位,也不应直接调用脚本。为了方便手动调用脚本,例如调用 ./scripts/checkpatch.pl,建议在脚本上设置执行位。

Kbuild 提供了变量 $(CONFIG_SHELL)、$(AWK)、$(PERL) 和 $(PYTHON3)来引用相应脚本的解释器。

Example:

#Makefile

cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \

$(KERNELRELEASE)

4 Host Program support(程序支持)

Kbuild 支持在host上构建可执行文件,以便在编译阶段使用。若要使用host可执行文件,需要执行两个步骤。

第一步是告诉 kbuild 存在host程序。可以利用"hostprogs"变量完成。

第二步是向可执行文件添加显式依赖项。这一步可以通过两种方式完成,一是在规则中添加依赖项,二是使用变量"always-y"。下面将介绍这两种可能性。

4.1 Simple Host Program

在某些情况下,需要在已经构建运行的计算机上编译和运行程序。以下一行代码告诉 kbuild ,bin2hex程序应该构建在build host上。

Example:

hostprogs := bin2hex

在上面的示例中,Kbuild 假定 bin2hex 是由一个名为 bin2hex.c 的c源文件构成的。该c源文件文件位于与 Makefile同一目录中。

4.2 Composite Host Programs(复合的Host程序)

host程序可以由多个对象组合而成。定义复合对象的host程序语法 和 定义内核对象的语法类似。$(<executable>-objs) 列出了所有用于链接最终可执行文件的对象。

Example:

#scripts/lxdialog/Makefile

hostprogs := lxdialog # 告诉 kbuild ,在build host上构建lxdialog

lxdialog-objs := checklist.o lxdialog.o # lxdialog 依赖两个可执行文件

扩展名为 .o 的对象是从相应的.c文件编译而来的。在上面的示例中,checklist.c编译为replenge.o,lxdialog.c编译为lxdialog.o。最后,两个 .o 文件链接到可执行文件 lxdialog。

注: host程序不允许使用<executable>-y 语法。

4.3 Using C++ for host programs

kbuild 为用C++编写的主机程序提供支持。这仅用于支持 kconfig,不建议用于一般用途。

Example:

#scripts/kconfig/Makefile

hostprogs := qconf

qconf-cxxobjs := qconf.o

在上面的示例中,可执行文件由C++文件 qconf.cc 组成 。 qconf.cc由 $(qconf-cxxobjs) 标识。

如果 qconf 由 .c 和 .cc 文件的混合组成,则可以使用额外的一行来标识它。

Example:

#scripts/kconfig/Makefile

hostprogs := qconf ## 告知kbuild有host程序qconf, qconf由下面程序混合组成

qconf-cxxobjs := qconf.o

qconf-objs := check.o

4.4 Controlling compiler options for host programs

编译host程序时,可以设置特定的标志

通过指定$(KBUILD_HOSTCFLAGS) 中的选项,使用 $(HOSTCC),程序将始终被进行编译。

通过使用变量HOST_EXTRACFLAGS设置标志将对所有创建在Makefile中的host程序产生作用。

Example:

#scripts/lxdialog/Makefile

HOST_EXTRACFLAGS += -I/usr/include/ncurses

若要为单个文件设置特定标志,请使用以下构造:

Example:

#arch/ppc64/boot/Makefile

HOSTCFLAGS_piggyback.o := -DKERNELBASE=$(KERNELBASE)

还可以为链接器指定其他选项。

Example:

#scripts/kconfig/Makefile

HOSTLDLIBS_qconf := -L$(QTDIR)/lib

当链接qconf时,它将传递额外的选项"-L$(QTDIR)/lib"。

4.5 When host programs are actually built

Kbuild 只会在host程序作为先决条件引用时才构建host程序。这可以通过两种方式实现列出先决条件:

1、在自定义规则(custom rule)中显式列出先决条件(prerequisite)。

Example:

#drivers/pci/Makefile

hostprogs := gen-devlist

$(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist

( cd $(obj); ./gen-devlist ) < $<

在更新 $(obj)/gen-devlist之前,不会构建目标 $(obj)/gen-devlist.h。

请注意,自定义规则中对host程序的引用必须以 $(obj) 为前缀。

2、Use always-y

当没有合适的自定义规则,并且在输入makefile时应构建host程序时,应使用always-y变量。

Example:

#scripts/lxdialog/Makefile

hostprogs := lxdialog

always-y := $(hostprogs)

Kbuild为此提供了以下简写(shorthand):

hostprogs-always-y := lxdialog

这将告诉 kbuild 构建 lxdialog,即使未在任何规则中引用。

5 Userspace Program support

就像host程序一样,Kbuild也支持为目标架构构建用户空间可执行文件(即与构建内核相同的架构)。

语法非常相似。不同之处在于使用"userprogs"而不是"hostprogs"

5.1 Simple Userspace Program

下面的一行告诉 kbuild,程序bpf-direct应该是为目标体系结构构建的。

Example:

userprogs := bpf-direct

在上面的示例中,Kbuild 假定 bpf-direct 是由一个名为 bpf-direct 的 C 源文件创建的 。c文件位于与 Makefile 位于同一目录中。

5.2 Composite Userspace Programs

userspace程序可以基于复合对象组成。用于为userspace程序定义复合对象的语法类似于用于内核对象的语法。$(<executable>-objs) 列出了用于链接最终可执行文件的所有对象。

Example:

#samples/seccomp/Makefile

userprogs := bpf-fancy

bpf-fancy-objs := bpf-fancy.o bpf-helper.o

扩展名为 .o 的对象是从相应的.c文件编译而来的。在上面的示例中,bpf-fancy.c 编译为 bpf-fancy.o 和 bpf-helper.c编译为 bpf-helper.o。最后,两个 .o 文件链接到可执行文件 bpf-fancy。

注: 用户空间程序不允许使用语法< executable >-y。

5.3 Controlling compiler options for userspace programs

When compiling userspace programs, it is possible to set specific flags. The programs will always be compiled utilising $(CC) passed the options specified in $(KBUILD_USERCFLAGS). To set flags that will take effect for all userspace programs created in that Makefile, use the variable userccflags.

编译用户空间程序时,可以设置特定的标志。这些程序将始终使用 $(CC) 通过 $(KBUILD_USERCFLAGS 中指定的选项 进行编译。请使用变量 userccflags对在该 Makefile 中创建的所有userapace程序生效的标志进行设置。

Example:

# samples/seccomp/Makefile

userccflags += -I usr/include

若要为单个文件设置特定标志,请使用以下构造:

Example:

bpf-helper-userccflags += -I user/include

还可以为linker指定其他选项。

Example:

# net/bpfilter/Makefile

bpfilter_umh-userldflags += -static

When linking bpfilter_umh, it will be passed the extra option -static.

链接bpfilter_umh时,它将被额外的选项 -static传递。

5.4 When userspace programs are actually built

Kbuild只有在被告知这样做时才会构建用户空间程序。有两种方法可以做到这一点。

  1. 将其添加为另一个文件的先决条件

    Example:

    #net/bpfilter/Makefile

    userprogs := bpfilter_umh

    $(obj)/bpfilter_umh_blob.o: $(obj)/bpfilter_umh

    $(obj)/bpfilter_umh 是在 $(obj)/bpfilter_umh_blob.o 之前构建的

  2. Use always-y

    Example:

    userprogs := binderfs_example

    always-y := $(userprogs)

    Kbuild为此提供了以下简写:

    userprogs-always-y := binderfs_example

    这将告诉 Kbuild 在访问此 Makefile 时构建binderfs_example。

6 Kbuild clean infrastructure

"make clean"会删除编译内核的 obj 树中生成的大部分文件。这包括生成的文件,如host程序。Kbuild 知道 $(hostprogs)、$(always-y)、$(always-m)、$(always-)、$(extra-y)、$(extra-)和 $(targets)中列出的目标。它们在"清理"期间全部被删除。与模式匹配的文件".[oas]", ".ko",以及kbuild生成的一些其他文件在执行"make clean"时会在整个内核源代码树中删除。

可以使用 $(clean-files) 在 kbuild 生成文件中指定其他文件或目录。

Example:

#lib/Makefile

clean-files := crc32table.h

执行"make clean"时,文件"crc32table.h"将被删除。Kbuild 将假定文件与 Makefile 位于同一相对目录中,除非前缀为 $(objtree)。

若要从 make clean 中排除某些文件或目录,请使用 $(no-clean-files) 变量。

通常,由于"obj-* := dir/",kbuild下降到子目录中,但是有时候在kbuild infrastructure不支持的架构Makefile文件中,这需要显式。

Example:

#arch/x86/boot/Makefile

subdir- := compressed

上面的分配指示 kbuild 在执行"make clean"时下降到压缩目录中。

注1:arch/$(SRCARCH)/Makefile不能使用"subdir-",因为该文件包含在顶级makefile中。相反,arch/$(SRCARCH)/Kbuild 可以使用 "subdir-"。

注2:在"清理"期间,将访问core-y,libs-y,drivers-y和net-y中列出的所有目录。

7 Architecture Makefiles

顶级 Makefile 设置环境并执行准备工作,然后开始在各个目录中向下移动。顶层 makefile 包含通用部分,而 arch/$(SRCARCH)/Makefile 包含为所述体系结构设置 kbuild 所需的内容。为此,arch/$(SRCARCH)/Makefile 设置了许多变量并定义了几个目标。

当 kbuild 执行时,将执行以下步骤(大致):

  1. 内核的配置 = >生成 .config
  2. 将内核版本存储在 include/linux/version.h
  3. 将所有其他先决条件更新到目标准备: - 在 arch/$(SRCARCH)/Makefile 中指定了其他先决条件
  4. 在 init-* core* drivers-* net-* libs-* 中列出的所有目录中递归下降,并构建所有目标。- 上述变量的值在 arch/$(SRCARCH)/Makefile 中展开。
  5. 然后链接所有对象文件,生成的文件 vmlinux 位于 obj 树的根目录下。链接的第一批对象以 head-y 列出,由 arch/$(SRCARCH)/Makefile 指定。
  6. 最后,特定于体系结构的部分执行任何必需的后处理并构建最终的引导映像。- 这包括构建引导记录 - 准备 initrd 映像等

7.1 Set variables to tweak the build to the architecture

(设置变量以根据体系结构调整构建)

  • KBUILD_LDFLAGS

    通用 $(LD) 选项(Generic $(LD) options)

    用于链接器的所有调用的标志。通常指定仿真就足够了。

    Example:

    #arch/s390/Makefile

    KBUILD_LDFLAGS := -m elf_s390

    注意:ldflags-y 可用于进一步自定义所使用的标志。请参阅第 3.9 节。

  • LDFLAGS_vmlinux

    链接 vmlinux 时的 $(LD) 选项

    LDFLAGS_vmlinux用于指定在链接最终 vmlinux 映像时传递给链接器的其他标志。LDFLAGS_vmlinux使用 LDFLAGS_$@ 支持。

    Example:

    #arch/x86/Makefile

    LDFLAGS_vmlinux := -e stext

  • OBJCOPYFLAGS

    objcopy 标志

    当 $(call if_changed,objcopy) 用于翻译 .o 文件时,将使用 OBJCOPYFLAGS 中指定的标志。$(call if_changed,objcopy)通常用于在vmlinux上生成原始二进制文件。

    Example:

    #arch/s390/Makefile

    OBJCOPYFLAGS := -O binary

    #arch/s390/boot/Makefile

    $(obj)/image: vmlinux FORCE

    $(call if_changed,objcopy)

    在此示例中,二进制 $(obj)/image 是 vmlinux 的二进制版本。

    $(call if_changed,xxx)的用法将在后面描述。

  • KBUILD_AFLAGS

    汇编程序标志(Assembler flags)

    默认值 - 请参阅顶层 Makefile 根据体系结构的要求追加或修改。

    Example:

    #arch/sparc64/Makefile

    KBUILD_AFLAGS += -m64 -mcpu=ultrasparc

  • KBUILD_CFLAGS

    $(CC) 编译器标志

    默认值 - 请参阅顶层 Makefile 根据体系结构的要求追加或修改。

    通常,KBUILD_CFLAGS变量取决于配置。

    Example:

    #arch/x86/boot/compressed/Makefile

    cflags-$(CONFIG_X86_32) := -march=i386

    cflags-$(CONFIG_X86_64) := -mcmodel=small

    KBUILD_CFLAGS += $(cflags-y)

    许多 arch Makefile 动态运行目标 C 编译器来探测支持的选项:

    #arch/x86/Makefile

    ...

    cflags-$(CONFIG_MPENTIUMII) += $(call cc-option,\

    -march=pentium2,-march=i686)

    ...

    # Disable unit-at-a-time mode ...

    KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time)

    ...

    第一个示例使用了配置选项在选中时扩展为"y"的技巧。

  • KBUILD_AFLAGS_KERNEL

    Assembler options(汇编程序选项) specific for built-in

    $(KBUILD_AFLAGS_KERNEL) contains extra C compiler flags used to compile resident kernel code.

  • KBUILD_AFLAGS_MODULE

    Assembler options(汇编程序选项) specific for modules

    $(KBUILD_AFLAGS_MODULE) is used to add arch-specific options that are used for assembler.

    From commandline AFLAGS_MODULE shall be used (see Kbuild).

  • KBUILD_CFLAGS_KERNEL

    $(CC) options specific for built-in

    $(KBUILD_CFLAGS_KERNEL) contains extra C compiler flags used to compile resident kernel code.

  • KBUILD_CFLAGS_MODULE

    Options for $(CC) when building modules

    $(KBUILD_CFLAGS_MODULE) is used to add arch-specific options that are used for $(CC). From commandline CFLAGS_MODULE shall be used (see Kbuild).

  • KBUILD_LDFLAGS_MODULE

    Options for $(LD) when linking modules

    $(KBUILD_LDFLAGS_MODULE) is used to add arch-specific options used when linking modules. This is often a linker script.

    From commandline LDFLAGS_MODULE shall be used (see Kbuild).

  • KBUILD_LDS

    The linker script with full path. Assigned by the top-level Makefile.

  • KBUILD_LDS_MODULE

    The module linker script with full path. Assigned by the top-level Makefile and additionally by the arch Makefile.

  • KBUILD_VMLINUX_OBJS

    All object files for vmlinux. They are linked to vmlinux in the same order as listed in KBUILD_VMLINUX_OBJS.

  • KBUILD_VMLINUX_LIBS

    All .a “lib” files for vmlinux. KBUILD_VMLINUX_OBJS and KBUILD_VMLINUX_LIBS together specify all the object files used to link vmlinux.

7.2 Add prerequisites to archheaders

archheaders: rule 用于生成头文件,这些文件可以通过"make header_install"安装到用户空间中。

在架构本身上运行时,它会在"make archprepare"之前运行。

7.3 Add prerequisites to archprepare

archprepare: 规则用于列出在子目录中开始向下下降之前需要构建的先决条件。这通常用于包含汇编程序常量的头文件。

Example:

#arch/arm/Makefile

archprepare: maketools

在此示例中,将处理文件目标 maketools,然后再在子目录中向下下载。另请参阅第 XXX-TODO 章,其中介绍了 kbuild 如何支持生成偏移头文件。

列出降序时要访问的目录(List directories to visit when descending)

arch Makefile 与顶部的 Makefile 合作,定义指定如何构建 vmlinux 文件的变量。请注意,模块没有相应的arch-specific 的部分;模块构建机器完全独立于架构。

head-y 、 core-y 、 libs-y 、 drivers-y

$(head-y) 列出了在 vmlinux 中首先要链接的对象。

$(libs-y) 列出了 lib.a 存档所在的目录。

其余部分列出了可在其中找到built-in.a 对象文件的目录。

然后,其余部分按以下顺序进行:

$(core-y), $(libs-y), $(drivers-y)

顶级 Makefile 定义所有泛型目录的值,而 arch/$(SRCARCH)/Makefile 仅添加特定于体系结构的目录。

Example:

# arch/sparc/Makefile

core-y += arch/sparc/

libs-y += arch/sparc/prom/

libs-y += arch/sparc/lib/

drivers-$(CONFIG_PM) += arch/sparc/power/

7.5特定体系结构的启动映像(Architecture-specific boot images)

arch Makefile 指定了获取 vmlinux 文件、压缩文件、将其包装在引导代码中并将生成的文件复制到某个位置的目标。这包括各种安装命令。实际目标没有跨体系结构标准化。

通常将任何其它处理程序放在 arch/$(SRCARCH)/ 下面的boot/ 下的目录中。

Kbuild 不提供任何智能方法来支持构建在 boot/ 中指定的目标。因此,arch/$(SRCARCH)/Makefile 应手动调用 make 以在 boot/ 中构建目标。

推荐的方法是在 arch/$(SRCARCH)/Makefile 中包含快捷方式,并在向下调用 arch/$(SRCARCH)/boot/Makefile 时使用完整路径。

Example:

#arch/x86/Makefile

boot := arch/x86/boot

bzImage: vmlinux

$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

"$(Q)$(MAKE) $(build)=<dir>"是在子目录中调用 make 的推荐方法。

没有用于命名特定体系结构的目标的规则,但执行“make help”将列出所有相关目标。为了支持这一点,必须定义 $(archhelp)

Example:

#arch/x86/Makefile

define archhelp

echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'

endif

当在没有参数的情况下执行 make 时,将构建遇到的第一个目标。在顶级 Makefile 中,存在的第一个目标是 all:。

向 all 添加新的先决条件:选择与 vmlinux 不同的默认目标。

默认情况下,体系结构应始终生成可启动映像。在" make help "中,默认目标以"*"突出显示。

Example:

#arch/x86/Makefile

all: bzImage

当"make"在没有参数的情况下执行时,将构建bzImage。

7.7 Commands useful for building a boot image

Kbuild provides a few macros that are useful when building a boot image.

ld

Link target. Often, LDFLAGS_$@ is used to set specific options to ld.

Example:

#arch/x86/boot/Makefile

LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary

LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext

targets += setup setup.o bootsect bootsect.o

$(obj)/setup $(obj)/bootsect: %: %.o FORCE

$(call if_changed,ld)

In this example, there are two possible targets, requiring different options to the linker. The linker options are specified using the LDFLAGS_$@ syntax - one for each potential target. $(targets) are assigned all potential targets, by which kbuild knows the targets and will:

  1. check for commandline changes

  2. delete target during make clean

    The “: %: %.o” part of the prerequisite is a shorthand that frees us from listing the setup.o and bootsect.o files.

    Note:

    It is a common mistake to forget the “targets :=” assignment, resulting in the target file being recompiled for no obvious reason.

    objcopy

    Copy binary. Uses OBJCOPYFLAGS usually specified in arch/$(SRCARCH)/Makefile. OBJCOPYFLAGS_$@ may be used to set additional options.

    gzip

    Compress target. Use maximum compression to compress target.

    Example:

    #arch/x86/boot/compressed/Makefile

    $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE

    $(call if_changed,gzip)

    dtc

    Create flattened device tree blob object suitable for linking into vmlinux. Device tree blobs linked into vmlinux are placed in an init section in the image. Platform code must copy the blob to non-init memory prior to calling unflatten_device_tree().

    To use this command, simply add *.dtb into obj-y or targets, or make some other target depend on %.dtb

    A central rule exists to create $(obj)/%.dtb from $(src)/%.dts; architecture Makefiles do no need to explicitly write out that rule.

    Example:

    targets += $(dtb-y)

    DTC_FLAGS ?= -p 1024

7.9 Preprocessing linker scripts

When the vmlinux image is built, the linker script arch/$(SRCARCH)/kernel/vmlinux.lds is used. The script is a preprocessed variant of the file vmlinux.lds.S located in the same directory. kbuild knows .lds files and includes a rule *lds.S -> *lds.

Example:

#arch/x86/kernel/Makefile

extra-y := vmlinux.lds

The assignment to extra-y is used to tell kbuild to build the target vmlinux.lds. The assignment to $(CPPFLAGS_vmlinux.lds) tells kbuild to use the specified options when building the target vmlinux.lds.

When building the *.lds target, kbuild uses the variables:

KBUILD_CPPFLAGS : Set in top-level Makefile

cppflags-y : May be set in the kbuild makefile

CPPFLAGS_$(@F) : Target-specific flags.

Note that the full filename is used in this

assignment.

The kbuild infrastructure for *lds files is used in several architecture-specific files.

7.10 Generic header files

The directory include/asm-generic contains the header files that may be shared between individual architectures. The recommended approach how to use a generic header file is to list the file in the Kbuild file. See “8.2 generic-y” for further info on syntax etc.

7.11 Post-link pass

If the file arch/xxx/Makefile.postlink exists, this makefile will be invoked for post-link objects (vmlinux and modules.ko) for architectures to run post-link passes on. Must also handle the clean target.

This pass runs after kallsyms generation. If the architecture needs to modify symbol locations, rather than manipulate the kallsyms, it may be easier to add another postlink target for .tmp_vmlinux? targets to be called from link-vmlinux.sh.

For example, powerpc uses this to check relocation sanity of the linked vmlinux file.

8 Kbuild syntax for exported headers

The kernel includes a set of headers that is exported to userspace. Many headers can be exported as-is but other headers require a minimal pre-processing before they are ready for user-space. The pre-processing does:

  • drop kernel-specific annotations

  • drop include of compiler.h

  • drop all sections that are kernel internal (guarded by ifdef _KERNEL_)

    All headers under include/uapi/, include/generated/uapi/, arch/<arch>/include/uapi/ and arch/<arch>/include/generated/uapi/ are exported.

    A Kbuild file may be defined under arch/<arch>/include/uapi/asm/ and arch/<arch>/include/asm/ to list asm files coming from asm-generic. See subsequent chapter for the syntax of the Kbuild file.

8.1 no-export-headers

no-export-headers is essentially used by include/uapi/linux/Kbuild to avoid exporting specific headers (e.g. kvm.h) on architectures that do not support it. It should be avoided as much as possible.

8.2 generic-y

If an architecture uses a verbatim copy of a header from include/asm-generic then this is listed in the file arch/$(SRCARCH)/include/asm/Kbuild like this:

Example:

#arch/x86/include/asm/Kbuild

generic-y += termios.h

generic-y += rtc.h

During the prepare phase of the build a wrapper include file is generated in the directory:

arch/$(SRCARCH)/include/generated/asm

When a header is exported where the architecture uses the generic header a similar wrapper is generated as part of the set of exported headers in the directory:

usr/include/asm

The generated wrapper will in both cases look like the following:

Example: termios.h:

#include <asm-generic/termios.h>

8.3 generated-y

If an architecture generates other header files alongside generic-y wrappers, generated-y specifies them.

This prevents them being treated as stale asm-generic wrappers and removed.

Example:

#arch/x86/include/asm/Kbuild

generated-y += syscalls_32.h

8.4 mandatory-y

mandatory-y is essentially used by include/(uapi/)asm-generic/Kbuild to define the minimum set of ASM headers that all architectures must have.

This works like optional generic-y. If a mandatory header is missing in arch/$(SRCARCH)/include/(uapi/)/asm, Kbuild will automatically generate a wrapper of the asm-generic one.

9 Kbuild Variables

The top Makefile exports the following variables:

VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION

These variables define the current kernel version. A few arch Makefiles actually use these values directly; they should use $(KERNELRELEASE) instead.

$(VERSION), $(PATCHLEVEL), and $(SUBLEVEL) define the basic three-part version number, such as “2”, “4”, and “0”. These three values are always numeric.

$(EXTRAVERSION) defines an even tinier sublevel for pre-patches or additional patches. It is usually some non-numeric string such as “-pre4”, and is often blank.

KERNELRELEASE

$(KERNELRELEASE) is a single string such as “2.4.0-pre4”, suitable for constructing installation directory names or showing in version strings. Some arch Makefiles use it for this purpose.

ARCH

This variable defines the target architecture, such as “i386”, “arm”, or “sparc”. Some kbuild Makefiles test $(ARCH) to determine which files to compile.

By default, the top Makefile sets $(ARCH) to be the same as the host system architecture. For a cross build, a user may override the value of $(ARCH) on the command line:

make ARCH=m68k ...

SRCARCH

This variable specifies the directory in arch/ to build.

ARCH and SRCARCH may not necessarily match. A couple of arch directories are biarch, that is, a single arch/*/ directory supports both 32-bit and 64-bit.

For example, you can pass in ARCH=i386, ARCH=x86_64, or ARCH=x86. For all of them, SRCARCH=x86 because arch/x86/ supports both i386 and x86_64.

INSTALL_PATH

This variable defines a place for the arch Makefiles to install the resident kernel image and System.map file. Use this for architecture-specific install targets.

INSTALL_MOD_PATH, MODLIB

$(INSTALL_MOD_PATH) specifies a prefix to $(MODLIB) for module installation. This variable is not defined in the Makefile but may be passed in by the user if desired.

$(MODLIB) specifies the directory for module installation. The top Makefile defines $(MODLIB) to $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE). The user may override this value on the command line if desired.

INSTALL_MOD_STRIP

If this variable is specified, it will cause modules to be stripped after they are installed. If INSTALL_MOD_STRIP is ‘1’, then the default option –strip-debug will be used. Otherwise, the INSTALL_MOD_STRIP value will be used as the option(s) to the strip command.

标签:Kernel,obj,Makefile,System,vmlinux,kbuild,Build,arch,Example
From: https://www.cnblogs.com/Bruce-blog/p/16994370.html

相关文章

  • os.system调用命令
    20221220使用python调用系统命令的时候需要用到os.system。具体用法是:os.system(cmd_string)参考:[1]https://www.cnblogs.com/liuhaidon/p/12077007.html......
  • itop3588开发板编译Debian-编译kernel
    在linux源码目录下输入以下命令编译Kernel./build.shkernel内核编译完如下图所示:编译完成后映像文件会打包成boot.img放到kernel目录。如下图所示更多内容可以......
  • new SqlSessionFactoryBuilder().build(inputStream, properties)
    SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream,properties);publicXMLConfigBuilder(InputStreaminputStream,Stringenvir......
  • StringBuilder和StringBuffer的区别以及衍生题目
    StringBuilder和StringBuffer的区别为什么StringBuffer是线程安全的?StringBuffer在单机环境下线程安全吗?为什么?StringBuffer在多机环境下线程安全吗?为什么?StringBuffer......
  • ArcGIS操作之Model Builder
    “按属性选择”的的使用技巧与方法说明:地理数据大多是海量数据,如何在海量数据中获得我们感兴趣的呢?我们通常会使用属性表的“按属性选择”选项卡,如下图:  那这个“按......
  • kubebuilder安装
    注意:go版本和kubebuilder版本需要兼容如下goenv参数一定要修改CGO_ENABLED="0"GO111MODULE="on"本机环境centos7.9amd64,go1.17和kubebuilderv3.4.1......
  • buildroot make 的时候出现 You seem to have the current working directory in your
    问题现象:在buildrootmake的时候,出现以下的提示:YouseemtohavethecurrentworkingdirectoryinyourLD_LIBRARY_PATHenvironmentvariable.Thisdoesn'twork......
  • 问题解决系列:NameError: name 'platform_system' is not defined
    问题场景使用 ​​pip​​​安装依赖的时候,更新之后,更新的依赖不能用。比如我将机器的​​ansible​​​版本指定安装​​2.7.11​​​版本,安装成功之后,使用命令​​ansible......
  • FileSystem
     Linux文件系统、磁盘I/O是怎么工作的......
  • Robot Framework使用OperatingSystem内置库执行dos命令
    OperatingSystem是内置库,可以直接导入使用,不需要单独安装。***Settings***LibraryOperatingSystem***TestCases***exec_bat${ret}Operatin......