Linux 2.6内核Makefile分析
则写法同普通的makefile规则。
编译程序在makefile所在的目录不能被执行,因此所有的特殊规则需要提供前期文件和目标文件的相对路径。
定义特殊规则时将使用到两个变量:
$(src): $(src)是对于makefile文件目录的相对路径,当使用代码树中的文件时
使用该变量$(src)。
$(obj): $(obj)是目标文件目录的相对路径。生成文件使用$(obj)变量。
例如: #drivers/scsi/Makefile
$(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl
$(CPP) -DCHIP=810 - < $< | ... $(src)/script_asm.pl
这就是使用普通语法的特殊编译规则。
目标文件依赖于两个前提文件。目标文件的前缀是$(obj), 前提文件的前缀是
$(src)(因为它们不是生成文件)。
5) 引导映象
体系makefile文件定义了编译vmlinux文件的目标对象,将它们压缩和封装成引导代码,并复制到合适的位置。这包括各种安装命令。在Linux中Makefile无法为所有的体系结构提供标准化的方法,因此常需要具体硬件体系结构下makefile提供附加处理规则。
附加处理过程常位于arch/$(ARCH)/下的boot/目录。
内核编译体系无法在boot/目录下提供一种便捷的方法创建目标系统文件。因此arch/$(ARCH)/Makefile要调用make命令在boot/目录下建立目标系统文件。建议使用的方法是在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命令。
当执行不带参数的make命令时,将首先编译第一个目标对象。在顶层makefile中第一个目标对象是all:。
一个体系结构需要定义一个默认的可引导映像。
增加新的前提文件给all目标可以设置不同于vmlinux的默认目标对象。
例如: #arch/i386/Makefile
all: bzImage
当执行不带参数的"make"命令时,bzImage文件将被编译。
6) 常用编译命令
if_changed
如果必要,执行传递的命令。
用法:
$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target)
当这条规则被使用时它将检查哪些文件需要更新,或命令行被改变。后面这种情况将迫使
重新编译编译选项被改变的执行文件。使用if_changed的目标对象必须列举在$( builtin-target)中,否则命令行检查将失败,目标一直会编译。
if_changed_dep
如果必要,执行传递的命令并更新依赖文件。
用法:
%.o: %.S FORCE
$(call if_changed_dep,as_o_S)
当这条规则被使用时它将检查哪些文件需要更新,或命令行被改变。同时它会重新检测依赖关系的改变并将生成新的依赖文件。这是与if_changed命令的区别。
7) 定制命令
当正常执行带编译命令时命令的简短信息会被显示(要想显示详细的命令,请在命令行中加入V=1)。要让定制命令具有这种功能需要设置两个变量:
quiet_cmd_<command> - 将被显示的内容
cmd_<command> - 被执行的命令
例如: #
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命令编译$(obj)/bzImage目标时将显示:
BUILD arch/i386/boot/bzImage
8) 预处理链接脚本
当编译vmlinux映像时将使用arch/$(ARCH)/kernel/vmlinux.lds链接脚本。
相同目录下的vmlinux.lds.S文件是这个脚本的预处理的变体。内核编译系统知晓.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目标的编译选项。
编译*.lds时将使用到下面这些变量:
CPPFLAGS : 定义在顶层Makefile
EXTRA_CPPFLAGS : 可以设置在编译的makefile文件中
CPPFLAGS_$(@F) : 目标编译选项。注意要使用文件全名。
9) 主机辅助程序的编译
内核编译系统支持在编译阶段编译主机可执行程序。为了使用主机程序需要两个步骤:第一个步骤使用hostprogs-y变量告诉内核编译系统有主机程序可用。第二步给主机程序添加潜在的依赖关系。有两种方法,在规则中增加依赖关系或使用$(always)变量。这一部分的内容相对于其他内核文件的编译要简单的多,感兴趣的读者可以参考scripts/Makefile.build中的相关内容。
10) Clean机制
- (转贴)Makefile解读(04-23)
- Linux内核配置系统详解(05-07)
- Linux下C编程基础之:make工程管理器(08-13)
- GNU ARM汇编--(十七)u-boot的makefile和mkconfig解读(11-26)
- TQ2440国嵌学院gboot-Makefile工程文件(11-26)
- REDIce-Linux--灵活的实时Linux内核(11-12)