vmlinux的构建过程

3.2.3 vmlinux的构建过程(1)

所有的体系结构都需要构建vmlinux,所以vmlinux的构建规则在顶层的Makefile中。

 
  
  1. linux-3.7.4/Makefile:  
  2.  
  3. cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) \  
  4.                     $(LDFLAGS_vmlinux)  
  5.  
  6. vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE  
  7.     +$(call if_changed,link-vmlinux) 

注意,构建vmlinux的命令使用了make的内置函数call。这是一个比较特殊的内置函数,make使用它来引用用户自己定义的带有参数的函数。if_changed是kbuild定义的一个函数,这里通过call引用这个函数,传递的实参是link-vmlinux。函数if_changed的定义如下:
 

 
  
  1. linux-3.7.4/scripts/Kbuild.include:  
  2.  
  3. if_changed = $(if $(strip $(any-prereq) $(arg-check)), \  
  4.     @set -e;                                                     \  
  5.     $(echo-cmd) $(cmd_$(1));                                  \  
  6.     echo ‘cmd_$@ := $(make-cmd)’ > $(dot-target).cmd) 

在if_changed中,any-prereq检查是否有依赖比目标新,或者依赖还没有创建;arg-check检查编译目标的命令相对上次是否发生变化。如果两者中只要有一个发生改变,就执行if函数的if块。注意if块中的使用黑体标识的部分,其中“1”代表的就是传给if_changed的第一个实参。由此可见,if_changed核心功能就是当目标的依赖或者编译命令发生变化时,执行表达式“cmd_$(1)”展开后的值。

这里,传给if_changed的第一个实参是link-vmlinux,因此,cmd_$(1)展开后为cmd_link-vmlinux。注意cmd_link-vmlinux中的第二项“$<”,这是make的自动变量,翻译自“Automatic Variable”,意指变量名相同,但是make根据具体上下文,将其自动替换为合适的值。这里,make会将这个自动变量替换为构建vmlinux中的规则中的第一个依赖,即shell脚本文件scripts/link-vmlinux.sh,该脚本文件中负责vmlinux链接的脚本如下:
 

 
  
  1. linux-3.7.4/scripts/link-vmlinux.sh:  
  2.  
  3. vmlinux_link()  
  4. {  
  5.     local lds="${objtree}/${KBUILD_LDS}" 
  6.  
  7.     if [ "${SRCARCH}" != "um" ]; then  
  8.         ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2}                  \  
  9.             -T ${lds} ${KBUILD_VMLINUX_INIT}                     \  
  10.             --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1}  
  11.     else  
  12.         ...  
  13.     fi  
  14. }  
  15. ...  
  16. vmlinux_link "${kallsymso}" vmlinux 

根据函数vmlinux_link的实现,如果平台不是“um”,那么就调用链接器将变量KBUILD_ VMLINUX_INIT、KBUILD_VMLINUX_MAIN中记录的目标文件链接为vmlinux。我们看看这两个变量的定义:
 

 
  
  1. linux-3.7.4/Makefile:  
  2.  
  3. # Externally visible symbols (used by link-vmlinux.sh)  
  4. export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)  
  5. export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y)\  
  6.    $(net-y) 

我们以core-y为例来分析变量KBUILD_VMLINUX_MAIN的值。

 
  
  1. linux-3.7.4/Makefile:  
  2.  
  3. core-y      :usr/  
  4. ...  
  5. core-y      += kernel/ mm/ fs/ ipc/ security/ crypto/ block/  
  6. ...  
  7. core-y      := $(patsubst %/, %/built-in.o, $(core-y))

你可能感兴趣的:(linux,内核)