一下内容全部来自于:linux内核源码包中的Documentation/kbuild/makefiles文档中的内容。

1.  在linux的每个目录中都会存在一个Makefile文件。而个根目录下面的Makefile文件为最顶层的Makefile文件。当我们在编译内核的时候,linux中的kbuild系统会从最顶层的Makefile文件开始,然后嵌入到最底层的文件中的Makefile文件中。最后在回到最顶层的Makefile文件之中。

   

2.  当在一个目录中既存在Makefile文件又存在Kbuild文件时,内核中的kbuild构建系统默认情况下使用的是Kbuild文件。


3 内核的构建文件

3.1 定义目标

定义目标是内核构建系统中的Makefile文件的主要部分。

    例如: obj-y += foo.o

    这个 obj-y += foo.o是告诉内核的构建系统(kbuild)在相应的目录下面有一个foo.o的目标文件,并且这个foo.o文件最后会被放入到vmlinux文件之中。而这个foo.o的目标文件是 通过对相应的foo.c文件进行编译形成的。

    例如:obj-m += foo.o

    这个 obj-m += foo.o是告诉内核的构建系统(kbuild)在相应的目录下面有一个foo.o的目标文件,并且这个foo.o文件最后会被编译成一个可加载的内核模块。

    通过以上可知,一个目标文件既可以直接编译到内核之中也可以将其编译到一个可加载的目标模块之中,然后通过加载这个目标模块来让目标文件进行运行。所以内核采用了下面的格式来同以上两种做法进行统一:

    obj-$(CONFIG_FOO) += foo.o

    当$(CONFIG_FOO)=y时,将其编译到内核之中;

    当$(CONFIG_FOO)=m时,将其编译到成一个可加载的内核模块。


3.2 obj-y用于将目标文件构建在linux内核之中

     linux内核构建系统(kbuild)最后编译$(obj-y)中的所有文件,然后调用“$(LD) -r”将$(obj-y)中的所有的目标文件合并为一个"build-in.o"文件。之后,上层的Makefile文件会将build-in.o文件链接到vmlinux文件之中。

          

3.3 obj-m可加载的目标模块

    linux的kbuild构建系统会把$(obj-m)中的目标文件构建为可加载的内核模块。

    在构建可加载的linux内核模块时,有可能这个可加载的内核模块只需要一个源文件,也可能需要多个不同的源文件。

    当一个可加载的内核模块只需要一个源文件时,可以通过如下的方式:

    obj-m += isdn_bsdcmp.o

    是告诉linux的内核构建系统(kbuild),将当前目录下面的

    isdn_bsdcmp.o目标文件构建成一个可加载的内核模块

    当一个可加载的内核模块需要多个源文件时,可以通过如下的方式来告诉linux的内核构建系统(kbuild),这个可加载的内核模块需要依赖于哪些源文件。

    obj-$(CONFIG_ISDN) += isdn.o

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

    $(obj-m)中的文件最终会被编译为一个可加载的内核模块。

    obj-m += isdn.o是告诉linux的内核构建系统(kbuild)将isdn.o的目标文件构建成一个可加载的内核模块。而这个isdn可加载的内核模块需要依赖于isdn_net_lib.o isdn_v110.o isdn_common.o文件。 isdn-objs就是告诉linux的内核构建系统(kbuild)isdn目标模块需要依赖那些模块。

    $(module_name-objs)用于指定模块所需要依赖的目标文件。 


3.6 Descending down in directories

    在一个目录下的Makefile文件只负责在自己所在的目录下面构建目标。但是我们经常在看到的是:在一个目录下面还有其他的目录存在,那么在父目录下面的Makefile文件是如果调用make去执行子目录下面的Makefile文件的。

    例如:

         #fs/Makefile

         obj-$(CONFIG_EXT2_FS) += ext2/

     当$(CONFIG_EXT2_FS)=y或$(CONFIG_EXT2_FS)=m时,只是用来告诉linux的内核构建系统kbuild要去执行ext/目录下面的Makefile文件了。而ext2/目录下面的Makefile文件中的规则规定了是将ext2/目录下面的文件编译到build-in.o之中(obj-y),还是编译成可加载的内模块(obj-m)。

     当$(CONFIG_EXT2_FS)既不是"y"也不是"m"时,父目录下面的Makefile文件是不会却换到ext2/目录下面去的。   


