4.增强编译工具
4.1增强编译工具
4.1.1 基本编译工具
gcc
binutils
对于POWERPC系列:
# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
# instructions.
# gcc-3.4 and binutils-2.14 are a fatal combination.
make
4.1.1 增强编译工具
编译系统要解决的问题中依赖关系的建立是一个重要的内容。同时,方便编写MAKEFILE也需要增加工具。比如同一类型的目标可能需要多个步骤,可以考虑把多个步骤作为一个命令加以执行以方便编写。
在编写包含多个命令的新命令时,需要考虑参数问题。LINUX编译系统使用2种传递参数的方法
1. 类似于C语言
2.环境变量如$@ $<
4.1.1.1 变量
dot-target = $(dir $@).$(notdir $@)
depfile = $(subst $(comma),_,$(dot-target).d) /* 依赖文件的名字,不允许 , */
4.1.1.2 函数
特殊字符的处理
escsq = $(subst $(squote),'/$(squote)',$1)
make-cmd = $(subst /#,///#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
打印字符串
#compare if two command is equal
echo-cmd = $(if $($(quiet)cmd_$(1)), echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
echo-why = $(call escsq, $(strip $(why))
调用命令,打印命令内容
cmd = @$(echo-cmd) $(cmd_$(1))
调整编译搜索目录
# Find all -I options and add $(srctree) if it is not abstract directory
flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
# Add $(obj)/ for paths that is not absolute
objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
调整编译器选项
as-option, as-option1,as-option2 返回as支持的option
as-instr, intruction, option1, option2 若AS支持intruction,使用option1,否则option2
cc-option, gcc-option1,gcc-option2 类as-option
cc-option-yn, gcc-option 支持返回y,否则返回n
cc-option-align /* Prefix align with either -falign or -malign*/
cc-version,compiler-name /* get compiler's version */
cc-ifversion, operator, operand, gcc-options /* if [ gcc version operator operand ] return gcc-options */
ld-option,ld-option1,ld-option2 类as-option
依赖检查和调用目标更新的复合命令
arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) $(filter-out $(cmd_$@), $(cmd_$(1))) )
any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
filechk 调用方式 call filechk,sample。以$<为参数调用filechk_sample,比较其结果和$@,若不同,更新$@
if_changed 和 if_changed_dep的差别在于if_changed适用于非源文件,因为其不根据源文件中定义的宏增加对位header文件的依赖关系
if_changed = $(if $(strip $(any-prereq) $(arg-check)), /
@set -e; /
$(echo-cmd) $(cmd_$(1)); /
echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
# execute the command and also postprocess generated .d dependencies
# file
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), /
@set -e; /
$(echo-cmd) $(cmd_$(1)); /
scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;/
rm -f $(depfile); /
mv -f $(dot-target).tmp $(dot-target).cmd)
# Usage: $(call if_changed_rule,foo)
if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), /
@set -e; /
$(rule_$(1)))
所有目标的实际make rule
cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
cmd_gzip = gzip -f -9 < $< > $@
cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
cmd_ld = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) $(filter-out FORCE,$^) -o $@
cmd_rmfiles = rm -f $(rm-files)
目标生成命令cmd_xxx
根据.o生成可重定位的.o
cmd_link_o_target = $(if $(strip $(obj-y)),/
$(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),/
rm -f $@; $(AR) rcs $@)
根据.o生成.a
cmd_link_l_target = rm -f $@; $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-y)
同cmd_link_o_target 但依赖不同
cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps)
同cmd_link_multi-y但采用不同的连接选项
cmd_link_multi-m = $(LD) $(ld_flags) $(LDFLAGS_MODULE) -o $@ $(link_multi_deps)
连接生成LINUX
cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ /
-T $(vmlinux-lds) $(vmlinux-init) /
--start-group $(vmlinux-main) --end-group /
$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
cmd_ksym_ld = $(cmd_vmlinux__)
生成与系统调用相关可加载软件模块
cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) /
-Wl,-T,$(filter-out FORCE,$^) -o $@
# Generate .S file with all kernel symbols
cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
获得符号表vmlinux-->system.map
cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
如果.o中有系统符号,计算出CRC,并连接入此.o
cmd_modversions = /
if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then /
$(CPP) -D__GENKSYMS__ $(c_flags) $< /
| $(GENKSYMS) $(if $(KBUILD_SYMTYPES), /
-T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH) /
> $(@D)/.tmp_$(@F:.o=.ver); /
/
$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) /
-T $(@D)/.tmp_$(@F:.o=.ver); /
rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); /
else /
mv -f $(@D)/.tmp_$(@F) $@; /
fi;
endif
from .s--> .s
cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
from .c --> .i
cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $<
从.c获得系统符号
cmd_cc_symtypes_c = $(CPP) -D__GENKSYMS__ $(c_flags) $< | $(GENKSYMS) -T $@ >/dev/null; test -s $@ || rm -f $@
反汇编.o但获得在LINUX中的地址而不是从0开始的地址
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o System.map $(OBJDUMP) > $@
预扫描.S 到 .s
cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
from .S --> .o
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
.lds --> ld
cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
目标生成命令rule_xxx
define rule_ksym_ld
:
+$(call cmd,vmlinux_version)
$(call cmd,vmlinux__)
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
endef
define rule_vmlinux__
:
$(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
$(call cmd,vmlinux__)
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
$(Q)$(if $($(quiet)cmd_sysmap), /
echo ' $($(quiet)cmd_sysmap) System.map' &&) /
$(cmd_sysmap) $@ System.map; /
if [ $$? -ne 0 ]; then /
rm -f $@; /
/bin/false; /
fi;
$(verify_kallsyms)
endef
define rule_cc_o_c
$(call echo-cmd,checksrc) $(cmd_checksrc) /
$(call echo-cmd,cc_o_c) $(cmd_cc_o_c); /
$(cmd_modversions) /
scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > /
$(dot-target).tmp; /
rm -f $(depfile); /
mv -f $(dot-target).tmp $(dot-target).cmd
endef
rule_cc_o_c比cmd_cc_o_c在于增加了符号crc的值。
安装使用命令
cmd_depmod = if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map /
$(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) -r) /
$(KERNELRELEASE); /
fi