Kbuild文件

3 Kbuild文件

大部分内核中的Makefile都是使用Kbuild组织结构的Kbuild Makefile。这章将介绍Kbuild Makefile的语法。

对于Kbuild文件名来讲,Kbuild编译系统更倾向于使用"Makefile"这个名字,当然"Kbuild"也是可以用的。但如果"Makefile"和"Kbuild"同时存在的话,Kbuild编译系统使用的将会是"Kbuild"文件。

3.1节将是对目标定义的一个快速介绍,以后的几章会提供更详细的内容以及实例。

3.1 目标定义

目标定义是Kbuild Makefile的主要部分,也是核心部分。主要是定义了要编译的文件,所有的选项,以及到哪些子目录去执行递归操作。

最简单的Kbuild makefile 只包含一行:

例子:

obj-y += foo.o

该例子告诉Kbuild:在这目录里,有一个名为foo.o的目标文件。foo.o将从foo.c或foo.S文件编译得到。

如果foo.o要编译成一模块,那就要用obj-m了。所采用的形式如下:

例子:

obj-$(CONFIG_FOO) += foo.o

$(CONFIG_FOO)可以为y(编译进内核) 或m(编译成模块)。如果CONFIG_FOO既不是y又不是m,那么该文件就不会被编译链接了。

3.2 编译进内核 -- obj-y

Kbuild Makefile 规定所有编译进内核的目标文件都在$(obj-y)列表中。而这些列表依赖内核的配置(.config)。

Kbuild编译所有的$(obj-y)文件。然后,调用"$(LD) -r"将它们合并到一个build-in.o文件中。稍后,该build-in.o会被其父Makefile链接进vmlinux中。

$(obj-y)列表中的文件是有顺序讲究的。而且$(obj-y)列表中可以有重复项:但是当第一个文件被链接到built-in.o中后,其余重复的文件就被忽略了。

链接目标这个动作也是有顺序的,因为有些函数,例如module_init()/__initcall,将会在启动时按照他们出现的顺序被调用。所以,记住改变链接的顺序可能改变你SCSI控制器的检测顺序,从而导致你的硬盘数据损害。

例子:

# drivers/isdn/i4l/Makefile

# Makefile for the kernel ISDN subsystem and device drivers.

# Each configuration option enables a list of files.

obj-$(CONFIG_ISDN)        += isdn.o

obj-$(CONFIG_ISDN_PPP_BSDCOMP)    += isdn_bsdcomp.o

3.3 编译可装载模块 -- obj-m

$(obj-m) 列举出了哪些文件要编译成可装载模块。

一个模块可以由一个文件或多个文件编译而成。如果是一个源文件,Kbuild Makefile只需简单的将其加到$(obj-m)中去就可以了。

例子:

# drivers/isdn/i4l/Makefile

obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

注意:此例中 $(CONFIG_ISDN_PPP_BSDCOMP) 的值为‘m‘

如果内核模块是由多个源文件编译而成,那你就要采用上面那个例子一样的方法去声明你所要编译的模块。

Kbuild系统需要知道你所编译的模块是基于哪些文件,所以你需要通过变量:

$(<module_name>-objs)

来告诉它。

例子:

#drivers/isdn/i4l/Makefile

obj-$(CONFIG_ISDN) += isdn.o

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

在这个例子中,模块名是isdn.o,Kbuild将对$(isdn-objs)中列出的所有文件进行编译,然后使用"$(LD) -r"生成isdn.o。

Kbuild recognises objects used for composite objects by the suffix -objs, and the suffix -y。

This allows the Makefiles to use the value of a CONFIG_ symbol to determine if an object is part

of a composite object.

例子:

# fs/ext2/Makefile

obj-$(CONFIG_EXT2_FS)        += ext2.o

 ext2-y                 := balloc.o bitmap.o

ext2-$(CONFIG_EXT2_FS_XATTR)    += xattr.o

在这个例子中,如果 $(CONFIG_EXT2_FS_XATTR) 是 ‘y‘,xattr.o将是复合对象 ext2.o的一部分。

注意:其实,将对象编译进内核时,上面的语法同样适用。所以,如果你的 CONFIG_EXT2_FS=y,那Kbuild会按你所期望的那样,生成一个独立ext2.o文件,然后将其链接到 built-in.o中。

3.4 输出的符号

Makefile对模块输出的符号没有特殊要求。

3.5 目标库文件 -- lib-y