3.7 编译标识符

    在linux内核构建的过程中,要用到的编译器为"gcc", 要用到的汇编为"as", 要用到的链接器为"ld"。然而,在编译linux内核的过程中,要编译不同的文件而有的文件需要不同的编译选项。那么如果将文件的编译选项告诉给相应的编译器?

    在linux内核的最顶层目录也就是根目录下面的Makefile文件中,有一个变量"KBUILD_CFLAGS",这个$(KBUILD_CFLAGS)中存放的是传递给gcc编译器的编译选项,如果被编译的文件在被gcc编译时,没有特殊的要求的话就会使用$(KBUILD_CFLAGS)中的编译选项。

    但是如果被gcc编译的文件有特殊的编译选项要求的话,使用如下的方式来指定编译选项:

    ccflags-y,是指定给$(CC)的编译选项;

    asflags-y,是指定给$(AS)的编译选项;

    ldflags-y,是指定给$(LD)的编译选项;

    例如:

         #drivers/sound/emu10k1/Makefile

         ccflags-y += -I$(obj) "-I"后面跟的是目录。


    在一个Makefile文件中可能会产生多个目标文件,但是在使用$(CC)产生每一个目标文件时,都需要不同的编译选项。可以使用如下的方法:

    CFLAGS_$@, AFLAGS_$@;

    例如:

         CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF

         CFLAGS_gdth.o  =  #-DDEBUG_GDTH=2

         CFLAGS_seagate.o = -DARBITRATE

    在产生aha152x.o gdth.o seagate.o目标文件时,会使用相应的编译选项。


3.9 依赖性追踪

    linux中的内核构建系统kbuild按照下面的格式来追踪文件与文件间的依赖性:

    1) 所有首先必须要的文件(.c和.h)

    2)在所有首先必须要的文件中的CONFIG_选项

    3)被用于编译目标的命令行


3.10 特殊的规则

    linux内核的构建过程中,有两个地方需要使用特殊规则:

    第一种是:对内核编译过程中产生的头文件(目标文件)的引用;

    第二中是:与体系结构相关的Makefile文件(首先必须要的文件);

    

    无论是对linux内核编译过程中产生的头文件的引用,还是对内核源码中本来就存在的Makefile文件的引用,都需要使用的是相对路径。

    $(src)中存放的是所要引用的Makefile文件所在目录的相对路径。如果要引用linux源码树中的文件的话,就要使用$(src);

    $(obj)中存放的将要引用的目标文件所在的目录的相对目录。如果要引用在linux内核编译过程中产生的文件,就要使用$(obj);

     例如:

         #drivers/scsi/Makefile

         $(obj)/53c8xx.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl

    引用53c8xx.h这个在linux内核编译过程中产生的头文件,而这个53c8xx.h目标文件位于$(obj)目录之下;而这个53c88xx.h头文件的产生,需要引用源码树中的script_asm.pl文件。script_asm.pl文件位于$(src)之下。


