`

KBuild MakeFile介绍

阅读更多

    从Linux 内核2.6 开始,Linux 内核的编译采用Kbuild 系统 ,这同过去的编译系统有很大的不同,尤其对于Linux 内核模块的编译。在新的系统下,Linux 编译系统会两次扫描LinuxMakefile :首先编译系统会读取Linux 内核顶层的Makefile ,然后根据读到的内容第二次读取KbuildMakefile 来编译Linux 内核。

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 ,是系统对应平台的MakefileKernel 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

这些编译选项用于指定ccasld 的编译选项

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

    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.oobjectfoo.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 ,那么文件将不会被编译也不会被连接。

·         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.olib.a 文件。

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

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

·         Descending down in directories

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

在这种情况下 obj-y obj-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

 

 原文地址 http://blog.sina.com.cn/s/blog_48c1b149010002qj.html

分享到:
评论

相关推荐

    KBuild MakeFile介绍.doc

    KBuild系统通过解析一系列的Makefile文件,包括Kernel Makefile、Kbuild Makefile以及ARCH Makefile,来决定编译内核或模块的具体步骤和配置。 Kernel Makefile,即位于内核源码顶层目录的Top Makefile,主要负责...

    linux内核kbuild Makefile详解

    2. **kbuild架构**:kbuild由一系列的Makefile组成,包括顶级的`Makefile`、`Rules.make`、`Kbuild`等,以及每个子目录中的`Kconfig`和`Makefile`。`Kconfig`用于配置内核选项,而`Makefile`则定义了如何构建目标。 ...

    kbuild makefile 总结

    ### Kbuild Makefile 在 Linux 2.4 与 2.6 内核下的应用 #### 1. Linux 2.4 内核模块 Makefile 分析 在 Linux 2.4 内核环境中,模块的编译相对简单,只需要内核源码头文件并在编译前定义 `MODULE`。下面是对给定的...

    kbuild系统原理

    kbuild 系统原理可以分为两部分来介绍,首先介绍 Linux 的命令工具 make 及其所操作的 makefile,然后介绍 kbuild makefile 对 makefile 的扩充,以及 kbuild makefile 的工作原理。 MAKE 概述 make 是一种命令...

    介绍kbuild 的入门文档

    - [Kernel Hacking HOWTO](https://www.kernel.org/doc/Documentation/kbuild/kbuild.txt):官方文档,详细介绍了`kbuild`的高级特性和最佳实践。 - [LWN.net](https://lwn.net/):Linux内核新闻网站,定期发布有关`...

    Linux内核的Makefile1

    本文主要关注Linux内核的Makefile结构,特别是kbuild Makefile系统,这是构建内核的核心部分。kbuild是Linux内核构建系统,用于自动化内核编译过程,确保高效且一致的构建体验。 1. Linux内核Makefile的组成部分: ...

    linux内核的makefile规则文.pdf

    Linux内核的Makefile系统由多个层次的文件组成,包括顶层Makefile、特定架构的Makefile、通用脚本Makefile以及分布于各个源代码子目录的Kbuild Makefile。顶层Makefile读取由内核配置程序生成的`.config`文件,确定...

    makefile.txt

    根据给定的部分内容,该文档详细介绍了Linux内核构建过程中所使用的Makefile的工作原理和各个组成部分。 #### 二、Makefile的组成部分 1. **顶级Makefile** (`Makefile`): - 读取`.config`文件中的配置信息。 -...

    LINUX2.6内核makefile详解

    他们所需要维护的只是他们所工作的子系统的 Kbuild Makefile。 3. 架构开发人员:这是些工作在具体架构,比如 sparc 或者 x86 等。 4. 内核维护人员:这是些负责维护和更新内核 Makefile 的人员。 Kbuild 文件 ...

    Linux Kbuild文档

    本文详细介绍了 Linux 内核配置方式、Kconfig 以及 Kbuild Makefile 的相关知识点,并通过一个具体的例子展示了如何使用 `Kbuild` 实现可配置编译的过程。通过理解这些概念和技术,开发者可以更好地定制和优化他们的...

    makefile英文手册

    文档还介绍了 kbuild 使用的 Makefile 语言的基本概念和高级特性,帮助开发者更好地理解和编写 kbuild Makefile 文件。 #### 致谢 (Credits) 文档最后列出了对 kbuild 和 Linux 内核构建系统的贡献者名单,感谢...

    KBUILD实现pdf

    Linux内核的构建系统KBUILD是Linux开发中的一个重要组成部分,它负责管理内核源码树中的Makefile,确保编译过程高效、一致。通过理解KBUILD,我们可以深入了解Linux内核的构建流程,这对于驱动程序开发和其他内核...

    Makefile与Kconfig

    Makefile文件面对树状结构的内核源码目录,内核编译采用了各个子目录拥有自己目录相关的Makefile(被称为sub-Makefile或kbuild Makefile)。这些sub-Makefile定义了根据该子目录下的源码文件构建目标文件的规则,...

    KBUILD 系统原理分析.pdf

    KBUILD通过对传统的`Makefile`文件进行扩展和优化,使得内核的编译变得更加灵活且易于管理。 #### 二、KBUILD的关键概念 ##### 2.1 编译与链接 **编译(Compile):** - **定义:** 编译是指将源代码转换为机器可理解...

    Kbuild分析

    Makefile的模块安装(modules_install)目标将编译好的模块安装到特定的目录中,而kbuild.include文件中包含了一些工具函数,如echo_cmd和cmd,以及if_changed*等,它们用于简化Makefile的编写。 kbuild的专题分析还...

    kbuild完整详细分析

    最后,我们将探讨 Kbuild 中 Makefile 的具体实现细节。 ##### 6.1 Built-in object goals - obj-y obj-y 用于指定要构建的对象文件列表。 ##### 6.2 模块目标 (Loadable modules goal - obj-m) - **6.2.1 ...

    Makefile使用手册

    在Linux内核构建中,Makefile主要分为五个部分:顶级Makefile、配置文件(.config)、架构相关的Makefile(arch/$(ARCH)/Makefile)、通用规则文件(scripts/Makefile.*)以及具体的kbuild Makefile。 #### 作用与...

    Kbuild的实现分析

    `kbuild`通过精心设计的Makefile规则确保命令按照正确的顺序执行。 ###### 定义命令包(Defining Canned Command Sequences) `kbuild`允许定义一系列命令序列,这样可以减少重复代码,并使构建脚本更加清晰易懂。 #...

Global site tag (gtag.js) - Google Analytics