Linux 2.6内核Makefile浅析

1 概述

Makefile由五个部分组成:

  • Makefile:根目录Makefile,它读取.config文件,并负责创建vmlinux(内核镜像)和modules(模块文件)。
  • .config:内核配置文件(一般由make menuconfig生成)。
  • arch/$(ARCH)/Makefile:目标处理器的Makefile。
  • scripts/Makefile.*:所有kbuild Makefile的规则,它们包含了定义/规则等。
  • kbuild Makefiles:每个子目录都有kbuild Makefile,它们负责生成built-in或模块化目标。(注意:kbuild Makefile是指使用kbuild结构的Makefile,内核中的大多数Makefile都是kbuild Makefile。)

2 kbuild文件

2.1 obj-y和obj-m

         最简单的kbuild Makefile可以仅包含:

obj-$(CONFIG_FOO) += foo.o

         其中$(CONFIG_FOO)可以等于y或m,它的值由.config文件给出。如果$(CONFIG_FOO)既不是y也不是m,那么该文件不会被编译和链接

         当$(CONFIG_FOO)等于y时,上面语句等价于obj-y += foo.o,它告诉kbuild在当前目录下,有一个叫做foo.o的目标文件,它将从foo.c或则foo.S编译得到。

         当$(CONFIG_FOO)等于m时,表示foo.o需要被编译成模块。

2.1.1 obj-y生成built-in.o

         Kbuild编译所有的$(obj-y)文件,并调用”$(LD) -r”把所有这些文件合并到built-in.o文件。这个built-in.o会被上一级目录的Makefile使用,最终链接到vmlinux中。

2.1.2 目标由多个源文件编译得到

         如果某个目标由多个源文件编译得到,那么可以通过$(-objs)或$(-y)把这些源文件告诉kbuild。Kbuild能够识别后缀-objs和-y,例如:

         #drivers/isdn/i4l/Makefile

         obj-$(CONFIG_ISDN) += isdn.o

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

         Kbuild会编译所有$(isdn-objs)中的对象,并调用"$(LD) -r"把它们链接成isdn.o文件。

         下面是一个使用后缀-y的例子。后缀-y的好处是,可以使用CONFIG_XXX符号来决定是否加入某些源文件(.o从对应的.c或.S编译得到):

         #fs/ext2/Makefile

         obj-$(CONFIG_EXT2_FS)        += ext2.o

         ext2-y                       := balloc.o bitmap.o

         ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o

2.1.3 调用子目录Makefile

         Makefile只负责编译当前目录中的对象。子目录中的对象,由子目录中的Makefile负责。如何让make调用子目录中的Makefile?答案是把子目录包含到obj-y或obj-m中。例如:

         #fs/Makefile

         obj-$(CONFIG_EXT2_FS) += ext2/

         当CONFIG_EXT2_FS为y或m时,kbuild系统会在ext2目录中调用make命令(也即调用ext2目录中的Makefile)