3.11 $(CC)支持的功能

    由于linux内核使用若干个不同的版本的编译器"$(CC)"进行编译,并且每一个版本的编译器都会支持一些独一无二的功能和选项。所以linux的内核构建系统kbuild就提供了一些基本的功能去检测提供给"$(CC)"的选项是否有效。"$(CC)"经常使用的是"gcc"编译器。

   1) as-option

      当"$(CC)"被用于去编译汇编代码时,"as-option"被用于去检测提供给"$(CC)"汇编编译器的选项是否被支持。

      例如:

          #arch/sh/Makefile

          cflags-y += $(call as-option, -Wa$(comma)-isa=$(isa-y),)

          当"$(CC)"用来编译汇编代码时,通过"call"来调用"as-option"来判断"-Wa$(comma)-isa=$(isa-y)"是否被支持,如果被支持"cflags-y += -Wa$(comma)-isa=$(isa-y)",否则的话如果提供可第二选项的话,"cflags-y +=提供的第二个选项"

   2) cc-ldoption

     当"$(CC)"被用于去链接目标文件时,可以通过"cc-ldoption"来判断提供给连接器的选项是否被支持。

     例如:

         #arch/i386/kernel/Makefile

         vsyscall-flags += $(call cc-ldoption, -Wl$(comma)--hash- 

                            style=syv)

         当"$(CC)"被用于链接目标文件时,通过"call"调用"cc-ldoption"来判断提供给连接器的"-Wl$(comma)--hash-style=syv"选项是否被支持。如果被支持的话,"vsyscall-flags += -Wl$(comma)--hash-style=syv"。如果同时也提供了第二选项,当第一个选项不被支持的话"vsyscall-flags +=第二个选项"

   3) cc-option

     同样,"cc-option"也是用来判读提供给"$(CC)"的选项是否被支持,如果不被支持的话使用提供的第二个选项。

     例如:

         #arch/i386/Makefile

         cflags-y +=$(call cc-option, -march=pentium-mmx, -march=i586)

         当"-march=pentium-mmx"被支持的话,"cflags-y += -march=pentium-mmx",否则的话"cflags-y += -march=i586"。

    须知:"cc-option"对"$(CC)"使用"KBUILD_CFLAGS"。

   4) cc-option-yn

     "cc-option-yn"被用于去检测提供给gcc的选项是否被支持,如果被支持的话返回"y",否则返回"n"。

     例如:

         #arch/ppc/Makefile

         biarch := $(call cc-option, -m32)

         aflags-$(biarch) += -a32

         cflags-$(biarch) += -m32

         如果gcc支持"-m32"选项的话,"biarch := y"

         aflags-y += -a32

         cflags-y += -m32

    须知:"cc-option-yn"对"$(CC)"使用"KBUILD_CFLAGS"

   5) cc-version

     "cc-version"用于返回"$(CC)"编译器的版本数字号。编译器版本数字号的格式为:<major><minor>。例如gcc 3.41,则其版本数字号为"0341"。

     例如:

          #arch/i386/Makefile

          cflags-y += $(shell  if [ $(call cc-version) -ge 0300 ] ;\

                    then echo "-mreparm=3";fi;)

          如果当前使用的gcc编译器的版本大于gcc 3.0的话,则"cflags-y += -mregparm=3"。

   6) cc-ifversion

      例如:

           cflags-y := $(call cc-ifversion, -lt, 0402, -O1)

           通过"call"调用"cc-ifversion"来判断当前的gcc编译器的版本号是否小于gcc 4.2版本。如果小于的话,"cflags-y := -O1"。

      shell脚本中用于两个数比较的符号位:

      -eq : 等于(equal)

      -ne : 不等于(not equal)

      -lt : 小于(less than)

      -le : 小于等于(less equal)

      -gt : 大于(greate than)

      -ge : 大于等于(greate equal)

    

   7) cc-fullversion

      例如:

           #arch/powerpc/Makefile

           $(Q)if test "$(call cc-fullversion)" = "040200";then \

             echo -n '***GCC-4.2.0 cannot compile the 64-bit powerpc';\

             false;\

             fi

    

   8) cc-cross-prefix

      "cc-cross-prefix"用于检测在$PATH之中是否存在相应的编译器前缀。如果存在的话,返回相应的编译器前缀。如果不存在的话,就什么都不返回。

      当我们进行交叉编译时:应该通过设置"CROSS_COMPILE"中的值来实现。

      例如:

           #arch/m68K/Makefile

           ifneq($(SUBARCH),$(ARCH)) //如果$(SUBARCH) != $(ARCH)

               ifeq($(CROSS_COMPILE),) // 如果$(CROSS_COMPILE)为空

                   CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux- 

                                      gnu-)

                endif

            endif    

          通过"call"调用"cc-cross-prefix"来判断在$PATH之中是否存在"m68k-linux-gnu-"编译器前缀,如果存在的话"CROSS_COMPILE := m68k-linux-gnu-"。



