Linux内核2.6Makefile文件
===目录
===1概述
===2角分工
===3内核编译文件
---3.1目标定义
---3.2内嵌对象-obj-y
---3.3可加载模块-obj-m
---3.4导出符号
---3.5库文件-lib-y
---3.6目录递归
-
--3.7编译标记
---3.8命令依赖
---3.9依赖关系
---3.10特殊规则
===4辅助程序
---4.1简单辅助程序
---4.2组合辅助程序
---4.3定义共享库
---4.4C++语言使用方法
---4.5辅助程序编译控制选项
---4.6何时建立辅助程序
-
--4.7使用hostprogs-$(CONFIG_FOO)
===1概述
Makefile包括五部分:
Makefile顶层Makefile文件
.config内核配置文件
arch/$(ARCH)/Makefile机器体系Makefile文件
scripts/Makefile.*所有内核Makefiles共用规则
kbuild Makefiles其它makefile文件
通过内核配置操作产生.config文件,顶层Makefile文件读取该文件的配置。顶层Makefile 文件负责产生两个主要的程序:vmlinux(内核image)和模块。顶层Makefile文件根据内核配置,通过递归编译内核代码树子目录建立这两个文件。顶层Makefile文件文本一个名为arch/$(ARCH)/Makefile的机器体系makefile文件。机器体系Makefile文件为顶层makefile 文件提供与机器相关的信息。每一个子目录有一
个makefile文件,子目录makefile文件根据上级目录makefile文件命令启动编译。这些makefile使用.config文件配置数据构建各种文件列表,并使用这些文件列表编译内嵌或模块目标文件。scripts/Makefile.*包含了所有的定义和规则,与makefile文件一起编译出内核程序。
===2角分工
人们与内核makefile存在四种不同的关系:
*用户*用户使用"make menuconfig"或"make"命令编译内核。他们通常不读或编辑内核makefile文件或其他源文件。
*普通开发者*普通开发者维护设备驱动程序、文件系统和网络协议代码,他们维护相关子系统的makefile文件,因此他们需要内核makefile文件整体性的一般知识和关于kbuild公共接口的详细知识。
*体系开发者*体系开发者关注一个整体的体系架构,比如sparc或者ia64。体系开发者既需要掌握关于体系的makefile文件,也要熟悉内核makefile文件。
*内核开发者*内核开发者关注内核编译系统本身。他们需要清楚内核makefile文件的所有方面。
本文档的读者对象是普通开发者和系统开发者。
===3内核编译文件
内核中大多数makefile文件是使用kbuild基础架构的makefile文件。本章介绍kbuild的makefile中的语法。
3.1节“目标定义”是一个快速导引,后面各章有详细介绍和实例。
---3.1目标定义
目标定义是makefile文件的主要部分(核心)。这些目标定义行定义了如何编译文件,特殊的兼容选项和递归子目录。
最简单的makefile文件只包含一行:
Example:obj-y+=foo.o
这行告诉kbuild在该目录下名为foo.o的目标文件(object),foo.o通过编译foo.c或者foo.S而得到。
如果foo.o编译成一个模块,则使用obj-m变量,因此常见写法如下:
Example:obj-$(CONFIG_FOO)+=foo.o
$(CONFIG_FOO)可以代表y(built-in对象)或m(module对象)。
如果CONFIG_FOO不是y或m,那么这个文件不会被编译和链接。
---3.2内嵌对象-obj-y
makefile文件将为编译vmlinux的目标文件放在$(obj-y)列表中,这些列表依赖于内核配置。
Kbuild编译所有的$(obj-y)文件,然后调用"$(LD)-r"合并这些文件到一个built-in.o文件中。built-in.o经过父makefile文件链接到vmlinux。$(obj-y)中的文件顺序很重要。列表中文件允许重复,文件第一次出现将被链接到built-in.o,后续出现该文件将被忽略。
链接顺序之所以重要是因为一些函数在内核引导时将按照他们出现的顺序被调用,如函数(module_init()/__initcall)。所以要牢记改变链接顺序意味着也要改变SCSI控制器的检测顺序和重数磁盘。
例如:#drivers/isdn/i4l/Makefile
#内核ISDN子系统和设备驱动程序Makefile
#每个配置项是一个文件列表
obj-$(CONFIG_ISDN)+=isdn.o
obj-$(CONFIG_ISDN_PPP_BSDCOMP)+=isdn_bsdcomp.o
---3.3可加载模块-obj-m
$(obj-m)表示对象文件(object files)编译成可加载的内核模块。
一个模块可以通过一个源文件或几个源文件编译而成。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
在这个例子中,模块名Kbuild首先编译$(isdn-objs)中的object文件,然后运行"$(LD)-r"将列表中文件生成
Kbuild使用后缀-objs、-y识别对象文件。这种方法允许makefile使用CONFIG_符号值确定一个object文件是否是另外一个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',则ext2.o只有xattr.o组成部分。
注意:当然,当你将对象文件编译到内核时,以上语法同样有效。因此,如果CONFIG_EXT2_FS=y,
Kbuild将先编译ext2.o文件,然后链接到built-in.o。
---3.4导出符号目标
在makefile文件中没有特别导出符号的标记。
---3.5库文件-lib-y
obj-*中的object文件用于模块或built-in.o编译。object文件也可能编译到库文件中--lib.a。
所有罗列在lib-y中的object文件都将编译到该目录下的一个单一的库文件中。
包含在0bj-y中的object文件如果也列举在lib-y中将不会包含到库文件中,因为他们不能被访问。但lib-m中的object文件将被编译进lib.a库文件。
注意在相同的makefile中可以列举文件到buit-in内核中也可以作为库文件的一个组成部分。因此在同一个目录下既可以有built-in.o也可以有lib.a文件。
例如:#arch/i386/lib/Makefile
lib-y:=checksum.o delay.o
这样将基于checksum.o、delay.o创建一个lib.a文件。
linux内核文件放在哪对于内核编译来说,lib.a文件被包含在libs-y中。将“6.3目录表”。
lib-y通常被限制使用在lib/和arch/*/lib目录中。
---3.6目录递归
makefile文件负责编译当前目录下的目标文件,子目录中的文件由子目录中的makefile 文件负责编译。编译系统将使用obj-y和obj-m自动递归编译各个子目录中文件。
如果ext2是一个子目录,fs目录下的makefile将使用以下赋值语句是编译系统编译ext2子目录。
例如:#fs/Makefile
obj-$(CONFIG_EXT2_FS)+=ext2/
如果CONFIG_EXT2_FS设置成'y(built-in)或'm'(modular),则对应的obj-变量也要设置,内核编译系统将进入ext2目录编译文件。
内核编译系统只使用这些信息来决定是否需要编译这个目录,子目录中makefile文件规定那些文件编
译为模块那些是内核内嵌对象。
当指定目录名时使用CONFIG_变量是一种良好的做法。如果CONFIG_选项不为'y'或'm',内核编译系统就会跳过这个目录。
---3.7编译标记
EXTRA_CFLAGS,EXTRA_AFLAGS,EXTRA_LDFLAGS,EXTRA_ARFLAGS
所有的EXTRA_变量只能使用在定义该变量后的makefile文件中。EXTRA_变量被makefile 文件所有的执行命令语句所使用。
$(EXTRA_CFLAGS)是使用$(CC)编译C文件的选项。
例如:#drivers/sound/emu10k1/Makefile
EXTRA_CFLAGS+=-I$(obj)
ifdef
DEBUG EXTRA_CFLAGS+=-DEMU10K1_DEBUG
endif
定义这个变量是必须的,因为顶层makefile定义了$(CFLAGS)变量并使用该变量编译整个代码树。
$(EXTRA_AFLAGS)是每个目录编译汇编语言源文件的选项。
例如:#arch/x86_64/kernel/Makefile
EXTRA_AFLAGS:=-traditional
$(EXTRA_LDFLAGS)和$(EXTRA_ARFLAGS)用于每个目录的$(LD)和$(AR)选项。
例如:#arch/m68k/fpsp040/Makefile
EXTRA_LDFLAGS:=-x
CFLAGS_$@,AFLAGS_$@
CFLAGS_$@和AFLAGS_$@只使用到当前makefile文件的命令中。
$(CFLAGS_$@)定义了使用$(CC)的每个文件的选项。$@部分代表该文件。
例如:#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文件的编译选项。
$(AFLAGS_$@)使用在汇编语言代码文件中,具有同上相同的含义。
例如:#arch/arm/kernel/Makefile
AFLAGS_head-armv.o:=-DTEXTADDR=$(TEXTADDR)-traditional
AFLAGS_head-armo.o:=-DTEXTADDR=$(TEXTADDR)-traditional
---3.9依赖关系
内核编译记录如下依赖关系:
1)所有的前提文件(both*.c and*.h)
2)CONFIG_选项影响到的所有文件
3)编译目标文件使用的命令行
因此,假如改变$(CC)的一个选项,所有相关的文件都要重新编译。
---3.10特殊规则
特殊规则使用在内核编译需要规则定义而没有相应定义的时候。典型的例子如编译时头文件的产生规则。其他例子有体系makefile编译引导映像的特殊规则。特殊规则写法同普通的Make规则。
Kbuild(应该是编译程序)在makefile所在的目录不能被执行,因此所有的特殊规则需要提供前提文件和目标文件的相对路径。
定义特殊规则时将使用到两个变量:
$(src):$(src)是对于makefile文件目录的相对路径,当使用代码树中的文件时使用该变量$(src)。
$(obj):$(obj)是目标文件目录的相对路径。生成文件使用$(obj)变量。
例如:#drivers/scsi/Makefile
$(obj)/53c8xx_d.h:$(src)/53c7,8xx.scr$(src)/script_asm.pl
$(CPP)-DCHIP=810-<$<|...$(src)/script_asm.pl
这就是使用普通语法的特殊编译规则。
目标文件依赖于两个前提文件。目标文件的前缀是$(obj),前提文件的前缀是$(src)(因为它们不是生成文件)。
===4辅助程序
内核编译系统支持在编译(compliation)阶段编译主机可执行程序。为了使用主机程序需要两个步骤:第一个步骤使用hostprogs-y变量告诉内核编译系统有主机程序可用。第二步给主机程序添加潜在的依赖关系。有两种方法,在规则中增加依赖关系或使用$(always)变量。具体描述如下。
---4.1简单辅助程序
在一些情况下需要在主机上编译和运行主机程序。下面这行告诉kbuild在主机上建立bin2hex程序。
例如:hostprogs-y:=bin2hex
Kbuild假定使用makefile相同目录下的单一C代码文件bin2hex.c编译bin2hex。
---4.2组合辅助程序
主机程序也可以由多个object文件组成。定义组合辅助程序的语法同内核对象的定义方法。
$(<executeable>-objs)包含了所有的用于链接最终可执行程序的对象。
例如:#scripts/lxdialog/Makefile

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。