LINUX编译系统(2)

3. 软件构造

3.1 软件第一级构造

 init-y  := init/
 drivers-y := drivers/ sound/
 net-y  := net/
 libs-y  := lib/
 core-y  := usr/
core-y  += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

init-y  := $(patsubst %/, %/built-in.o, $(init-y))
core-y  := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y  := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1  := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2  := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y  := $(libs-y1) $(libs-y2)


以下的构造在 arch/ppc/Makefile

head-y    := arch/ppc/kernel/head.o
...

core-y    += arch/ppc/kernel/ arch/powerpc/kernel/ /
...

 

_all: all

all: uImage zImage
zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm : vmlinux

uImage: vmlinux

bzImage: zImage

vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds

all: vmlinux

 

3.2 以下为若干动态生成的文件/目录:

include/linux/version.h: $(srctree)/Makefile FORCE
     $(call filechk,version.h)

include/linux/utsrelease.h: include/config/kernel.release FORCE
     $(call filechk,utsrelease.h)
include/linux/compile.h: FORCE
     @echo '  CHK     $@'
     $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ /
     "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(CFLAGS)"
include/asm:
     @echo '  SYMLINK $@ -> include/asm-$(ARCH)'
     $(Q)if [ ! -d include ]; then mkdir -p include; fi;
     @ln -fsn asm-$(ARCH) $@
include/config/kernel.release: include/config/auto.conf FORCE
     $(Q)rm -f $@
     $(Q)echo $(kernelrelease) > $@
.version

      cmd_vmlinux_version = set -e;                     /
     if [ ! -r .version ]; then   /
       rm -f .version;    /
       echo 1 >.version;    /
     else      /
       mv .version .old_version;   /
       expr 0$$(cat .old_version) + 1 >.version; /
     fi;      

 

3.3 具体构造方法

3.3.1 obj-y
LINUX软件采用层次构造的方法.每个层次的软件模块文件名统一为built-in.o 。每个软件模块对应不同的目录。一个软件模块可以有本目录的.o和子目录的built-in.o所构造。

obj-y = a.o

obj-y += cpu/

编译系统做如下变换:

1. 获取子软件模块的目录和名称

子软件模块的目录

__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
subdir-ym := $(addprefix $(obj)/,$(subdir-ym))  
(subdir-ym := $(sort $(subdir-y) $(subdir-m))) 

软件模块的直接构建模块列表

obj-y  := $(patsubst %/, %/built-in.o, $(obj-y))
obj-y  := $(addprefix $(obj)/,$(obj-y))
子软件模块的名称

subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)))

subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))

2. 建立子软件模块的构建依赖

$(sort $(subdir-obj-y)): $(subdir-ym) ;

$(subdir-ym):
 $(Q)$(MAKE) $(build)=$@

(注:本目录下的.o  和 .c文件之间的依赖由implicit rule确定)
3. 建立软件模块的构建依赖

builtin-target := $(obj)/built-in.o

$(builtin-target): $(obj-y) FORCE
 $(call if_changed,link_o_target)
4. 加入到编译目标

__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) /
  $(if $(KBUILD_MODULES),$(obj-m)) /
  $(subdir-ym) $(always)
3.3.2 obj-m

obj-m不同于obj-y在于

1.同一目录中可以有多个不同的可加载软件模块

2. 一个可加载软件模块可以有多个.s/.c组成

obj-m = a.o b.o

obj-m += c/d.o

a-objs = aa.o bb.o

b-y = dd.o ee.o

LINUX编译系统做如下的变换

1.获取可加载软件模块的列表和子目录的列表

__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m)))
subdir-m += $(__subdir-m)
obj-m  := $(filter-out %/, $(obj-m))
2. 获取不同类型的可加载模块列表(多.o文件构造和单.o文件构造列表)

multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))

single-used-m := $(addprefix $(obj)/,$(single-used-m))
multi-used-m := $(addprefix $(obj)/,$(multi-used-m))

3. 多.o文件构造的.o列表

multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y)))

multi-objs-m := $(addprefix $(obj)/,$(multi-objs-m))
4. 单.o文件的生成依赖
$(single-used-m): %.o: %.c FORCE
     $(call cmd,force_checksrc)
     $(call if_changed_rule,cc_o_c)
     @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
5. 多.o文件的生成依赖

link_multi_deps =                     /
$(filter $(addprefix $(obj)/,         /
$($(subst $(obj)/,,$(@:.o=-objs)))    /
$($(subst $(obj)/,,$(@:.o=-y)))), $^)
$(multi-used-m) : %.o: $(multi-objs-m) FORCE
     $(call if_changed,link_multi-m)
     @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
6. 子目录依赖

适用于多.o文件中有源文件位于子目录中。

$(subdir-ym):
     $(Q)$(MAKE) $(build)=$@

7. 加入到编译目标中
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) /
  $(if $(KBUILD_MODULES),$(obj-m)) /
  $(subdir-ym) $(always)

其中:

multi-objs-m 和real-objs-m

real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
用于设置针对模块编译的编译标志

$(multi-objs-m)         : modname = $(modname-multi)
$(multi-objs-m:.o=.i)   : modname = $(modname-multi)
$(multi-objs-m:.o=.s)   : modname = $(modname-multi)
$(multi-objs-m:.o=.lst) : modname = $(modname-multi)

$(real-objs-m)        : modkern_cflags := $(CFLAGS_MODULE)
$(real-objs-m:.o=.i)  : modkern_cflags := $(CFLAGS_MODULE)
$(real-objs-m:.o=.s)  : modkern_cflags := $(CFLAGS_MODULE)
$(real-objs-m:.o=.lst): modkern_cflags := $(CFLAGS_MODULE)
$(real-objs-m)        : quiet_modtag := [M]
$(real-objs-m:.o=.i)  : quiet_modtag := [M]
$(real-objs-m:.o=.s)  : quiet_modtag := [M]
$(real-objs-m:.o=.lst): quiet_modtag := [M]
$(real-objs-m)      : modkern_aflags := $(AFLAGS_MODULE)
$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)

3.3.3 lib-y

lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))

 

ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
lib-target := $(obj)/lib.a
endif

$(lib-target): $(lib-y) FORCE
 $(call if_changed,link_l_target)

 

3.3.4 Implicit Rule

%.o: %.c FORCE
 $(call cmd,force_checksrc)
 $(call if_changed_rule,cc_o_c)

 

你可能感兴趣的:(Linux,linux,module,filter,build,symlink,include)