4 Host Program 支持

   linux的内核构建系统kbuild支持在主机正在处于编译阶段的时候,构建host executales。

   那些为了使用这些host executables,需要两步:

   第一步:告诉linux内核构建系统kbuild存在host executable programs。方法是:通过使用"hostprogs-y"变量。

   第二步:显示的添加对这个host executable program程序的依赖关系。方法是:

        1) 添加一条依赖规则;

        2) 使用"$(always)"变量。


4.1 简单的host program

    在一些情况下,当计算机的kbuild处于构建内核阶段的过程中时,这个kbuild系统需要编译并且运行一个程序。

    例如:

         hostprogs-y := bin2hex(这个是一个可执行的二进制文件,而不是一个目标文件啊)

         这行规则用于告诉linux的构建系统kbuild,这个bin2hex在编译完成以后需要在当前的主机上运行。


4.2 复合host program

    $<executable>-objs后面列出所有依赖的目标文件。

    例如:

         hostprogs-y := lxdiag

         lxdiag-objs := checlist.o lxdiag.o

         checklist.c文件被编译而产生checklist.o文件

         lxdiag.c 文件被编译而产生lxdiag.o文件

         checklist.o lxdiag.o这两个文件最后会被链接成一个可执行的lxdiag文件


4.3 定义共享库

    在linux之中,所有的"*.so"文件都是共享库文件。并且这些共享库文件会被编译成位置无关的对象。

    linux的内核构建系统kbuild提供了对共享库的支持。

    例如:

         hostprogs-y := conf

         conf-objs := conf.o libkconfig.so

         libconfig-objs := expr.o type.o

         链接conf.o和共享库文件libkconfig.so形成conf可执行文件。但是共享库文件libkconfig.so文件依赖于expr.o type.o这两个目标文件。

         由于共享库文件是一种位置无关的对象,所有它所依赖的目标文件也会被构建成为一种位置无关的代码。


4.4 控制对host program的编译器选项

    当编译host program时,可以需要设置指定的编译选项。

    host program程序的编译器可以通过"$(HOSTCC)"来指定,而传递个"$(HOSTCC)"

编译器的编译器选项可以通过"$(HOSTCFLAGS)"来指定。

    为了使设置的"$(HOSTCC)"编译器选项对相应的Makefile文件产生的host programs程序都起作用,可以使用"HOST_EXTRACFLAGS"变量。

    例如: 

         #scripts/lxdiaog/Makefile

         HOST_EXTRACFLAGS += -I/usr/include/ncurse

    为了使设置的"$(HOSTCC)"编译器选项只对一个单独的文件起作用,可以使用如下的方法:

    例如:

         #arch/ppc64/boot/Makefile

         HOSTCFLAGS_piggback.o := -DKERNELBASE=$(KERNELBASE)


4.5 host programs程序的构建时机

   (1) 当在linux内核构建的过程中产生的一个文件需要引用这个host program时,host program才会被构建。

       例如:

            #driver/pci/Makefile

            hostprogs-y := gen-devlist

            $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist

               (cd $(obj); ./gen-devlist) < $<

            在linux内核的构建过程中会产生一个devlist.h文件,而这个devlist.h

文件要引用源码树中的pci.ids文件,可构建过程中形成的可执行文件gen-devlist。此时linux的构建系统才会开始构建gen-devlist这个可执行文件。

    (2) 使用$(always)

        当在一个Makefile文件中使用了$(always)时,kbuild就会构建相应的可执行文件。

        例如:

             #scripts/lxdialog/Makefile

             hostprogs-y := lxdialog

             always      := $(hostprogs-y)

             当kbuild在Makefile文件中看到了always这个变量后,他就会构建这个lxdialog可执行文件。