2.2 lib-y和lib-m

         在一个目录下,obj-y所列出的文件,将被编译成built-in.o文件,而lib-y或lib-m所列出的文件,将在当前目录下生成lib.a文件。

         注意:一般lib-y或lib-m只用在lib/和archlib目录中。
    --- 3.6 目录递归
   makefile文件负责编译当前目录下de目标文件,子目录中de文件由子目录中demakefile文件负责编译。编译系统将使用obj-y和obj-m自动递归编译各个子目录中文件。
   如果ext2是一个子目录,fs目录下demakefile将使用以下赋值语句是编译系统编译ext2子目录。
    例如: #fs/Makefile
   obj-$(CONFIG_EXT2_FS) += ext2/
   如果CONFIG_EXT2_FS设置成'y(built-in)或'm'(modular),则对应deobj-变量也要设置,内核编译系统将进入ext2目录编译文件。
   内核编译系统只使用这些信息来决定是否需要编译这个目录,子目录中makefile文件规定那些文件编译为模块那些是内核内嵌对象。
   当指定目录名时使用CONFIG_变量是一种良好de做法。如果CONFIG_选项不为'y'或'm',内核编译系统就会跳过这个目录。
    --- 3.7 编译标记
   EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS
   所youdeEXTRA_变量只能使用在定义该变量后demakefile文件中。EXTRA_变量被makefile文件所youde执行命令语句所使用。
   $(EXTRA_CFLAGS)是使用$(CC)编译C文件de选项。
    例如: # drivers/sound/emu10k1/Makefile
    EXTRA_CFLAGS += -I$(obj)
    ifdef
    DEBUG EXTRA_CFLAGS += -DEMU10K1_DEBUG
    endif
   定义这个变量是必须de,因为顶层makefile定义了$(CFLAGS)变量并使用该变量编译整个代码树。
   $(EXTRA_AFLAGS)是每个目录编译汇编语言源文件de选项。
    例如: #arch/x86_64/kernel/Makefile
    EXTRA_AFLAGS := -traditional
   $(EXTRA_LDFLAGS)和$(EXTRA_ARFLAGS)用于每个目录de$(LD)和$(AR)选项。
    例如: #arch/m68k/fpsp040/Makefile
   EXTRA_LDFLAGS := -x
    CFLAGS_$@, AFLAGS_$@
   CFLAGS_$@和AFLAGS_$@只使用到当前makefile文件de命令中。
   $(CFLAGS_$@)定义了使用$(CC)de每个文件de选项。$@部分代表该文件。
    例如: # 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文件de编译选项。
   $(AFLAGS_$@)使用在汇编语言代码文件中,具you同上相同de含义。
    例如: # arch/arm/kernel/Makefile
   AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional
   AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional
    --- 3.9 依赖关系
   内核编译记录如下依赖关系:
    1) 所youde前提文件(both *.c and *.h)
    2) CONFIG_ 选项影响到de所you文件
    3) 编译目标文件使用de命令行
   因此,假如改变$(CC)de一个选项,所you相关de文件都要重新编译。
    --- 3.10 特殊规则
   特殊规则使用在内核编译需要规则定义而没you相应定义de时候。典型de例子如编译时头文件de产生规则。其他例子you体系makefile编译引导映像de特殊规则。特殊规则写法同普通deMake规则。
   Kbuild(应该是编译程序)在makefile所在de目录不能被执行,因此所youde特殊规则需要提供前提文件和目标文件de相对路径。
   定义特殊规则时将使用到两个变量:
    $(src): $(src)是对于makefile文件目录de相对路径,当使用代码树中de文件时使用该变量$(src)。
    $(obj): $(obj)是目标文件目录de相对路径。生成文件使用$(obj)变量。
    例如: #drivers/scsi/Makefile
   $(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl
    $(CPP) -DCHIP=810 - < $< | … $(src)/script_asm.pl
   这就是使用普通语法de特殊编译规则。
   目标文件依赖于两个前提文件。目标文件de前缀是$(obj), 前提文件de前缀是$(src)(因为它们不是生成文件)。
    === 4 辅助程序
   内核编译系统支持在编译(compliation)阶段编译主机可执行程序。为了使用主机程序需要两个步骤:第一个步骤使用hostprogs-y变量告诉内核编译系统you主机程序可用。第二步给主机程序添加潜在de依赖关系。you两种方法,在规则中增加依赖关系或使用$(always)变量。具体描述如下。
    --- 4.1 简单辅助程序
   在一些情况下需要在主机上编译和运行主机程序。下面这行告诉kbuild在主机上建立bin2hex程序。
    例如: hostprogs-y := bin2hex
   Kbuild假定使用makefile相同目录下de单一C代码文件bin2hex.c编译bin2hex。
    --- 4.2 组合辅助程序
   主机程序也可以由多个object文件组成。定义组合辅助程序de语法同内核对象de定义方法。
   $(<executeable>-objs)包含了所youde用于链接最终可执行程序de对象。
    例如: #scripts/lxdialog/Makefile
   hostprogs-y   := lxdialog
   lxdialog-objs := checklist.o lxdialog.o
   扩展名。o文件都编译自对应de。c文件。在上面de例子中checklist.c编译成checklist.o,lxdialog.c编译为lxdialog.o。最后两个。o文件链接成可执行文件lxdialog。
   注意:语法<executable>-y不能用于定义主机程序。
    --- 4.3 定义共享库
   扩展名为。sode对象是共享库文件,并且是位置无关deobject文件。内核编译系统提供共享库使用支持,但使用方法you限制。在下面例子中libkconfig.so库文件被链接到可执行文件conf中。
    例如: #scripts/kconfig/Makefile
   hostprogs-y   := conf
   conf-objs    := conf.o libkconfig.so
   libkconfig-objs := expr.o type.o
   共享库文件需要对应de-objs定义, 在上面例子中库libkconfig由两个对象组成:expr.o和type.o。expr.o和type.o将被编译为位置无关代码并被链接如libkconfig.so。共享库不支持C++语言。
    --- 4.4 C++语言使用方法
   内核编译系统提供了对C++主机程序de支持以用于内核配置,但不主张其它方面使用这种方法。
    例如: #scripts/kconfig/Makefile
   hostprogs-y   := qconf
   qconf-cxxobjs := qconf.o
   在上面例子中可执行文件由C++文件qconf.cc组成 - 通过$(qconf-cxxobjs)标识。
   如果qconf由。c和。cc文件混合组成,附加行表示这种情况。
    例如: #scripts/kconfig/Makefile
   hostprogs-y   := qconf
   qconf-cxxobjs := qconf.o
   qconf-objs   := check.o
    --- 4.5 辅助程序编译控制选项
   当编译主机程序时仍然可以使用$(HOSTCFLAGS)设置编译选项传递给$(HOSTCC)。这些选项将影响所you使用变量HOST_EXTRACFLAGdemakefile创建de主机程序。
    例如: #scripts/lxdialog/Makefile
   HOST_EXTRACFLAGS += -I/usr/include/ncurses
   为单个文件设置选项使用下面方式:
    例如: #arch/ppc64/boot/Makefile
   HOSTCFLAGS_piggyback.o := -DKERNELBASE=$(KERNELBASE)
   也可以使用附加链接选项:
    例如: #scripts/kconfig/Makefile
   HOSTLOADLIBES_qconf := -L$(QTDIR)/lib
   当链接qconf时将使用外部选项"-L$(QTDIR)/lib"。
    --- 4.6 何时建立辅助程序
   只you当需要时内核编译系统才会编译主机程序。you两种方式:
    (1) 在特殊规则中作为隐式de前提需求
    例如: #drivers/pci/Makefile
    hostprogs-y := gen-devlist
   $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist
    ( cd $(obj); ./gen-devlist ) < $<
   编译目标文件$(obj)/devlist.h需要先建立$(obj)/gen-devlist。注意在特殊规则中使用主机程序必须加前缀$(obj)。
    (2) 使用$(always)
   当没you合适de特殊规则可以使用,并且在进入makefile文件时就要建立主机程序,可以使用变量$(always)。
    例如: #scripts/lxdialog/Makefile
   hostprogs-y   := lxdialog
   always    := $(hostprogs-y)
   这样就告诉内核编译系统即使没you任何规则使用lxdialog也要编译它。
    --- 4.7 使用hostprogs-$(CONFIG_FOO)
   在Kbuild文件中典型模式如下:

. . .


    例如: #scripts/Makefile
   hostprogs-$(CONFIG_KALLSYMS) += kallsyms
   对Kbuild来说'y'用于内嵌对象'm'用于模块。
   因此如果config符号是'm',编译系统也将创建该程序。换句话说内核编译系统等同看待hostprogs-m和hostprogs-y。但如果不涉及到CONFIG符号仅建议使用hostprogs-y。
    === 5 编译清除机制
    "make clean"命令删除在编译内核生成de大部分文件,例如主机程序,列举在 $(hostprogs-y)、$(hostprogs-m)、$(always)、$(extra-y)和$(targets)中目标文件都将被删除。代码目录数中de"*.[oas]"、"*.ko"文件和一些由编译系统产生de附加文件也将被删除。
   附加文件可以使用$(clean-files)进行定义。
    例如: #drivers/pci/Makefile
    clean-files := devlist.h classlist.h
    当执行"make clean"命令时, "devlist.h classlist.h"两个文件将被删除。内核编译系统默认这些文件与makefile具you相同de相对路径,否则需要设置以'/'开头de绝对路径。
   删除整个目录使用以下方式:
    例如: #scripts/package/Makefile
    clean-dirs := $(objtree)/debian/
   这样就将删除包括子目录在内de整个debian目录。如果不使用以'/'开头de绝对路径内核编译系统见默认使用相对路径。
   通常内核编译系统根据"obj-* := dir/"进入子目录,但是在体系makefile中需要显式使用如下方式:
    例如: #arch/i386/boot/Makefile
    subdir- := compressed/
   上面赋值语句指示编译系统执行"make clean"命令时进入compressed/目录。
   在编译最终de引导映像文件demakefile中you一个可选de目标对象名称是archclean。
    例如: #arch/i386/Makefile
   archclean:
    $(Q)$(MAKE) $(clean)=arch/i386/boot
    当执行"make clean"时编译器进入arch/i386/boot并象通常一样工作。arch/i386/boot中demakefile文件可以使用subdir-标识进入更下层de目录。
    注意1: arch/$(ARCH)/Makefile不能使用"subdir-",因为它被包含在顶层makefile文件中,在这个位置编译机制是不起作用de。
    注意2: 所you列举在core-y、libs-y、drivers-y和net-y中de目录将被"make clean"命令清除。
    === 6 体系Makefile文件
   在开始进入各个目录编译之前,顶层makefile文件设置编译环境和做些准备工作。顶层makefile文件包含通用部分,arch/$(ARCH)/Makefile包含该体系架构所需de设置。因此arch/$(ARCH)/Makefile会设置一些变量和少量de目标。
   当编译时将按照以下大概步骤执行:
    1) 配置内核 => 产生 .config文件
    2) 保存内核版本到include/linux/version.h文件中
    3) 符号链接include/asm to include/asm-$(ARCH)
    4) 更新所you目标对象de其它前提文件
    - 附加前提文件定义在arch/$(ARCH)/Makefile文件中
    5) 递归进入init-* core* drivers-* net-* libs-*中de所you子目录和编译所youde目标对象
    - 上面变量值都引用到arch/$(ARCH)/Makefile文件。
    6) 链接所youdeobject文件生成vmlinux文件,vmlinux文件放在代码树根目录下。
   最开始链接de几个object文件列举在arch/$(ARCH)/Makefile文件dehead-y变量中。
    7) 最后体系makefile文件定义编译后期处理规则和建立最终de引导映像bootimage。
    - 包括创建引导记录
    - 准备initrd映像和相关处理
    --- 6.1 变量设置
   LDFLAGS     $(LD)一般选项
   选项使用于链接器de所you调用中。通常定义emulation就可以了。
    例如: #arch/s390/Makefile
   LDFLAGS   := -m elf_s390
    注意: EXTRA_LDFLAGS和LDFLAGS_$@可以进一步订制使用选项,将第7章。
   LDFLAGS_MODULE      $(LD)链接模块de选项
   LDFLAGS_MODULE通常设置$(LD)链接模块de。ko选项。
   默认为"-r"即可重定位输出文件。
   LDFLAGS_vmlinux  $(LD)链接vmlinux选项
   LDFLAGS_vmlinux定义链接最终vmlinux时链接器de选项。
   LDFLAGS_vmlinux支持使用LDFLAGS_$@。
    例如: #arch/i386/Makefile
   LDFLAGS_vmlinux := -e stext
   OBJCOPYFLAGS     objcopy选项
    当使用$(call if_changed,objcopy)转化a .o文件时,OBJCOPYFLAGS中de选项将被使用。
    $(call if_changed,objcopy)经常被用作为vmlinux产生原始de二进制文件。
    例如: #arch/s390/Makefile
   OBJCOPYFLAGS:= -O binary
   #arch/s390/boot/Makefile
   $(obj)/image: vmlinux FORCE $(call if_changed,objcopy)
   在上面例子中$(obj)/image是vmlinuxde二进制版本文件。$(call if_changed,xxx)
   de使用方法见后。
   AFLAGS   $(AS)汇编选项
   默认值见顶层Makefile文件
   针对每个体系需要另外添加和修改它。
    例如: #arch/sparc64/Makefile
    AFLAGS += -m64 -mcpu=ultrasparc
   CFLAGS     $(CC)编译器选项
   默认值见顶层Makefile文件
   针对每个体系需要另外添加和修改它。
   通常CFLAGS变量值取决于内核配置。
    例如: #arch/i386/Makefile
   cflags-$(CONFIG_M386) += -march=i386
    CFLAGS += $(cflags-y)
   许多体系Makefiles文件动态启动市场目标机器上deC编译器检测支持de选项:
   #arch/i386/Makefile
    …
   cflags-$(CONFIG_MPENTIUMII)   += $(call cc-option,\
   -march=pentium2,-march=i686) …
    # Disable unit-at-a-time mode …
    CFLAGS += $(call cc-option,-fno-unit-at-a-time)
    …
   第一个例子当config选项是'y'时将被选中。
   CFLAGS_KERNEL     $(CC)编译built-in对象de选项
   $(CFLAGS_KERNEL)包含外部C编译器选项编译本地内核代码。
   CFLAGS_MODULE     $(CC)编译模块选项
   $(CFLAGS_MODULE)包含外部C编译器选项编译可加载内核代码。
    --- 6.2 增加预设置项
    prepare: 这个规则用于列举开始进入子目录编译前需要de前提文件。通常是些包含汇编常量de头文件。
    例如:
   #arch/s390/Makefile
    prepare: include/asm-$(ARCH)/offsets.h
   在这个例子中include/asm-$(ARCH)/offsets.h将在进入子目录前编译。
   详见XXX-TODO文件描述了kbuild如何产生offset头文件。
    --- 6.3 目录表
   体系makefile文件和顶层makefile文件共同定义了如何建立vmlinux文件de变量。注意没you体系相关de模块对象定义部分:所youde模块对象都是体系无关de。
    head-y, init-y, core-y, libs-y, drivers-y, net-y
    $(head-y) 列举首先链接到vmlinuxde对象文件。
    $(libs-y) 列举了能够找到lib.a文件de目录。
   其余de变量列举了能够找到内嵌对象文件de目录。
    $(init-y) 列举de对象位于$(head-y)对象之后。
   然后是如下位置秩序:
    $(core-y), $(libs-y), $(drivers-y) 和 $(net-y)。
   顶层makefile定义了所you同用目录,arch/$(ARCH)/Makefile文件只需增加体系相关de目录。
    例如: #arch/sparc64/Makefile
    core-y += arch/sparc64/kernel/
    libs-y += arch/sparc64/prom/ arch/sparc64/lib/
   drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/
    --- 6.4 引导映像
   体系makefile文件定义了编译vmlinux文件de目标对象,将它们压缩和封装成引导代码,并复制到合适de位置。这包括各种安装命令。如何定义实际de目标对象无法为所youde体系结构提供标准化de方法。
   附加处理过程常位于arch/$(ARCH)/下deboot/目录。
   内核编译系统无法在boot/目录下提供一种便捷de方法创建目标系统文件。因此arch/$(ARCH)/Makefile要调用make命令在boot/目录下建立目标系统文件。建议使用de方法是在arch/$(ARCH)/Makefile中设置调用,并且使用完整路径引用arch/$(ARCH)/boot/Makefile。
    例如: #arch/i386/Makefile
    boot := arch/i386/boot
    bzImage: vmlinux
    $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
   建议使用"$(Q)$(MAKE) $(build)=<dir>"方式在子目录中调用make命令。
   没you定义体系目标系统文件de规则,但执行"make help"命令要列出所you目标系统文件,因此必须定义$(archhelp)变量。
    例如: #arch/i386/Makefile
    define
    archhelp echo '* bzImage    - Image (arch/$(ARCH)/boot/bzImage)'
    endef
   当执行不带参数demake命令时,将首先编译第一个目标对象。在顶层makefile中第一个目标对象是all:。
   一个体系结构需要定义一个默认de可引导映像。
    "make help"命令de默认目标是以*开头de对象。
   增加新de前提文件给all目标可以设置不同于vmlinuxde默认目标对象。
    例如: #arch/i386/Makefile
    all: bzImage
   当执行不带参数de"make"命令时,bzImage文件将被编译。
    --- 6.5 编译非内核目标
   extra-y
   extra-y定义了在当前目录下创建没you在obj-*定义de附加de目标文件。
   在extra-y中列举目标是处于两个目de:
    1) 是内核编译系统在命令行中检查变动情况
    - 当使用$(call if_changed,xxx)时
    2) 内核编译系统知道执行"make clean"命令时删除哪些文件
    例如: #arch/i386/kernel/Makefile
    extra-y := head.o init_task.o
   上面例子extra-y中de对象文件将被编译但不会练接到built-in.o中。
    --- 6.6 编译引导映像命令
   Kbuild提供了一些编译引导映像you用de宏。
   if_changed
   if_changed是后面命令使用de基础。
    用法:
    target: source(s)
    FORCE $(call if_changed,ld/objcopy/gzip)
   当这条规则被使用时它将检查哪些文件需要更新,或命令行被改变。后面这种情况将迫使重新编译编译选项被改变de执行文件。使用if_changedde目标对象必须列举在$(targets)中,否则命令行检查将失败,目标一直会编译。
   赋值给$(targets)de对象没you$(obj)/前缀。
   if_changed也可以和定制命令配合使用,见6.7"kbuild定制命令"。
    注意: 一个常见错误是忘记了FORCE前导词。
    ld
   链接目标。常使用LDFLAGS_$@作为ldde选项。
   objcopy
   复制二进制文件。常用于arch/$(ARCH)/Makefile中和使用OBJCOPYFLAGS作为选项。
   也可以用OBJCOPYFLAGS_$@设置附加选项。
    gzip
   压缩目标文件。使用最大压缩算法压缩目标文件。
    例如: #arch/i386/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)
   在上面例子中you两个可能de目标对象,分别需要不同de链接选项。使用LDFLAGS_$@语法为每个目标对象设置不同de链接选项。
   $(targets)包含所youde目标对象,因此内核编译系统知道所youde目标对象并且将:
    1) 检查命令行de改变情况
    2) 执行make clean命令时删除目标对象
    ": %: %.o"是简写方法,减写setup.o和bootsect.o文件。
    注意: 常犯错误是忘记"target :="语句,导致没you明显de原因目标文件被重新编译。
    --- 6.7 定制编译命令
   当执行带KBUILD_VERBOSE=0参数de编译命令时命令de简短信息会被显示。要让定制命令具you这种功能需要设置两个变量:
   quiet_cmd_<command> - 将被显示de内容
   cmd_<command>     - 被执行de命令
    例如: #
   quiet_cmd_image = BUILD  $@
    cmd_image = $(obj)/tools/build $(BUILDFLAGS) \
   $(obj)/vmlinux.bin > $@
    targets += bzImage
   $(obj)/bzImage: $(obj)/vmlinux.bin $(obj)/tools/build FORCE
    $(call if_changed,image)
    @echo 'Kernel: $@ is ready'
    执行"make KBUILD_VERBOSE=0"命令编译$(obj)/bzImage目标时将显示:
   BUILD  arch/i386/boot/bzImage
    --- 6.8 预处理连接脚本
   当编译vmlinux映像时将使用arch/$(ARCH)/kernel/vmlinux.lds链接脚本。
   相同目录下devmlinux.lds.S文件是这个脚本de预处理de变体。内核编译系统知晓。lds文件并使用规则*lds.S -> *lds。
    例如: #arch/i386/kernel/Makefile
    always := vmlinux.lds
   #Makefile
    export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
   $(always)赋值语句告诉编译系统编译目标是vmlinux.lds。$(CPPFLAGS_vmlinux.lds)赋值语句告诉编译系统编译vmlinux.lds目标de编译选项。
   编译*.lds时将使用到下面这些变量:
   CPPFLAGS     : 定义在顶层Makefile
   EXTRA_CPPFLAGS     : 可以设置在编译demakefile文件中
   CPPFLAGS_$(@F) : 目标编译选项。注意要使用文件全名。
    --- 6.9 $(CC)支持功能
   内核可能会用不同版本de$(CC)进行编译,每个版本you不同de性能和选项,内核编译系统提供基本de支持用于验证$(CC)选项。$(CC)通常是gcc编译器,但其它编译器也是可以。
    cc-option cc-option 用于检测$(CC)是否支持给定de选项,如果不支持就使用第二个可选项。
    例如: #arch/i386/Makefile
    cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
   在上面例子中如果$(CC)支持-march=pentium-mmx则cflags-y等于该值,否则等于-march-i586。如果没you第二个可选项且第一项不支持则cflags-y没you被赋值。
    cc-option-yn cc-option-yn用于检测gcc是否支持给定de选项,支持返回'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。
   cc-option-align gcc版本>= 3.0用于定义functions、loops等边界对齐选项。
    gcc < 3.00
   cc-option-align = -malign
    gcc >= 3.00
   cc-option-align = -falign
    例如:
    CFLAGS += $(cc-option-align)-functions=4
    在上面例子中对于gcc >= 3.00来说-falign-functions=4,gcc < 3.00版本使用-malign-functions=4。
    cc-version cc-version返回$(CC)编译器数字版本号。
   版本格式是<major><minor>,均为两位数字。例如gcc 3.41将返回0341。
   当一个特定$(CC)版本在某个方面you缺陷时cc-version是很you用de。例如-mregparm=3在一些gcc版本会失败尽管gcc接受这个选项。
    例如: #arch/i386/Makefile
    GCC_VERSION := $(call cc-version)
    cflags-y += $(shell \
    if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
   在上面例子中-mregparm=3只使用在版本大于等于3.0degcc中。
    === 7 Kbuild变量
   顶层Makefile文件导出下面这些变量:
    VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
   这几个变量定义了当前内核版本号。很少体系体系Makefiles文件直接使用他们,常用$(KERNELRELEASE)代替。
   $(VERSION)、$(PATCHLEVEL)和$(SUBLEVEL)定义了三个基本部分版本号,例如"2", "4",和"0"。这三个变量一直使用数值表示。
   $(EXTRAVERSION)定义了更细de补钉号,通常是短横跟一些非数值字符串,例如"-pre4"。
   KERNELRELEASE
   $(KERNELRELEASE)是一个单一字符如"2.4.0-pre4",适合用于构造安装目录和显示版本字符串。一些体系文件使用它用于以上目de。
    ARCH
   这个变量定义了目标系统体系结构,例如"i386"、“arm"、"sparc". 一些内核编译文件测试$(ARCH)用于确定编译哪个文件。默认情况下顶层Makefile文件设置$(ARCH)为主机相同de系统体系。当交叉编译编译时,用户可以使用命令行改变$(ARCH)值:
    make ARCH=m68k …
   INSTALL_PATH
   这个变量定义了体系Makefiles文件安装内核映项和System.map文件de路径。
   INSTALL_MOD_PATH, MODLIB
   $(INSTALL_MOD_PATH)定义了模块安装变量$(MODLIB)de前缀。这个变量通常不在Makefile文件中定义,如果需要可以由用户添加。
   $(MODLIB)定义了模块安装目录。
   顶层Makefile定义$(MODLIB)为$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)。用户可以使用命令行修改这个值。
    === 8 Makefile语言
   内核Makefiles设计目标用于运行GNU Make程序。Makefiles仅使用GNU Make提到de特性,但使用了较多deGNU扩展部分。
    GNU Make程序支持基本de列表处理功能。内核Makefiles文件结合"if"语句使用了简单de列表建立和维护功能。
    GNU Make程序you两种赋值操作符:":="和"="。 ":="执行时立即计算右值并赋值给左值。"="类似公式定义,当每次使用左值要被使用时计算右值并赋给它。
   一些情况中使用"="合适,而一些情况中使用":="才是正确选择。
    === 9 Credits
    Original version made by Michael Elizabeth Chastain, <mailto:mec@shout.net> Updates
    by Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> Updates by Sam Ravnborg <sam@ravnborg.org>
    === 10 TODO
    - Describe how kbuild support shipped files with _shipped.
    - Generating offset header files.
    - Add more variables to section 7?

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值