makefile | |
|
|
来源: ChinaUnix博客 日期: 2007.11.15 17:23 (共有条评论) 我要评论 | |
=== 目录 === 1 概述 === 2 用户与作用 === 3 Kbuild文件 --- 3.1 目标定义 --- 3.2 编译进内核 - obj-y --- 3.3 编译可装载模块 - obj-m --- 3.4 输出的符号 --- 3.5 目标库文件 - lib-y --- 3.6 递归躺下访问目录 --- 3.7 编辑标志 --- 3.8 命令行的依赖关系(原文中没有写:-)) --- 3.9 跟踪依赖 --- 3.10 特殊规则 --- 3.11 $(CC) 支持的函数 === 4 本机程序支持 --- 4.1 简单的本机程序 --- 4.2 复合的本机程序 --- 4.3 定义共享库 --- 4.4 使用用C++编写的本机程序 --- 4.5 控制本机程序的编译选项 --- 4.6 编译主机程序时 --- 4.7 使用 hostprogs-$(CONFIG_FOO) === 5 Kbuild清理 === 6 架构Makefile --- 6.1 调整针对某一具体架构生成的镜像 --- 6.2 将所需文件加到 archprepare 中 --- 6.3 递归下向时要访问的目录列表 --- 6.4 具体架构的启动镜像 --- 6.5 构造非Kbuild目标 --- 6.6 构建启动镜像的命令 --- 6.7 Kbuild自定义命令 --- 6.8 联接器预处理脚本 === 7 Kbuild 变量 === 8 Makefile语言 === 9 关于作者 === 10 TODO === 1 概述 Linux内核的Makefile分为5个部分: Makefile 顶层Makefile .config 内核配置文件 arch/$(ARCH)/Makefile 具体架构的Makefile scripts/Makefile.* 通用的规则等。面向所有的Kbuild Makefiles。 kbuild Makefiles 内核源代码中大约有500个这样的文件 顶层Makefile阅读的.config文件,而该文件是由内核配置程序生成的。 顶层Makefile负责制作:vmlinux(内核文件)与模块(任何模块文件)。制作的过程主要是 通过递归向下访问子目录的形式完成。并根据内核配置文件确定访问哪些子目录。顶层 Makefile要原封不动的包含一具体架构的Makefile,其名字类似于 arch/$(ARCH)/ Makefile。该架构Makefile向顶层Makefile提供其架构的特别信息。 每一个子目录都有一个Kbuild Makefile文件,用来执行从其上层目录传递下来的命令。 Kbuild Makefile从.config文件中提取信息,生成Kbuild完成内核编译所需的文件列表。 scripts/Makefile.*包含了所有的定义、规则等信息。这些文件被用来编译基于kbuild Makefile的内核。(**有点不通**) === 2 用户与作用 可以将人们与内核Makefile的关系分成4类。 *使用者* 编译内核的人。他们只是键入"make menuconfig"或"make"这样的命令。一般 情况下是不会读或编辑任何内核Makefile(或者任何的源文件)。 *普通开发人员* 这是一群工作在内核某一功能上的人,比如:驱动开发,文件系统或 网络协议。他们所需要维护的只是他们所工作的子系统的Kbuild Makefile。为了提高 工作的效率,他们也需要对内核Makefile有一个全面的认识,并且要熟悉Kbuild的接口 。 *架构开发人员* 这是一些工作在具体架构,比如sparc 或者ia64,上面的人。架构开 发者需要在熟悉kbuild Makefile的同时,也要熟悉他所工作架构的Makefile。 *Kbuild开发者* 维护Kbuild系统的人。他们需要知晓内核Makefile的方方面面。 该文件是为普通开发人员与架构开发人员所写。 === 3 Kbuild文件 大部分内核中的Makefile都是使用Kbuild组织结构的Kbuild Makefile。这章介绍了 Kbuild Makefile的语法。 Kbuild文件倾向于"Makefile"这个名字,"Kbuild"也是可以用的。但如果"Makefile" "Kbuild"同时出现的话,使用的将会是"Kbuild"文件。 3.1节 目标定义是一个快速介绍,以后的几章会提供更详细的内容以及实例。 --- 3.1 目标定义 目标定义是Kbuild Makefile的主要部分,也是核心部分。主要是定义了要编 译的文件,所有的选项,以及到哪些子目录去执行递归操作。 最简单的Kbuild makefile 只包含一行: 例子: obj-y += foo.o 该例子告诉Kbuild在这目录里,有一个名为foo.o的目标文件。foo.o将从foo.c 或foo.S文件编译得到。 如果foo.o要编译成一模块,那就要用obj-m了。所采用的形式如下: 例子: obj-$(CONFIG_FOO) += foo.o $(CONFIG_FOO)可以为y(编译进内核) 或m(编译成模块)。如果CONFIG_FOO不是y 和m,那么该文件就不会被编译联接了。 --- 3.2 编译进内核 - obj-y Kbuild Makefile 规定所有编译进内核的目标文件都存在$(obj-y)列表中。而 这些列表依赖内核的配置。 Kbuild编译所有的$(obj-y)文件。然后,调用"$(LD) -r"将它们合并到一个 build-in.o文件中。稍后,该build-in.o会被其父Makefile联接进vmlinux中。 $(obj-y)中的文件是有顺序的。列表中有重复项是可以的:当第一个文件被联 接到built-in.o中后,其余文件就被忽略了。 联接也是有顺序的,那是因为有些函数(module_init()/__initcall)将会在启 动时按照他们出现的顺序进行调用。所以,记住改变联接的顺序可能改变你 SCSI控制器的检测顺序,从而导致你的硬盘数据损害。 例子: #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 --- 3.3 编译可装载模块 - obj-m $(obj-m) 列举出了哪些文件要编译成可装载模块。 一个模块可以由一个文件或多个文件编译而成。如果是一个源文件,Kbuild Makefile只需简单的将其加到$(obj-m)中去就可以了。 例子: #drivers/isdn/i4l/Makefile obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o 注意:此例中 $(CONFIG_ISDN_PPP_BSDCOMP) 的值为'm' 如果内核模块是由多个源文件编译而成,那你就要采用上面那个例子一样的 方法去声明你所要编译的模块。 Kbuild需要知道你所编译的模块是基于哪些文件,所以你需要通过变量 $(-objs)来告诉它。 例子: #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)中列出的 所有文件,然后使用"$(LD) -r"生成isdn.o。 Kbuild能够识别用于组成目标文件的后缀-objs和后缀-y。这就让Kbuild Makefile可以通过使用 CONFIG_ 符号来判断该对象是否是用来组合对象的。 例子: #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将是复合 对象 ext2.o的一部分。 注意:当然,当你要将其编译进内核时,上面的语法同样适用。所以,如果 你的 CONFIG_EXT2_FS=y,那Kbuild会按你所期望的那样,生成 ext2.o文件 ,然后将其联接到 built-in.o中。 --- 3.4 输出的符号 在Makefile中,没有对模块输出的符号有特殊要求。 --- 3.5 目标库文件 - lib-y 在 obj-* 中所列文件是用来编译模块或者是联接到特定目录中的 built-in.o 。同样,也可以列出一些将被包含在lib.a库中的文件。 在 lib-y 中所列出的文件用来组成该目录下的一个库文件。 在 obj-y 与 lib-y 中同时列出的文件,因为都是可以访问的,所以该文件是 不会被包含在库文件中的。 同样的情况, lib-m 中的文件就要包含在 lib.a 库文件中。 注意,一个Kbuild makefile可以同时列出要编译进内核的文件与要编译成库 的文件。所以,在一个目录里可以同时存在 built-in.o 与 lib.a 两个文件。 例子: #arch/i386/lib/Makefile lib-y := chechsum.o delay.o 这将由 checksum.o 和delay.o 两个文件创建一个库文件 lib.a。为了让 Kbuild 真正认识到这里要有一个库文件 lib.a 要创建,其所在的目录要加 到 libs-y 列表中。 还可参考"6.3 递归下向时要访问的目录列表" lib-y 使用一般限制在 lib/ 和 arch/*/lib 中。 --- 3.6 递归向下访问目录 一个Makefile只对编译所在目录的对象负责。在子目录中的文件的编译要由 其所在的子目录的Makefile来管理。只要你让Kbuild知道它应该递归操作, 那么该系统就会在其子目录中自动的调用 make 递归操作。 这就是 obj-y 和 obj-m 的作用。 ext2 被放的一个单独的目录下,在fs目录下的Makefile会告诉Kbuild使用 下面的赋值进行向下递归操作。 例子: #fs/Makefile obj-$(CONFIG_EXT2_FS) += ext2/ 如果 CONFIG_EXT2_FS 被设置为 'y'(编译进内核)或是'm'(编译成模块),相 应的 obj- 变量就会被设置,并且Kbuild就会递归向下访问 ext2 目录。 Kbuild只是用这些信息来决定它是否需要访问该目录,而具体怎么编译由该目 录中的Makefile来决定。 将 CONFIG_ 变量设置成目录名是一个好的编程习惯。这让Kbuild在完全忽略那 些相应的 CONFIG_ 值不是'y'和'm'的目录。 --- 3.7 编辑标志 EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS 所有的 EXTRA_ 变量只在所定义的Kbuild Makefile中起作用。EXTRA_ 变量可 以在Kbuild Makefile中所有命令中使用。 $(EXTRA_CFLAGS) 是用 $(CC) 编译C源文件时的选项。 例子: # drivers/sound/emu10kl/Makefile EXTRA_CFLAGS += -I$(obj) ifdef DEBUG EXTRA_CFLAGS += -DEMU10KL_DEBUG endif 该变量是必须的,因为顶层Makefile拥有变量 $(CFLAGS) 并用来作为整个源 代码树的编译选项。 $(EXTRA_AFLAGS) 也是一个针对每个目录的选项,只不过它是用来编译汇编 源代码的。 例子: #arch/x86_64/kernel/Makefile EXTRA_AFLAGS := -traditional $(EXTRA_LDFLAGS) 和 $(EXTRA_ARFLAGS)分别与 $(LD)和 $(AR)类似,只不 过,他们是针对每个目录的。 例子: #arch/m68k/fpsp040/Makefile EXTRA_LDFLAGS := -x CFLAGS_$@, AFLSGA_$@ CFLAGS_$@ 和 AFLAGS_$@ 只能在当前Kbuild Makefile中的命令中使用。 $(CFLAGS_$@) 是 $(CC) 针对每个文件的选项。$@ 表明了具体操作的文件。 例子: # 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的编辑选项。 $(AFLAGS_$@) 也类似,只不是是针对汇编语言的。 例子: # arch/arm/kernel/Makefile AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional --- 3.9 跟踪依赖 Kbuild 跟踪在以下方面依赖: 1) 所有要参与编译的文件(所有的.c 和.h文件) 2) 在参与编译文件中所要使用的 CONFIG_ 选项 3) 用于编译目标的命令行 因此,如果你改变了 $(CC) 的选项,所有受影响的文件都要重新编译。 --- 3.10 特殊规则 特殊规则就是那Kbuild架构不能提供所要求的支持时,所使用的规则。一个 典型的例子就是在构建过程中生成的头文件。 另一个例子就是那些需要采用特殊规则来准备启动镜像。 特殊规则的写法与普通Make规则一样。 Kbuild并不在Makefile所在的目录执行,所以所有的特殊规则都要提供参与 编译的文件和目标文件的相对路径。 在定义特殊规则时,要使用以下两个变量: $(src) $(src) 表明Makefile所在目录的相对路径。经常在定位源代码树中的文件时 ,使用该变量。 $(obj) $(obj) 表明目标文件所要存储目录的相对路径。经常在定位所生成的文件时 ,使用该变量。 例子: #drivers/scsi/Makefile $(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl $(CPP) -DCHIP=810 - = 3.00 cc-option-align = -falign 例子: CFLAGS += $(cc-option-align)-functions=4 在上面的例子中,选项 -falign-funcions=4 被用在gcc >= 3.00的时候。对 于小于3.00时, 使用 -malign-funcions=4 。 cc-version cc-version以数学形式返回 $(CC) 编译器的版本号。 其格式是:,二者都是数学。比如,gcc 3.41 会返回 0341。 当某版本的 $(CC) 在某方面有缺陷时,cc-version就会很有用。比如,选项 -mregparm=3 虽然会被gcc接受,但其实现是有问题的。 例子: #arch/i386/Makefile cflags-y += $(shell \ if [ $(call cc-version) -ge 0300 ] ; then \ echo "-meregparm=3"; fi ;) 在上面的例子中,-mregparm=3只会在gcc的版本号大于等于3.0的时候使用。 cc-ifversion cc-ifversion测试 $(CC) 的版本号,如果版本表达式为真,就赋值为最后的 参数。 例子: #fs/reiserfs/Makefile EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0402, -O1) 在这个例子中,如果 $(CC) 的版本小于4.2,EXTRA_CFLAGS就被赋值 -O1。 cc-ifversion 可使用所有的shell 操作符:-eq,-ne,-lt,-le,-gt,和-ge。 第三个参数可以像上面例子一样是个文本,但也可以是个扩展的变量或宏。 /*这段翻译的不好*/ === 4 本机程序支持 Kbuild 支持编译那些将在编译阶段使用的可执行文件。 为了使用该可执行文件,要将编译分成二个阶段。 第一阶段是告诉Kbuild存在哪些可执行文件。这是通过变量 hostprogs-y来完成的。 第二阶段是添加一个对可执行文件的显性依赖。有两种方法:增加依赖关系到一个规则 中,或是利用变量 $(always)。 以下是详细叙述. --- 4.1 简单的本机程序 在编译内核时,有时会需要编译并运行一个程序。 下面这行就告诉了kbuild,程序bin2hex应该在本机上编译。 例子: hostprogs-y := bin2hex 在上面的例子中,Kbuild假设bin2hex是由一个与其在同一目录下,名为 bin2hex.c 的C语言源文件编译而成的。 --- 4.2 复合的本机程序 本机程序可以由多个文件编译而成。 所使用的语法与内核的相应语法很相似。 $(-objs) 列出了联接成最后的可执行文件所需的所有目标文件。 例子: #scripts/lxdialog/Makefile hostprogs-y := lxdialog lxdialog-objs := checklist.o lxdialog.o 扩展名为.o的文件是从相应的.c文件编译而来的。在上面的例子中, checklist.c 编译成了checklist.o,lxdialog.c编译成了lxdialog.o。 最后,两个.o文件联接成了一可执行文件,lxdialog。 注意:语法 -y不是只能用来生成本机程序。 --- 4.3 定义共享库 扩展名为so的文件称为共享库,被编译成位置无关对象。 Kbuild也支持共享库,但共享库的使用很有限。 在下面的例子中,libconfig.so共享库用来联接到可执行文件 conf中。 例子: #scripts/kconfig/Makefile hostprogs-y := conf conf-objs := conf.o libkconfig.so libkcofig-objs := expr.o type.o 共享库文件经常要求一个相应的 -objs,在上面的例子中,共享库libkconfig 是由 expr.o 和 type.o两个文件组成的。 expr.o 和 type.o 将被编译成位置无关码,然后联接成共享库文件 libkconfig.so。C++并不支持共享库。 --- 4.4 使用用C++编写的本机程序 kbuild也支持用C++编写的本机程序。在此专门介绍是为了支持kconfig,并且 在一般情况下不推荐使用。 例子: #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 控制本机程序的编译选项 当编译本机程序时,有可能使用到特殊选项。程序经常是利用$(HOSTCC)编译 ,其选项在 $(HOSTCFLAGS)变量中。 可通过使用变量 HOST_EXTRACFLAGS,影响所有在Makefile文件中要创建的 主机程序。 例子: #scripts/lxdialog/Makefile HOST_EXTRACFLAGS += -I/usr/include/ncurses 为一单个文件设置选项,可按形式进行: 例子: #arch/ppc64/boot/Makefile HOSTCFLAGS_pinggyback.o := -DKERNELBASE=$(KERNELBASE) 同样也可以给联接器声明一特殊选项。 例子: #scripts/kconfig/Makefile HOSTLOADLIBES_qconf := -L$(QTDIR)/lib 当联接qconf时,将会向联接器传递附加选项 "-L$(QTDIR)/lib"。 --- 4.6 编译主机程序时 Kbuild只在需要时编译主机程序。 有两种方法: (1) 在一具体的规则中显性列出所需要的文件 例子: #drivers/pci/Makefile hostprogs-y := gen-devlist $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist ( cd $(obj); ./gen-devlist ) " 。 并没有对架构特殊目标的命名规则,但用命令 "make help" 可以列出所有的 相关目标。 为了支持 "make help",$(archhelp) 必须被定义。 例子: #arch/i386/Makefile define archhelp echo '* bzImage - Image (arch/$(ARCH)/boot/bzImage)' endef 当make 没带参数执行时,所遇到的第一个目标将被执行。在顶层,第一个目标 就是 all:。 每个架构Makefile都要默认构造一可启动的镜像文件。 在 "make help"中,默认目标就是被加亮的'*'。 添加一新的前提文件到 all:,就可以构造出一不同的vmlinux。 例子: #arch/i386/Makefile all: bzImage 当 make 没有参数时,bzImage将被构造。 --- 6.5 构造非Kbuild目标 extra-y extra-y 列出了在当前目录下,所要创建的附加文件,不包含任何已包含在 obj-* 中的文件。 用 extra-y 列目标,主要是两个目的: 1) 可以使Kbuild检查命令行是否发生变化 - 使用 $(call if_changed,xxx) 的时候 2) 让Kbuild知道哪些文件要在 "make clean" 时删除 例子: #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) 当执行该规则时,就检查是否有文件需要更新,或者在上次调用以后,命令行 发生了改变。如果有选项发生了改变,后者会导致重新构造。 只有在 $(targets)列出的的目标文件,才能使用 if_changed,否则命令行的 检查会失败,并且目标总会被重建。 给 $(targets)的赋值没有前缀 $(obj)/ 。 if_changed 可用来联接自定义的 Kbuild命令,关于Kbuild自定义命令请看 6.7节。 注意:忘记 FORCE 是一种典型的错误。还有一种普遍的错误是,空格有的时候 是有意义的;比如。下面的命令就会错误(注意在逗号后面的那个多余的空格): target: source(s) FORCE #WRONG!# $(call if_changed, ld/objcopy/gzip) ld 联接目标。经常是使用LDFLAGS_$@来设置ld的特殊选项。 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) 在这个例子中,有两个可能的目标文件,分别要求不同的联接选项。定义联接 器的选项使用的是 LDFLAGS_$@ 语法,每个潜在的目标一个。 $(targets) 被分配给所有的潜在目标,因此知道目标是哪些,并且还会: 1) 检查命令行是否改变 2) 在 "make clean" 时,删除目标文件 前提部分中的 ": %: %.o" 部分使我们不必在列出文件 setup.o 和 bootsect.o 。 注意:一个普遍的错误是忘记了给 "target"赋值,导致在target中的文件总是 无缘无故的被重新编译。 --- 6.7 Kbuild自定义命令 当Kbuild的变量 KBUILD_VERBOSE 为0时,只会显示命令的简写。 如果要为自定义命令使用这一功能,需要设置2个变量: quiet_cmd_ - 要显示的命令 cmd_ - 要执行的命令 例子: # 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 生成的。 Kbuild认识.lds文件,并包含由*.lds.S文件生成*.lds文件的规则。 例子: #arch/i386/kernel/Makefile always := vmlinux.lds #Makefile export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) $(always)的值是用来告诉Kbuild,构造目标 vmlinux.lds。 $(CPPFLAGS_vmlinux.lds),Kbuild在构造目标vmlinux.lds时所用到的特殊 选项。 当构造 *.lds 目标时,Kbuild要用到下列变量: CPPFLAGS : 在顶层目录中设置 EXTRA_CPPFLAGS : 可以在Kbuild Makefile中设置 CPPFLAGS_$(@F) : 目标特别选项 注意,此处的赋值用的完整的文件名。 针对*.lds文件的Kbuild构架还被用在许多具体架构的文件中。(***不通***) === 7 Kbuild 变量 顶层Makefile输出以下变量: VERSION,PATCHLEVEL,SUBLEVEL,EXTRAVERSION 这些变量定义了当前内核的版本号。只有很少一部分Makefile会直接用到这些 变量;可使用 $(KERNELRELEASE)代替。 $(VERSION),$(PATCHLEVEL),和$(SUBLEVEL) 定义了最初使用的三个数字的版本 号,比如"2""4"和"0"。这三个值一般是数字。 $(EXTRAVERSION) 为了补丁定义了更小的版本号。一般是非数字的字符串,比如 "-pre4" ,或就空着。 KERNELRELEASE $(KERNELRELEASE) 是一个字符串,类似"2.4.0-pre4",用于安装目录的命名或 显示当前的版本号。一部分架构Makefile使用该变量。 ARCH 该变量定义了目标架构,比如"i386","arm" 或"sparc"。有些Kbuild Makefile 根据 $(ARCH) 决定编译哪些文件。 默认情况下,顶层Makefile将其设置为本机架构。如果是跨平台编译,用户可以 用下面的命令覆盖该值: make ARCH=m68k ... INSTALL_PATH 该变量为架构Makefile定义了安装内核镜像与 System.map 文件的目录。 主要用来指明架构特殊的安装路径。 INSTALL_MOD_PATH,MODLIB $(INSTALL_MOD_PATH) 为了安装模块,给 $(MODLIB) 声明了前缀。该变量不能 在Makefile中定义,但可以由用户传给Makefile。 $(MODLIB) 具体的模块安装的路径。顶层Makefile将$(MODLIB)定义为 $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)。用户可以通过命令行 参数的形式将其覆盖。 INSTALL_MOD_STRIP 如果该变量有定义,模块在安装之前,会被剥出符号表。如果 INSTALL_MOD_STRIP 为 "1",就使用默认选项 --strip-debug。否则, INSTALL_MOD_STRIP 将作为命令 strip 的选项使用。 === 8 Makefile语言 内核的Makefile使用的是GNU Make。该Makefile只使用GNU Make已注明的功能,并使用 了许多GNU 的扩展功能。 GNU Make支持基本的显示处理过程的函数。内核Makefile 使用了一种类似小说的方式 ,显示"if"语句的构造、处理过程。 GNU Make 有2个赋值操作符,":="和"="。":=",将对右边的表达式求值,并将所求的值 赋给左边。"="更像是一个公式定义,只是将右边的值简单的赋值给左边,当左边的表达 式被使用时,才求值。 有时使用"="是正确的。但是,一般情况下,推荐使用":="。 === 9 关于作者 第一版由 Michael Elizabeth Chastain, 修改:kai Germaschewski Sam Ravnborg === 10 TODO - 描述Kbuild是如何用 _shipped 来支持 shipped 文件的。 - 生成分支头文件 - 在第7节加入更多的变量 |