4.7 使用hostprogs-$(CONFIG_FOO)

    例如:

         #scripts/Makefile

          hostprogs-$(CONFIG_KALLSYMS) += kallsyms

         上面的这种格式是在Kbuild文件中看到的一种常用形式。而无论$(CONFIG_KALLSYMS)=m还是$(CONFIG_KALLSYMS)=y,都会产生kallsyms这个可执行文件。

     

5 kbuild清除infrastructure

   "make clean"会清除在编译内核的过程中所产生的大多数文件(也包括在编译过程中形成的host programs程序)。linux的内核构建系统kbuild知道在linux编译过程中产生的文件都会存放在$(hostprogs-m)、$(hostprogs-y)、 $(always)  $(extra-y)、$(targets)这些变量之中。在执行"make clean"时,会删除以上几个变量之中的文件。

    当想通过"make clean"去删除其它的文件的话,可以使用如下方式:

    例如:

         #drivers/pci/Makefile

         clean-files := devlist.h classlist.h

         当然如果devlist.h classlist.h与Makefile不是在同一个目录下时,devlist.h classlist.h就要使用绝对路径。

    当想通过"make clean"去删除一个目录的话,可以使用如下的方式:

    例如:

        #scripts/package/Makefile

         clean-dirs := $(objtree)/debain/

         当执行"make clean"时,会删除$(objtress)下面的debain目录,以及debain下面的所有的目录。


6 与体系结构相关的Makefile文件

    在linux源代码包中的最顶层的Makefile文件主要的工作是设置环境变量和做一些为进入到下一次Makefile文件的准备工作。

    在linux源代码包的最顶层的Makefile文件包含的是适合各种体系结构的通用部分,而arch/$(ARCH)/Makefile文件中包含的是与自身体系结构相关的部分。

    为了让linux内核的构建系统kbuild在构建相应的体系结构相关的内核时,使用arch/$(ARCH)/Makefile中的内容,在arch/$(ARCH)/Makefile文件中定义了许多变量和一些目标。

    linux内核的构建系统kbuild按照下面的步骤进行:

    1).通过"make menuconfig"去配置内核,从而产生内核的配置文件.config

    2).把linux内核的版本号存放在include/linux/version.h文件之中。

    3).把include/asm软链接到include/asm-gen

    4).准备目标文件所需要的首要文件。

       还有一些必须要的首要文件存放在arch/$(ARCH)/Makefile文件之中。

    5).递归的进入到 init-*,core*,drivers-*,net-*,libs-*等变量中存放的目录之中去,构建相应的目标。

        init-*,core*,drivers-*,net-*,libs-*这几个变量中的内容会在arch/$(ARCH)/Makefile文件中被扩展。

    6).链接所有的目标文件,然后在源码树的根目录下面形成vmlinux文件。

       在arch/$(ARCH)/Makefile中的"head-y"定义了第一个将要被链接的对象。

    7).最后,构成了一个bootp_w_picpath引导镜像。


6.1设置变量,使得编译的内核与体系结构相关

    LDFLAGS  定义了通用的$(LD)选项。

    在$(LDFLAGS)中定义的$(LD)选项内容,在任何调用$(LD)汇编器的地方都会被使用。

    而ldflags-y中定义的汇编器选项,是在进一步的自定义中使用的。


    LDFLAGS_MODULE 中定义的选项,在$(LD)汇编器进行模块的链接时使用(将*.ko文件链接为模块)。

   

    LDFLAGS_vmlinux 中定义的选项,在$(LD)汇编器进行链接形成vmlinux文件是使用。

 

    KBUILD_AFLAGS 为传递给$(AS)的选项。

            默认值存放在linux源代码树的最顶层中的Makefile之中。

            可以通过扩展或修改KBUILD_AFLAGS中的内容来适应相应的体系结构

   

    KBUILD_CFLAGS 为传递给$(CC)编译器的选项。

            默认值存放在linux源代码树的最顶层中的Makefile之中。

            可以通过扩展或修改KBUILD_CFLAGS中的内容来适应相应的体系结构

    KBUILD_CFLAGS中的内容经常依赖于相应的配置。

    例如:

        #arch/i386/Makefile

         cflags-$(CONFIG_M386) += -march=i386

         KBUILD_CFLAGS += $(cflags-y)


    CFLAGS_KERNEL $(CC) options specific for built-in


    CFLAGS_MODULE $(CC) options specific for modules


