Chinaunix首页 | 论坛 | 博客
  • 博客访问: 568662
  • 博文数量: 185
  • 博客积分: 4031
  • 博客等级: 上校
  • 技术积分: 1591
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-27 19:45
文章分类

全部博文(185)

文章存档

2011年(14)

2010年(63)

2009年(108)

我的朋友

分类:

2009-08-07 18:26:52

Linux内核Makefile文件(二)

默认分类   2008-05-30 12:42   阅读2   评论0  
字号:    
Linux内核Makefile文件(二)
2008年05月30日 星期五 11:50

=== 6 体系Makefile文件

在开始进入各个目录编译之前,顶层Makefile文件设置编译环境和做些准备工作。顶层Makefile文件包含通用部分,arch/$ (ARCH) /Makefile包含该体系架构所需的设置。因此arch/$(ARCH)/Makefile会设置一些变量和少量的目标。

当编译时将按照以下大概步骤执行:
1) 配置内核 => 产生 .config文件
2) 保存内核版本到include/linux/version.h文件中
3) 符号链接include/asm to include/asm-$(ARCH)
4) 更新所有目标对象的其它前提文件
- 附加前提文件定义在arch/$(ARCH)/Makefile文件中
5) 递归进入init-* core* drivers-* net-* libs-*中的所有子目录和编译所有的目标对象
- 上面变量值都引用到arch/$(ARCH)/Makefile文件。
6) 链接所有的object文件生成vmlinux文件,vmlinux文件放在代码树根目录下。
最开始链接的几个object文件列举在arch/$(ARCH)/Makefile文件的head-y变量中。
7) 最后体系Makefile文件定义编译后期处理规则和建立最终的引导映像bootimage。
- 包括创建引导记录
- 准备initrd映像和相关处理

--- 6.1 变量设置

LDFLAGS      $(LD)一般选项

     选项使用于链接器的所有调用中。通常定义emulation就可以了。

     Example:
             #arch/s390/Makefile
             LDFLAGS   := -m elf_s390

     注意: EXTRA_LDFLAGS和LDFLAGS_$@可以进一步订制使用选项,请参考第7章。

LDFLAGS_MODULE       $(LD)链接模块的选项

     LDFLAGS_MODULE通常设置$(LD)链接模块的.ko选项。默认为"-r"即可重定位输出文件。

LDFLAGS_vmlinux   $(LD)链接vmlinux选项

     LDFLAGS_vmlinux定义链接最终vmlinux时链接器的选项。LDFLAGS_vmlinux支持使用LDFLAGS_$@。

     Example:
             #arch/i386/Makefile
             LDFLAGS_vmlinux := -e stext

OBJCOPYFLAGS      objcopy选项

     当使用$(call if_changed,objcopy)转化a .o文件时,OBJCOPYFLAGS中的选项将被使用。$(call if_changed,objcopy)经常被用作为vmlinux产生原始的二进制文件。

     Example:
             #arch/s390/Makefile
             OBJCOPYFLAGS := -O binary

             #arch/s390/boot/Makefile
             $(obj)/image: vmlinux FORCE
                      $(call if_changed,objcopy)

     在上面例子中$(obj)/image是vmlinux的二进制版本文件。$(call if_changed,xxx)的使用方法见后。

AFLAGS   $(AS)汇编选项

     默认值见顶层Makefile文件。针对每个体系需要另外添加和修改它。

     Example:
             #arch/sparc64/Makefile
             AFLAGS += -m64 -mcpu=ultrasparc

CFLAGS      $(CC)编译器选项

     默认值见顶层Makefile文件。针对每个体系需要另外添加和修改它。

     通常CFLAGS变量值取决于内核配置。

     Example:
             #arch/i386/Makefile
             cflags-$(CONFIG_M386) += -march=i386
             CFLAGS += $(cflags-y)

     许多体系Makefiles文件动态启动市场目标机器上的C编译器检测支持的选项:

           #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对象的选项

     $(CFLAGS_KERNEL)包含外部C编译器选项编译本地内核代码。

CFLAGS_MODULE      $(CC)编译模块选项

     $(CFLAGS_MODULE)包含外部C编译器选项编译可加载内核代码。