obj-* 中所列出的目标文件是用来编译成模块或者是链接到特定目录中的built-in.o的。同样,你也可以列出一些目标文件,它们将被包含在lib.a库中。

lib-y 所列出的目标文件将会被用来组成该目录下的一个单独的库文件。

obj-y 与 lib-y 同时列出的目标文件,因为都是可以访问的,所以该文件是不会被包含在库文件中的。

同样,lib-m 中所列出的目标文件就要包含在 lib.a 库文件中。

注意:一个Kbuild makefile可以同时列出要编译进内核的文件和要编译成库的文件。所以,在一个目录里可以同时存在 built-in.o 与 lib.a 两种文件。

例子:

# arch/i386/lib/Makefile

lib-y    := chechsum.o delay.o

这将由 checksum.o 和delay.o 两个文件创建一个库文件lib.a。为了让Kbuild 系统真正认识到这里要有一个库文件 lib.a 要创建,库文件lib.a所在的目录需要加到 libs-y 列表中。

还可参考"6.3 递归向下时要访问的目录列表"。

lib-y 的使用一般限制在 lib/ 和 arch/*/lib 中。

3.6 递归向下访问目录

其实,一个Makefile只负责编译其所在目录下的对象文件。在子目录中的文件的编译要由其所在的子目录的Makefile来管理。只要你让Kbuild系统知道它应该递归操作,那么Kbuild系统就会在其子目录中自动调用 make 从而进行递归操作。

obj-y 和 obj-m 就有这样的作用。

ext2 被放在一个单独的目录下,在fs目录下的Makefile会告诉Kbuild系统使用下面的赋值进行向下递归操作。

例子:

# fs/Makefile

obj-$(CONFIG_EXT2_FS) += ext2/

如果 CONFIG_EXT2_FS 被设置为 ‘y‘(编译进内核)或是‘m‘(编译成模块),相应的 obj- 变量就会被设置,并且Kbuild就会递归向下访问 ext2 目录。

Kbuild系统只是用这些信息来决定它是否需要访问该目录,而具体怎么编译由该子目录中的Makefile来决定。

It is good practice to use a CONFIG_ variable when assigning directory    names. This allows kbuild to totally skip the directory if the corresponding CONFIG_ option is neither ‘y‘ nor ‘m‘.

3.7 编辑标志

EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS

所有的EXTRA_ 变量只在其被定义的Kbuild Makefile文件中起作用。而且,EXTRA_ 变量可以在Kbuild Makefile中的所有命令中使用。

l          $(EXTRA_CFLAGS) 是用 $(CC) 编译C源文件时要用到的选项。

例子:

# drivers/sound/emu10kl/Makefile

EXTRA_CFLAGS += -I$(obj)

ifdef DEBUG

EXTRA_CFLAGS += -DEMU10KL_DEBUG

endif

EXTRA_CFLAGS变量是必须的,因为顶层Makefile使用 $(EXTRA_CFLAGS)作为整个源代码树的编译选项。

l          $(EXTRA_AFLAGS) 也是一个针对每个目录的选项,只不过它是用来编译汇编源代码的。

例子:

# arch/x86_64/kernel/Makefile

EXTRA_AFLAGS := -traditional

l          $(EXTRA_LDFLAGS) 和 $(EXTRA_ARFLAGS)分别与 $(LD)和 $(AR)类似,只不过,他们是针对内核的每个目录的编辑标志。

例子:

# arch/m68k/fpsp040/Makefile

EXTRA_LDFLAGS := -x

l          [email protected], [email protected]

[email protected] 和 [email protected] 只能在当前Kbuild Makefile中的命令中使用。

$([email protected]) 是 $(CC) 针对每个文件的选项。[email protected] 表明了具体操作的目标文件。

例子:

# drivers/scsi/Makefile

CFLAGS_aha152x.o =  -DAHA152X_STAT -DAUTOCONF

CFLAGS_gdth.o    =  # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ \

-DGDTH_STATISTICS

CFLAGS_seagate.o =  -DARBITRATE -DPARITY -DSEAGATE_USE_ASM

以上三行分别设置了aha152x.o,gdth.o 和 seagate.o的编译选项。

l          $([email protected])也类似,只是针对汇编语言的。

例子:

# arch/arm/kernel/Makefile

AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional

AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) –traditional

3.9 跟踪依赖

Kbuild 跟踪以下情况的依赖:

1)   所有要参与编译的文件(所有的.c 和.h文件)

2)   在参与编译文件中所要使用的 CONFIG_ 选项

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

因此,如果你改变了 $(CC) 的选项,所有受影响的文件都要重新编译。

3.10 特殊规则

特殊规则就是Kbuild编译系统不能提供所要求的支持时,所使用的规则。一个典型的例子就是在构建过程中生成的头文件。Another example are the architecture-specific Makefiles which need special rules to prepare boot images etc.

Special rules are written as normal Make rules.

Kbuild is not executing in the directory where the Makefile is located, so all special rules shall provide a relative     path to prerequisite files and target files.

Two variables are used when defining special rules:

l          $(src)

$(src) 表明Makefile所在目录的相对路径。需要定位源代码树中的文件时经常使用该变量。

l          $(obj)

$(obj) 表明目标文件所要存储目录的相对路径。经常在定位所生成的目标文件时使用该变量。

例子:

# 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)来定位源文件。

3.11 $(CC) 支持的函数

内核可能由多个不同版本的$(CC)编译,而每个版本都支持不同的功能集与选项集。Kbuild系统提供了检查 $(CC) 可用选项的基本功能。$(CC)一般情况下是gcc编译器,但也可以使用其它编译器来代替gcc。

l          as-option

as-option,当编译汇编文件(*.S)时,用来检查 $(CC) 是否支持特定选项。如果第一个选项不支持的话,可选的第二个选项就派上用场了。

例子:

# arch/sh/Makefile

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

在上面的例子里,如果 $(CC) 支持选项 -Wa$(comma)-isa=$(isa-y),cflags-y就会被赋予该值。    第二个参数是可选的,当第一个参数不支持时,就会使用该值。

l          ld-option

ld-option,当链接目标文件时,用来检查 $(CC) 是否支持特定选项。如果第一个选项不支持的话,可选的第二个选项可以用来指定。

例子:

#arch/i386/kernel/Makefile

vsyscall-flags += $(call ld-option, -Wl$(comma)--hash-style=sysv)

在上面的例子中,如果 $(CC)支持选项 -Wl$(comma)--hash-style=sysv,ld-option就会被赋予该值。

第二个参数是可选的,当第一个参数不支持时,就会使用该值。

l          cc-option

cc-option,用来检查 $(CC) 是否支持特定选项,并且不支持使用可选的第二项。

例子:

# arch/i386/Makefile

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

在上面的例子中,如果 $(CC)支持选项 -march=pentium-mmx,cc-option就会被赋予该值,否则就赋 -march-i586。

cc-option的第二个参数是可选的。如果忽略的话,当第一个选项不支持时,cflags-y 不会被赋值。

l          cc-option-yn

cc-option-yn,用来检查 gcc 是否支持特定选项,返回‘y‘支持,否则为‘n‘。

例子:

# 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。

l          cc-option-align

gcc版本大于3.0时,改变了函数,循环等用来声明内存对齐的选项。当用到对齐选项时,$(cc-option-align) 用来选择正确的前缀:

gcc < 3.00

cc-option-align = -malign

gcc >= 3.00

cc-option-align = -falign

例子:

CFLAGS += $(cc-option-align)-functions=4

在上面的例子中,选项 -falign-funcions=4 被用在gcc >= 3.00的时候。对于小于3.00时, 使用 -malign-funcions=4 。

l          cc-version

cc-version以数学形式返回 $(CC) 编译器的版本号。

其格式是:<major><minor>,二者都是数学。比如,gcc 3.41 会返回 0341。 当某版本的 $(CC) 在某方面有缺陷时,cc-version就会很有用。比如,选项-mregparm=3 虽然会被gcc接受,但其实现是有问题的。

例子:

# arch/i386/Makefile

cflags-y += $(shell \

if [ $(call cc-version) -ge 0300 ] ; then \

echo "-meregparm=3"; fi ;)

在上面的例子中,-mregparm=3只会在gcc的版本号大于等于3.0的时候使用。

l          cc-ifversion

cc-ifversion测试 $(CC) 的版本号,如果版本表达式为真,就赋值为最后的参数。

例子:

#fs/reiserfs/Makefile

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

在这个例子中,如果 $(CC) 的版本小于4.2,EXTRA_CFLAGS就被赋值 -O1。

cc-ifversion 可使用所有的shell 操作符:-eq,-ne,-lt,-le,-gt,和-ge。

第三个参数可以像上面例子一样是个文本,但也可以是个扩展的变量或宏。

时间: 2024-10-12 02:40:52

Kbuild文件的相关文章

Linux内核Makefile文件(翻译自内核手册)

转载自:http://www.cnblogs.com/jason-lu/p/3728198.html --译自Linux3.9.5 Kernel Makefiles(内核目录documention/kbuild/makefiles.txt) kbuild(kernel build) 内核编译器 This document describes the Linux kernel Makefiles 本文当介绍了Linux内核的Makefile === Table of Contents=== 目录

Make ARCH=arm CROSS_COMPILE=arm-linux-gcc menuconfig 分析

在编译LINUX内核时,首先要修改内核源码顶层目录下的makefile文件,将其中ARCH ?= $(SUBARCH)修改为ARCH ?= arm,将CROSS_COMPILE    ?= 修改为CROSS_COMPILE    ?= arm-linux-gcc,或者不修改,而是将ARCH和CROSS_COMPILE的值通过命令行传入.然后在linux内核源码目录下,执行make menuconfig,那之后发生了什么? make命令在未指定文件的情况下,默认寻找名为Makefile或GNUMa

配置Linux Kernel时make menuconfig执行流程分析

   在编译内核前,一般是根据已有的配置文件(一般在内核根目录下的arch/arm/configs/文件夹下,把该目录下的xxx_defconfig文件拷贝到内核根目录下,并重命名为.config)来进行编译; 或者需要先配置裁剪内核. 假设我们要基于一块ARM芯片的开发板配置裁剪内核时,在内核的根目录下运行:make ARCH=arm menuconfig命令后,会弹出如下配置界面: 当我们在内核的根目录下运行make ARM=arm menuconfig这条命令时,内核根目录下的Makefi

Linux源文件夹结构呈现

1.arch文件夹: - 相关的存储在不同平台上的代码,每个平台都采用了不同的文件夹来区分. ******Alpha平台 ******Arm平台 ******Arv32平台 ******X86平台 2.drivers文件夹:存放驱动程序的文件夹.不同的驱动用不同的文件夹来加以区分. ******ftape:磁带驱动 ******hfmodem:无线电设备驱动 ******joystick:游戏杆驱动 ******paride:从并口訪问IDE设备的支持 ******cdrom:光驱驱动 ****

编译android的linux kernel goldfish

https://source.android.com/source/building-kernels.html $ export PATH=/home/hzh/oldhome/learn/android-4.2.2/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:${PATH} $ export ARCH=arm $ export SUBARCH=arm $ export CROSS_COMPILE=arm-eabi- $ make ARCH=arm g

Linux源代码目录结构介绍

1.arch目录:存放不同平台的相关代码,每种平台用不同的目录来区分. ******Alpha平台 ******Arm平台 ******Arv32平台 ******X86平台 2.drivers目录:存放驱动程序的目录,不同的驱动用不同的目录来加以区分. ******ftape:磁带驱动 ******hfmodem:无线电设备驱动 ******joystick:游戏杆驱动 ******paride:从并口访问IDE设备的支持 ******cdrom:光驱驱动 ******char:字符设备驱动

【转载】你知道 Linux 内核是如何构建的吗?

内核的根 Makefile 负责构建两个主要的文件:vmlinux (内核镜像可执行文件)和模块文件.内核的 Makefile 从定义如下变量开始: VERSION = 4 PATCHLEVEL = 2 SUBLEVEL = 0 EXTRAVERSION = -rc3 NAME = Hurr durr I'ma sheep 这些变量决定了当前内核的版本,并且被使用在很多不同的地方,比如同一个 Makefile 中的 KERNELVERSION : KERNELVERSION = $(VERSIO

Linux 2.6内核Makefile浅析【转】

转自:http://blog.csdn.net/tommy_wxie/article/details/7280463 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 概述 kbuild文件 1 obj-y和obj-m 11 obj-y生成built-ino 12 目标由多个源文件编译得到 13 调用子目录Makefile 2 lib-y和lib-m 3 编译选项变量 31 ccflags-yasflags-yldflags-y 32 subdir-ccflags-ysub

kernel makefile

===Documentation/kbuild/makefiles.txt=== The Makefiles have five parts: Makefile                               the top Makefile. .config                                  the kernel configuration file. arch/$(ARCH)/Makefile         the arch Makefile.