`
hududumo
  • 浏览: 238515 次
文章分类
社区版块
存档分类
最新评论

KBuild MakeFile介绍(转)

 
阅读更多

引自:http://blog.chinaunix.net/space.php?uid=21289517&do=blog&id=1828166

Linux内核Makefile分类

  • Kernel Makefile

Kernel Makefile位于Linux内核源代码的顶层目录,也叫 Top Makefile。它主要用于指定编译Linux Kernel目标文件(vmlinux)和模块(module)。这编译内核或模块是,这个文件会被首先读取,并根据读到的内容配置编译环境变量。对于内核或驱动开发人员来说,这个文件几乎不用任何修改。

  • Kbuild Makefile

Kbuild系统使用Kbuild Makefile来编译内核或模块。当Kernel Makefile被解析完成后,Kbuild会读取相关的Kbuild Makefile进行内核或模块的编译。Kbuild Makefile有特定的语法指定哪些编译进内核中、哪些编译为模块、及对应的源文件是什么等。内核及驱动开发人员需要编写这个Kbuild Makefile文件。

  • ARCH Makefile

ARCH Makefile位于ARCH/$(ARCH)/Makefile,是系统对应平台的Makefile。Kernel Top Makefile会包含这个文件来指定平台相关信息。只有平台开发人员会关心这个文件。


Kbuild Makefile
Kbuild Makefile的文件名不一定是Makefile,尽管推荐使用Makefile这个名字。大多的Kbuild文件的名字都是Makefile。为了与其他Makefile文件相区别,你也可以指定Kbuild Makefile的名字为Kbuild。而且如果“Makefile”和“Kbuild”文件同时存在,则Kbuild系统会使用“Kbuild”文件。

  • 目标定义

Kbuild Makefile的一个最主要功能就是指定编译什么,这个功能是通过下面两个对象指定的obj-?和xxx-objs:

  • obj-?

obj-?指定编译什么,怎么编译?其中的“?”可能是“y”或“m”,“y”指定把对象编译进内核中,“m”指定把对象编译为模块。语法如下;
obj-? = $(target).o
target为编译对象的名字。如果没有指定xxx-objs,这编译这个对象需要的源文件就是$(target).c或$(target).s。如果指定了$(target)-objs,则编译这个对象需要的源文件由$(target)-objs指定,并且不能有$(target).c或$(target).s文件。

  • xxx-objs

xxx-objs指定了编译对象需要的文件,一般只有在源文件是多个时才需要它。

只要包含了这两行,Kbuild Makefile就应该可以工作了。

  • 嵌套编译

有时一个对象可能嵌入到另一个对象的目录下,那个如何编译子目录下的对象呢?其实很简单,只要指定obj_?的对象为子目录的名字就可以了:

obj-? = $(sub_target)/

其中“?”可以是“y”或“m”,$(sub_target)是子目录名字。

  • 编译器选项

尽管在大多数情况下不需要指定编译器选项,有时我们还是需要指定一些编译选项的。

  • ccflags-y, asflags-y and ldflags-y

这些编译选项用于指定cc、as和ld的编译选项

编译外部模块
有时候我们需要在内核源代码数的外面编译内核模块,编译的基本命令是:

make -C $(KERNEL_DIR) M=`pwd` modules
我们可以把这个命令集成到Makefile里,这样我们就可以只输入“make”命令就可以了。回想上一章的那个Makefile,它把Normal Makefile 和Kbuild Makefile集成到一个文件中了。为了区别Kbuild Makefile 和Normal Makefile,这样我们改写Makefile为如下形式,并且添加Kbuild Makefile - “Kbuild”。

##Makefile
ifneq ($(KERNELRELEASE),)
include "Kbuild"
else
KERNEL_DIR = /lib/modules/`uname -r`/build
MODULEDIR := $(shell pwd)

.PHONY: modules
default: modules

modules:
make -C $(KERNEL_DIR) M=$(MODULEDIR) modules

clean distclean:
rm -f *.o *.mod.c .*.*.cmd *.ko
rm -rf .tmp_versions
endif

## Kbuild
MODULE_NAME = helloworld
$(MODULE_NAME)-objs := hello.o
obj-m := $(MODULE_NAME).o


一般不需要在Makefile里包含如下代码,这样写完全是为了兼容老版本的Kbuild系统。KERNELRELEASE变量在Kernel Makefile里定义的,因此只有在第二次由Kbuild读取这个Makefile文件时才会解析到Kbuild的内容。

ifneq ($(KERNELRELEASE),)
include "Kbuild"
else
...
endif


外部头文件
有时需要连接内核源代码外部的系统头文件,但Kbuild系统默认的系统头文件都在内核源代码内部,如何使用外部的头文件呢?这个可以借助于Kbuild系统的特殊规则:

  • EXTRA_CFLAGS

EXTRA_CFLAGS可以给Kbuild系统添加外部系统头文件,
EXTRA_CFLAGS += $(ext_include_path)
一般外部头文件可能位于外部模块源文件的目录内,如何指定呢?这可以借助$(src)或$(obj)

  • $(src)/$(obj)

$(src)是一个相对路径,它就是Makefile/Kbuild文件所在的路径。同样$(obj)就是编译目标保存的路径,默认就是源代码所在路径。


因此,我们修改Kbuild文件添加 EXTRA_CFLAGS 来包含外部头文件尽管在这个驱动里没有引用外部系统头文件:

## Kbuild
MODULE_NAME = helloworld
$(MODULE_NAME)-objs := hello.o
EXTRA_CFLAGS := -I$(src)/include
obj-m := $(MODULE_NAME).o

  • Goal definitions

Example:

obj-y += foo.o

告诉kbuild,在文件夹中又一个叫做foo.o的object。foo.o将会被从foo.c或者foo.S被构建。

如果foo.o被构建成一个模块,则将使用变量obj-mExample:

obj-$(CONFIG_FOO) += foo.o

$(CONFIG_FOO)要么是y(built-in)要么是m(module)。如果CONFIG_FOO既不是y也不是m,那么文件将不会被编译也不会被连接。

  • Built-in object goals - obj-y

kbuild Makefiles在$(obj-y)列表中为vmlinux指明object文件。这个列表依靠内核的配置。

$(obj-y)中的文件的顺序是非常重要的。列表中允许两个相同的文件:第一个实体将被连接到built-in.o,后面的实体将会被忽略。

连接的顺序也很重要,因为在boot过程中某些函数(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) += isdn.o
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

  • Loadable module goals - obj-m

$(obj-m)指明object文件作为可装载的内核模块被构建。一个模块可能从一个或者多个源文件被构建。kbuild maefile只是简单的将源文件加到%(obj-m)

Example:
#drivers/isdn/i4l/Makefile
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

注意这里$(CONFIG_ISDN_PPP_BSDCOMP)是m.

Note: In this example $(CONFIG_ISDN_PPP_BSDCOMP) evaluates to 'm'。

如果一个内核模块从多个源文件构建,KBuild就必须要知道你想从哪些部分构建模块。因此,你不得不设置$(<module_name>-objs)变量来告诉KBuild。

Example:
#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)的object文件,然后在这些文件的列表中调用"$(LD) -r"来产生isdn.o。

Kbuild使用后缀-objs,-y来识别混合的object文件。这允许Makefiles使用变量CONFIG_sambol来决定一个object是否是混合object的的一部分。

Example:
#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只是混合object文件ext2.o的一部分。

注意,当你构造一个objects到内核中时,上面的语法当然也能够工作。因此,如果你让CONFIG_EXT2=Y,KBuild将会为你构建一个独立的ext2.o文件,并且连接到built-in.o。

  • Library file goals - lib-y

obj-*连接的Objects在指明的文件夹中被用作模块或者综合进built-in.o。也又可能被列出的objects将会被包含进一个库,lib.a。所有用lib-y列出的objects在那个文件夹中被综合进单独的一个库。列在obj-y和附加列在lib-y中的Objects将不会被包含在库中,因为他们将会被任意的存取。对于被连接在lib-m中,连续的objects将会被包含在lib.a中。值得注意的是kbuild makefile可能列出文件用作built-in,并且作为库的一部分。因此,同一个文件夹可能包含一个built-in.o和lib.a文件。

Example:
#arch/i386/lib/Makefile
lib-y := checksum.o delay.o

这里讲会创建一个基于checksum.o和delay.o的库文件。对于kbuild,识别一个lib.a正在被构建,这个文件夹应该被列在libs-y中。lib-y的使用方法通常被限制在lib/和arc/*/lib中。

  • Descending down in directories

一个Makefile只负责在他自己的文件夹中构建objects。在子文件夹中的文件应该由子文件夹中的Makefiles来照顾。如果你知道他们,build系统将会自动递归地用在子文件夹中的make。

在这种情况下obj-yobj-m就被使用了。ext2存在于不同的文件夹中,Makefile出现在fs/,则告诉kbuild从后面的参数下来。

Example:
#fs/Makefile
obj-$(CONFIG_EXT2_FS) += ext2/

如果CONFIG_EXT2_FS被设置成y(built-in)或者m(modular),相应的obj-变量将会被设置,并且kbuild将会从ext2文件夹继承下来。Kbuild只会使用这些信息来决定它需要访问这些文件夹,而在子文件夹中的Makefile来指明哪些是modules哪些是built-in。

当赋值文件夹名字的时候,使用CONFIG_variable是很好的选择。这允许kbuild完全的跳过文件夹,而不管CONFIG_option是否是y或者m。

  • Compilation flags

EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS。

所有的EXTRA_ variables只应用在kbuild中,他们被赋值的地方。EXTRA_variables应用在kbuild makefile中所有的可执行的命令。$(EXTRA_CFLAGS)指明用$(CC)编译C文件的时候的选项。

Example:
# drivers/sound/emu10k1/Makefile
EXTRA_CFLAGS += -I$(obj)
ifdef DEBUG
EXTRA_CFLAGS += -DEMU10K1_DEBUG
endif

这里的变量是必须的,因为顶层的Makefile拥有变量$(CFLAGS)并且用它来作为整个树的编译标志当编译汇编源文件的时候$(EXTRA_AFLAGS),和每个文件夹的选项是相似的。

Example:
#arch/x86_64/kernel/Makefile
EXTRA_AFLAGS := -traditional

$(EXTRA_LDFLAGS)$(EXTRA_ARFLAGS)对于每个文件夹的$(LD)和$(AR)选项是类似的。

Example:
#arch/m68k/fpsp040/Makefile
EXTRA_LDFLAGS := -x

CFLAGS_$@, AFLAGS_$@

CFLAGS_$@AFLAGS_$@只应用到当前kbuild makefile的命令。

$(CFLAGS_$@)为每个文件的$(CC)指明选项。$@
部分有一个字面上的值,指明它是为那个文件。

Example:
# 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

These three lines specify compilation flags for aha152x.o,
gdth.o, and seagate.o

$(AFLAGS_$@) is a similar feature for source files in assembly
languages.

Example:
# arch/arm/kernel/Makefile
AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional
AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional

分享到:
评论

相关推荐

    KBuild MakeFile介绍.doc

    Kbuild系统使用Kbuild Makefile来编译内核或模块。当Kernel Makefile被解析完成后,Kbuild会读取相关的Kbuild Makefile进行内核或模块的编译。Kbuild Makefile有特定的语法指定哪些编译进内核中、哪些编译为模块、及...

    linux内核kbuild Makefile详解

    linux下各平台的下的makefile文件与gnu makefile有一些不一样,这里作了详细分解,有好几个文件,把这个看会了,看linux下makefile不是问题

    kbuild makefile 总结

    linux设备驱动makefile:2.4内核模块Makefile模板 #Makefile for linux2.4 KVER=$(shell uname -r) KDIR=/lib/modules/$(KVER)/build OBJS=mymodule.o CFLAGS=-D__KERNEL__ -I$(KDIR) /include -DMODULE

    Linux Kbuild文档

    1.Linux内核配置方式 2.Kconfig 3.Kbuild Makefile 4.一个使用linux Kbuild实现可配置编译的例子

    Linux内核的Makefile2

    3.1节目标定义是一个快速的简介,下面的章节将会提供细节和例子 3.1 目标定义目标定义是kbuild Makefile的主要部分(核心) 3.2 内置目标 -

    Linux内核的Makefile1

    3.1节目标定义是一个快速的简介,下面的章节将会提供细节和例子 3.1 目标定义目标定义是kbuild Makefile的主要部分(核心) 3.2 内置目标 -

    Kbuild分析

    Kbuild系统实现分析,Kconfig和Makefile语法

    Linux下Makefile说明文档翻译

    为了学习Linux下的Makefile,从昨天开始决定要翻译一下源码底下/Documentation/kbuild目录下的modules.txt和Makefile.txt说明文档,今天翻译完,从网上找了篇别人的译文对比了下,感觉自己翻译的还算差强人意,所以...

    Linux内核Makefile浅析

    多的资料(《嵌入式Linux应用开发完全手册》、Documentation/kbuild/makefiles.txt)已经向我们展示了一个初级Linux用户者应该懂得的知识--怎样添加需要编译的文件、添加编译的规则、多个源文件构成一个目标文件的...

    KBUILD实现pdf

    理解Kbuild有助于理解Linux的编译流程,对于Linux的体系架构理解起到事半功倍的作用

    Linux那些事儿之我是Block层

    COPYING Documentation MAINTAINERS README arch crypto fs init kernel mm scripts sound CREDITS Kbuild Makefile REPORTING-BUGS block drivers include ipc lib net security usr 进入block目录,用旁光看一下...

    如何写MAKEFILE文件.doc

    MAKEFILe 关于一个如何书写该类文件的说明

    linux2.6内核Makefile详解

    内核目录的documention/kbuild/makefiles.txt的中文翻译,快速入门还是有点帮助。

    \\192.168.1.233\george_home\fpga\kbuild_test\kbuild_app.tgz

    kbuild一般编译内核,当前这个工程用于控制编译应用程序,非常不错的例子

    linux2.6内核Makefile详解 pdf

    熟悉内核的 Makefile对开发设备驱动、理解内核代码结构都是非常重要的 linux2.6 内核 Makefile 的许多特性和 2.4 内核差别很大,在内核目录的documention/kbuild/makefiles.txt中有详细的说明

    kernel2.6.x Makefile详解 .chm

    kernel2.6.x Makefile详解 linux2.6内核Makefile的许多特性和2.4内核差别很大,在内核目录的documention/kbuild/makefiles.txt中有详细的说明。 本文是中文翻译,方便学习

    makefile.doc

    熟悉内核的Makefile对开发设备驱动、理解内核代码结构都是非常重要的! 在内核目录的documention/kbuild/makefiles.txt中有详细的说明。给大家一个中文版的翻译

    kbuild:Userland的Kbuild存储库模板

    Userland的Kbuild存储库模板 相同的代码库用于从超级计算机到超小型设备的不同范围的计算系统。 建库 没有粘合代码的更简单的makefile,很难读取和维护 减轻开发人员对代码依赖项管理的负担 一种简单高效的方法来...

    嵌入式系统/ARM技术中的kbuild系统-内核模块的编译

    我们可以通过分析它的Makefile入手。以下是一个简单的hello内核模块的Makefile.  ifneq ($(KERNELRELEASE),)  obj-m:=hello.o  else  KERNELDIR:=/lib/modules/$(shell uname -r)/build  PWD:=$(shell pwd...

    build external modules

    linux 2.6 内核 kbuild 文档。 讲述编译内核模块 makefile编写事项 老外写得,英文版

Global site tag (gtag.js) - Google Analytics