--- 6.2 增加预设置项

     prepare: 这个规则用于列举开始进入子目录编译前需要的前提文件。通常是些包含汇编常量的头文件。
     prepare: 这个规则用于列举开始进入子目录编译前需要的前提文件。通常是些包含汇编常量的头文件。

     Example:
             #arch/s390/Makefile
             prepare: include/asm-$(ARCH)/offsets.h

     在这个例子中include/asm-$(ARCH)/offsets.h将在进入子目录前编译。详见XXX-TODO文件描述了kbuild如何产生offset头文件。

--- 6.3 目录表

     体系Makefile文件和顶层Makefile文件共同定义了如何建立vmlinux文件的变量。注意没有体系相关的模块对象定义部分:所有的模块对象都是体系无关的。

head-y, init-y, core-y, libs-y, drivers-y, net-y

     $(head-y) 列举首先链接到vmlinux的对象文件。
     $(libs-y) 列举了能够找到lib.a文件的目录。
     其余的变量列举了能够找到内嵌对象文件的目录。

     $(init-y) 列举的对象位于$(head-y)对象之后。
     然后是如下位置秩序:
     $(core-y), $(libs-y), $(drivers-y) 和 $(net-y)。

     顶层Makefile定义了所有同用目录,arch/$(ARCH)/Makefile文件只需增加体系相关的目录。

     Example:
             #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文件的目标对象,将它们压缩和封装成引导代码,并复制到合适的位置。这包括各种安装命令。如何定义实际的目标对象无法为所有的体系结构提供标准化的方法。

     附加处理过程常位于arch/$(ARCH)/下的boot/目录。

     内核编译系统无法在boot/目录下提供一种便捷的方法创建目标系统文件。因此arch/$(ARCH)/Makefile要调用make命令在 boot/目录下建立目标系统文件。建议使用的方法是在arch/$(ARCH)/Makefile中设置调用,并且使用完整路径引用arch/$ (ARCH)/boot/Makefile。

     Example:
             #arch/i386/Makefile
             boot := arch/i386/boot
             bzImage: vmlinux
                     $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

     建议使用"$(Q)$(MAKE) $(build)=

"方式在子目录中调用make命令。
     没有定义体系目标系统文件的规则,但执行"make help"命令要列出所有目标系统文件,因此必须定义$(archhelp)变量。

     Example:
             #arch/i386/Makefile
             define archhelp
               echo '* bzImage     - Image (arch/$(ARCH)/boot/bzImage)'
             endef

     当执行不带参数的make命令时,将首先编译第一个目标对象。在顶层Makefile中第一个目标对象是all:。
     一个体系结构需要定义一个默认的可引导映像。
     "make help"命令的默认目标是以*开头的对象。
     增加新的前提文件给all目标可以设置不同于vmlinux的默认目标对象。

     Example:
           #arch/i386/Makefile
           all: bzImage

     当执行不带参数的"make"命令时,bzImage文件将被编译。

--- 6.5 编译非内核目标

extra-y

     extra-y定义了在当前目录下创建没有在obj-*定义的附加的目标文件。

     在extra-y中列举目标是处于两个目的:
      1) 是内核编译系统在命令行中检查变动情况
        - 当使用$(call if_changed,xxx)时
      2) 内核编译系统知道执行"make clean"命令时删除哪些文件

     Example:
             #arch/i386/kernel/Makefile
             extra-y := head.o init_task.o

     上面例子extra-y中的对象文件将被编译但不会练接到built-in.o中。

--- 6.6 编译引导映像命令

     Kbuild提供了一些编译引导映像有用的宏。

if_changed

     if_changed是后面命令使用的基础。

     用法:
        target: source(s)
            FORCE $(call if_changed,ld/objcopy/gzip)

     当这条规则被使用时它将检查哪些文件需要更新,或命令行被改变。后面这种情况将迫使重新编译编译选项被改变的执行文件。使用if_changed的目标对象必须列举在$(targets)中,否则命令行检查将失败,目标一直会编译。
     赋值给$(targets)的对象没有$(obj)/前缀。
     if_changed也可以和定制命令配合使用,见6.7"kbuild定制命令"。

     注意: 一个常见错误是忘记了FORCE前导词。

ld
      链接目标。常使用LDFLAGS_$@作为ld的选项。