6.2 列出kbuild将要遍历的目录

    linux源代码树中的顶层Makefile文件和与体系结构相关的Makefile文件通过定义变量来指定如何构建vmlinux文件。

    在linux中的模块的构建与体系结构是完全无关的。

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

   

    $(head-y) 中存放的是在形成vmlinux时,首先需要链接的目标;


    $(libs-y) 中存放的一些目录。而linux中的静态库文件(*.a)将会存放在这些目录之中。

      而余下的目录,是built-in.o文件存放的地方。

    $(init-y) 是 $(head-y)中未定义的目标文件存放的地方。

    然后按照下面的顺序:

    $(core-y), $(libs-y), $(drivers-y), $(net-y)


    所有的一般目录都可以使用linux源代码树中的最顶层Makefile文件中定义的变量。而"arch/$(ARCH)/Makefile"中仅仅添加一些体系结构指定的目录。

    例如:

         #arch/sparc64/Makefile

         core-y += arch/sparc64/kernel/

         libs-y += arch/sparc64/prom arch/sparc64/lib/

         drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/


6.3 体系结构指定的引导镜像

     linux的内核构建系统kbuild并没有提供任何方法去支持在boot/目录下面去构建一个指定的目标。因此,应该arch/$(ARCH)/Makefile中手动的调用make去在boot/目录下面构建一个目标。

     推荐的方法是:在arch/$(ARCH)/Makefile文件中加入一条arch/$(ARCH)/boot/Makefile全路径的规则。

     例如:

         #arch/i386/Makefile

         boot := arch/i386/boot 在arch/i386/Makefile文件中包含将要

                                 存放生成的目标文件的路径

         bzImage: vmlinux

             $(Q)$(MAKE) $(build)=$(boot)  $(boot)/$@

               在"arch/i386/Makefile"文件中调用"make"来执行"arch/i386/boot"中的Makefile文件。

     在一个子目录中调用"make"命令的推荐的方法是:

           "$(Q)$(MAKE) $(build)=<dir>"

    

     linux内核构建系统kbuild并没有对对内核进行编译后产生的与体系结构相关的目标文件如何命名进行规定。但是可以通过执行"make help"命令来列出所有相关的目标文件名。然而为了支持"make help"功能,$(archhelp)必须被定义

     例如:

          #arch/mips/Makefile

wKiom1SQGxiS48DBAAGAUb07tCg288.jpg

   

          #arch/arm/Makefile

wKiom1SQG2KwSf7RAANrDio5DFM222.jpg  

   

     当编译内核时,只执行"make"命令而不带任何参数的话,遇到的第一个目标将会被构建。而第一个目标被保存在linux内核源代码树中的最顶层Makefile文件中:  wKiom1SQHqeyCQicAAFjio1HM_Y259.jpg

    

   每一种体系结构都后一种默认的bootable p_w_picpath。当执行"make help"时,带"*"的行就是默认的bootable p_w_picpath。

   为了构建一个最终形成的目标不是vmlinux,可以这样做:   wKiom1SQIQKDLrzlAAI5P9CbAlM288.jpg


wKioL1SQIw2h7wyNAAHfywpfth4925.jpg




6.5 构建non-kbuild目标

    当在编译linux内核时,在一个目录下面不仅会产生"obj-*"中指定的目标文件,还会产生其它一些文件。而这些非"obj-*"文件,可以存放在"extra-y"之中。同时,在执行"make clean"命令时,会将$(extra-y)中的内容给删除。并且