objcopy
      复制二进制文件。常用于arch/$(ARCH)/Makefile中和使用OBJCOPYFLAGS作为选项。
     也可以用OBJCOPYFLAGS_$@设置附加选项。

gzip
      压缩目标文件。使用最大压缩算法压缩目标文件。

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

      在上面例子中有两个可能的目标对象,分别需要不同的链接选项。使用LDFLAGS_$@语法为每个目标对象设置不同的链接选项。
     $(targets)包含所有的目标对象,因此内核编译系统知道所有的目标对象并且将:
      1) 检查命令行的改变情况
      2) 执行make clean命令时删除目标对象

     ": %: %.o"是简写方法,减写setup.o和bootsect.o文件。

     注意: 常犯错误是忘记"target :="语句,导致没有明显的原因目标文件被重新编译。

--- 6.7 定制编译命令

     当执行带KBUILD_VERBOSE=0参数的编译命令时命令的简短信息会被显示。要让定制命令具有这种功能需要设置两个变量:
     quiet_cmd_ - 将被显示的内容
      cmd_      - 被执行的命令

     Example:
             #
             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链接脚本。
     相同目录下的vmlinux.lds.S文件是这个脚本的预处理的变体。内核编译系统知晓.lds文件并使用规则*lds.S -> *lds。

    Example:
            #arch/i386/kernel/Makefile
            always := vmlinux.lds
            #Makefile
            export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)

     $(always)赋值语句告诉编译系统编译目标是vmlinux.lds。$(CPPFLAGS_vmlinux.lds)赋值语句告诉编译系统编译vmlinux.lds目标的编译选项。

    编译*.lds时将使用到下面这些变量:
     CPPFLAGS      : 定义在顶层Makefile
     EXTRA_CPPFLAGS      : 可以设置在编译的Makefile文件中
     CPPFLAGS_$(@F) : 目标编译选项。注意要使用文件全名。


=== 7 Kbuild变量

顶层Makefile文件导出下面这些变量:

VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION

     这几个变量定义了当前内核版本号。很少体系体系Makefiles文件直接使用他们,常用$(KERNELRELEASE)代替。

     $(VERSION)、$(PATCHLEVEL)和$(SUBLEVEL)定义了三个基本部分版本号,例如"2", "4",和"0"。这三个变量一直使用数值表示。

     $(EXTRAVERSION)定义了更细的补钉号,通常是短横跟一些非数值字符串,例如"-pre4"。

KERNELRELEASE

    $(KERNELRELEASE)是一个单一字符如"2.4.0-pre4",适合用于构造安装目录和显示版本字符串。一些体系文件使用它用于以上目的。

ARCH

    这个变量定义了目标系统体系结构,例如"i386"、“arm"、"sparc". 一些内核编译文件测试$(ARCH)用于确定编译哪个文件。默认情况下顶层Makefile文件设置$(ARCH)为主机相同的系统体系。当交叉编译编译 时,用户可以使用命令行改变$(ARCH)值:

       make ARCH=m68k ...

INSTALL_PATH

     这个变量定义了体系Makefiles文件安装内核映项和System.map文件的路径。

INSTALL_MOD_PATH, MODLIB

     $(INSTALL_MOD_PATH)定义了模块安装变量$(MODLIB)的前缀。这个变量通常不在Makefile文件中定义,如果需要可以由用户添加。
     $(MODLIB)定义了模块安装目录。
     顶层Makefile定义$(MODLIB)为$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)。用户可以使用命令行修改这个值。


=== 8 Makefile语言

内核Makefiles设计目标用于运行GNU Make程序。Makefiles仅使用GNU Make提到的特性,但使用了较多的GNU扩展部分。

GNU Make程序支持基本的列表处理功能。内核Makefiles文件结合"if"语句使用了简单的列表建立和维护功能。

GNU Make程序有两种赋值操作符:":="和"="。 ":="执行时立即计算右值并赋值给左值。"="类似公式定义,当每次使用左值要被使用时计算右值并赋给它。

一些情况中使用"="合适,而一些情况中使用":="才是正确选择。


=== 9 Credits

Original version made by Michael Elizabeth Chastain, <>
Updates by Kai Germaschewski <>
Updates by Sam Ravnborg <>

=== 10 TODO

- Describe how kbuild support shipped files with _shipped.
- Generating offset header files.
- Add more variables to section 7?

阅读(763) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~