"extra-y"中的文件不会被链接到built-in.o之中去的。

    例如:

        #arch/i386/kernel/Makefile

        extra-y := head.o init_task.o

        这两个head.o init_task.o文件最终是不会被链接到built-in.o之中去的,但是这两个文件也是在编译的过程中产生的目标文件。



6.6 构建一个boot p_w_picpath文件的命令

    linux内核构建系统kbuild提供了一些宏命令用于构建boot p_w_picpath文件。

    if_changed

    用法:

        target: source(s) FORCE //FORCE是必须的,不能忽略的

            $(call if_changed,ld/objcopy/gzip)

    kbuild使用上面的规则来检测$(target)中的内容是否发生了更新,或这"call if_changed, ld/objcopy/gzip"中的传递个"ld","objcopy","gzip"的参数与之前的不同。如果是后者的会,kbuild会重新执行"ld","objcopy","gzip"等命令来重新构建$(target)中的目标。

     任何要使用if_changed的目标都必须要放在$(target)之中,否则的话这个"call if_changed"将执行失败,这个target中的目标将会总是被重新构建。

    在target变量赋值时,不能使用$(obj)/这样的前缀。

 

     ld 用于链接目标。经常使用LDFLAGS_$@Q去指定传递个ld的选项参数。

   

    objcopy用于复制二进制格式的文件。

           通常使用的是OBJCOPYFLAGS这个变量。而OBJCOPYFLAGS通常被放在arch/$(ARCH)/Makefile之中。

           OBJCOPYFLAGS_$@可以用于设置额外的选项。

 

    gzip用于压缩目标。通常使用最大压缩比去压缩目标。

  

    例如:

        #arch/i386/boot/Makefile

        //LDFLAGS_bootsetc中指定了在链接bootsetc.o为bootsetc可执行文件时所要传递给$(LD)连接器的选项参数

        LDFLAGS_bootsetc := -Ttext 0x0 -s --oformat binary

        LDFLAGS_setup  := -Ttext 0x0 -s --oformat binary -e begtext

          targets += setup setup.o bootsetc bootsetc.o

          $(obj)/setup $(obj)/bootsetc: %: %.o FORCE

                $(call if_changed,ld)

        当setup.o bootsetc.o等文件被更新时,调用ld来对其进行重新编译。

    须知:

        我们通常会忘记给"target :="赋值,造成目标文件毫无理由的被重新编译。


6.8 预处理链接器脚本

    当在构建vmlinux镜像文件时,在arch/$(ARCH)/kernel/vmlinux.lds的连接器脚本会被使用。

    而在有的arch/$(ARCH)/kernel/目录下面存放的是vmlinux.lds.S文件。

    kbuild系统知道这个.lds文件并且还包含了一条规则:"*lds.S --> *.lds"

    例如:

        #arch/i386/kernel/Makefile

        //告诉kbuild系统去构建vmlinux.lds

        always := vmlinux.lds

       //当在构建vmlinux.lds时,传递给相应的编译器选项。

        export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)

    当构建.lds目标文件时,kbuild系统会使用如下的变量:

    KBUILD_CCPFLAGS:在最顶层的Makefile文件之中被设置;

    cppflags_y : 在kbuild makefile文件中被设置

    CPPFLAGS_$(@F):target specific flags。


8 Kbuild变量

 

  ARCH变量

      这个变量用于定义目标体系结构,例如"i386","arm","sparc"。一些kbuild Makefile需要通过"$(ARCH)"去判断哪些文件需要去编译。

      默认情况下,最顶层的Makefile文件会把$(ARCH)设置成主机的体系结构。

但是如果要进行交叉编译,可以通过如下的方式的来设置最顶层的Makefile中的$(ARCH)来进行交叉编译:

     make ARCH=m68k


  INSTALL_PATH变量

      用于设置arch Makefile把kernel p_w_picpath和System.map.file安装到什么地方。


  INSTALL_MOD_PATH、 MODLIB变量

  MODLIB用于指定模块的安装目录;

         在最顶层的Makefile中指定

         MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)

         export MODLIB

  可以通过命令行来修改MODLIB的值,来重新设置模块的安装目录。