海思(Hi3521a)uboot详细分析(3)——顶层config.mk分析

    该config.mk位于uboot源码的根目录下, 其包含了子目录下许多同名的config.mk。所以千万注意这些同名文件的主次区别。
    通过顶层Makefile中的include $(TOPDIR)/config.mk 可以知道,在顶层Makefile中有包含顶层的config.mk
顶层config.mk内容主要结构为:

  1. 设置各种路径
  2. 设置主机环境的编译选项
  3. 确定各交叉编译工具
  4. 确定各种级别的编译选项
  5. 指定链接脚本
  6. 获得起始链接地址
  7. 设置头文件搜寻路径
  8. 使用起始链接地址
  9. 设置自动推导规则

    需要注意的是,结构顺序并不一定代表代码执行顺序,具体可以参考博客《顶层Makefile分析》,或是其uboot内容《序言和目录》

1. 设置各种路径

ifneq ($(OBJTREE),$(SRCTREE))
ifeq ($(CURDIR),$(SRCTREE))
dir :=
else
dir := $(subst $(SRCTREE)/,,$(CURDIR))
endif

obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/)

$(shell mkdir -p $(obj))
else
obj :=
src :=
endif
  • 本段代码还是在进行原地编译和外部输出编译的一些路径设置
  • 说到底,主要是将根目录下Makefile中和路径有关的变量导入进来

2.设置主机环境的编译选项

# clean the slate ...
PLATFORM_RELFLAGS =
PLATFORM_CPPFLAGS =
PLATFORM_LDFLAGS =
  • 先将这三个变量清零
HOSTCFLAGS	= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \
		  $(HOSTCPPFLAGS)
HOSTSTRIP	= strip
  • 定义了两个变量HOSTCFLAGS、HOSTSTRIP

3.确定各交叉编译工具

ifeq ($(HOSTOS),darwin)
# get major and minor product version (e.g. '10' and '6' for Snow Leopard)
DARWIN_MAJOR_VERSION	= $(shell sw_vers -productVersion | cut -f 1 -d '.')
DARWIN_MINOR_VERSION	= $(shell sw_vers -productVersion | cut -f 2 -d '.')

before-snow-leopard	= $(shell if [ $(DARWIN_MAJOR_VERSION) -le 10 -a \
	$(DARWIN_MINOR_VERSION) -le 5 ] ; then echo "$(1)"; else echo "$(2)"; fi ;)

# Snow Leopards build environment has no longer restrictions as described above
HOSTCC		 = $(call before-snow-leopard, "cc", "gcc")
HOSTCFLAGS	+= $(call before-snow-leopard, "-traditional-cpp")
HOSTLDFLAGS	+= $(call before-snow-leopard, "-multiply_defined suppress")
else
HOSTCC		= gcc
endif

ifeq ($(HOSTOS),cygwin)
HOSTCFLAGS	+= -ansi
endif

HOSTCFLAGS_NOPED = $(filter-out -pedantic,$(HOSTCFLAGS))
HOSTCFLAGS	+= -pedantic
  • 如果主机是darwin或是cygwin时生效,这里我们使用的是linux,在这里这段代码不生效。
cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
		> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
  • 检查编译选项对于当前编译器是否存在,确保仅仅只有支持的编译器选项被使用
AS	= $(CROSS_COMPILE)as
LD	= $(CROSS_COMPILE)ld
CC	= $(CROSS_COMPILE)gcc
CPP	= $(CC) -E
AR	= $(CROSS_COMPILE)ar
NM	= $(CROSS_COMPILE)nm
LDR	= $(CROSS_COMPILE)ldr
STRIP	= $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB	= $(CROSS_COMPILE)RANLIB
  • 确定了完整的各交叉编译工具,
  • CROSS_COMPILE在海思的uboot是通过终端命令输入确定的
  • 我们饿编译的时候需要指定CROSS_COMPILE这个参数,
  • 编译指定命令:make ARCH=arm CROSS_COMPILE=arm-hisiv300-linux-

4.确定各种级别的编译选项

# Load generated board configuration
sinclude $(OBJTREE)/include/autoconf.mk
  • 包含文件/include/autoconf.mk,此文件也不是源码自带的,其内容全部都是CONFIG_开头的变量,makefile利用这些变量来指导编译过程的走向(.c文件条件编译)
  • autoconf.mk其实是由顶层Makefile利用根目录下:
  • include/config_defaults.h,include/configs/hi3521a.h,include/asm/config.h文件生成的,其中include/asm/config.h是根据配置生成的软连接,其指向:asm -> ../arch/arm/include/asm/
  • uboot的可移植性很大程度来源于autoconf.mk的内容,它也是移植工作的关键所在
CPUDIR=arch/$(ARCH)/cpu/$(CPU)
ifneq ($(SRCTREE)/$(CPUDIR),$(wildcard $(SRCTREE)/$(CPUDIR)))
CPUDIR=arch/$(ARCH)/cpu
endif

sinclude $(TOPDIR)/arch/$(ARCH)/config.mk	# include architecture dependend rules
sinclude $(TOPDIR)/$(CPUDIR)/config.mk		# include  CPU	specific rules

ifdef	SOC
sinclude $(TOPDIR)/$(CPUDIR)/$(SOC)/config.mk	# include  SoC	specific rules
endif
ifdef	VENDOR
BOARDDIR = $(VENDOR)/$(BOARD)
else
BOARDDIR = $(BOARD)
endif
ifdef	BOARD
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk	# include board specific rules
endif
  • 这里包含了各种级别的编译属性选项,引入了各种文件
  • /arch/arm/config.mk
  • /arch/arm/cpu/hi3521a/config.mk
  • /board/hi3521a/config.mk
ifneq (,$(findstring -march=armv7,${PLATFORM_CPPFLAGS}))
__ARM_ARCH__ := 7
PLATFORM_CPPFLAGS += -D__ARM_ARCH__=$(__ARM_ARCH__)
else
ifneq (,$(findstring -march=armv6,${PLATFORM_CPPFLAGS}))
__ARM_ARCH__ := 6
PLATFORM_CPPFLAGS += -D__ARM_ARCH__=$(__ARM_ARCH__)
else
ifneq (,$(findstring -march=armv5,${PLATFORM_CPPFLAGS}))
__ARM_ARCH__ := 5
PLATFORM_CPPFLAGS += -D__ARM_ARCH__=$(__ARM_ARCH__)
else
ifneq (,$(findstring -march=armv4,${PLATFORM_CPPFLAGS}))
__ARM_ARCH__ := 4
PLATFORM_CPPFLAGS += -D__ARM_ARCH__=$(__ARM_ARCH__)
else
ifneq (,$(findstring -march=armv3,${PLATFORM_CPPFLAGS}))
__ARM_ARCH__ := 3
PLATFORM_CPPFLAGS += -D__ARM_ARCH__=$(__ARM_ARCH__)
else
__ARM_ARCH__ := 0
PLATFORM_CPPFLAGS += -D__ARM_ARCH__=$(__ARM_ARCH__)
endif
endif
endif
endif
endif
  • 在变量PLATFORM_CPPFLAGS中查找匹配的字符串
  • 我们在上面包含的/board/hi3521a/config.mk中
  • 有定义PLATFORM_CPPFLAGS += -march=armv7-a -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE)
ifneq (,$(findstring s,$(MAKEFLAGS)))
ARFLAGS = cr
else
ARFLAGS = crv
endif
RELFLAGS= $(PLATFORM_RELFLAGS)
DBGFLAGS= -g # -DDEBUG
OPTFLAGS= -Os #-fomit-frame-pointer
  • 配置编译选项

5.指定链接脚本

ifndef LDSCRIPT
#LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
ifeq ($(CONFIG_NAND_U_BOOT),y)
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
else
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
endif
endif
  • 连接脚本所在目录赋值
  • LDSCRIPT这个变量定义是在:
  • /arch/arm/config.mk 中有定义:
  • LDSCRIPT := $(SRCTREE)/$(CPUDIR)/u-boot.lds
  • 所以的赋值是如果没有定义LDSCRIPT才生效
  • 最终连接到的文件是:/arch/arm/cpu/hi3521a/u-boot.lds
OBJCFLAGS += --gap-fill=0xff

gccincdir := $(shell $(CC) -print-file-name=include)

CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS)		\
	-D__KERNEL__
  • 配置编译选项

6.获得起始链接地址

ifneq ($(TEXT_BASE),)
CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
endif
  • TEXT_BASE这个变量的含义是uboot将来被链接时的起始地址,是规定好的,但由于uboot使用虚拟地址映射,所以这个地址并不是真正的物理地址
  • 最后进行判断,如果TEXT_BASE不为空,就将其设置到CPPFLAGS里面去
  • TEXT_BASE 这个变量是在/board/hi3521a/config.mk中定义
  • TEXT_BASE = 0x80800000
ifneq ($(RESET_VECTOR_ADDRESS),)
CPPFLAGS += -DRESET_VECTOR_ADDRESS=$(RESET_VECTOR_ADDRESS)
endif

7. 设置头文件搜寻路径

ifneq ($(OBJTREE),$(SRCTREE))
CPPFLAGS += -I$(OBJTREE)/include2 -I$(OBJTREE)/include
endif

CPPFLAGS += -I$(TOPDIR)/include
CPPFLAGS += -fno-builtin -ffreestanding -nostdinc	\
	-isystem $(gccincdir) -pipe $(PLATFORM_CPPFLAGS)
  • 本段设置了头文件的搜寻路径,添加了顶层目录下的include文件夹作为搜索路径。然后进行了一些其他设置(比如禁止标准的include路径)
  • 这样,编译器在编译的时候就能正确的读取到include文件夹下的头文件(其实是配置阶段创建的符号链接)了
ifdef BUILD_TAG
CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes \
	-DBUILD_TAG='"$(BUILD_TAG)"'
else
CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes
endif

CFLAGS += $(call cc-option,-fno-stack-protector)
  •  定义变量CFLAGS
# $(CPPFLAGS) sets -g, which causes gcc to pass a suitable -g<format>
# option to the assembler.
AFLAGS_DEBUG :=

# turn jbsr into jsr for m68k
ifeq ($(ARCH),m68k)
ifeq ($(findstring 3.4,$(shell $(CC) --version)),3.4)
AFLAGS_DEBUG := -Wa,-gstabs,-S
endif
endif
  • 我们的不是m68k架构,这部分代码无效
AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)

8.使用起始链接地址

LDFLAGS += -Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS)
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)
endif
  • 本段是把TEXT_BASE用-Ttext传给了链接脚本,故链接脚本将从TEXT_BASE开始链接

9.设置自动推导规则

BCURDIR = $(subst $(SRCTREE)/,,$(CURDIR:$(obj)%=%))
$(obj)%.s:	%.S
	$(CPP) $(AFLAGS) $(AFLAGS_$(BCURDIR)/$(@F)) $(AFLAGS_$(BCURDIR)) \
		-o $@ $<
$(obj)%.o:	%.S
	$(CC)  $(AFLAGS) $(AFLAGS_$(BCURDIR)/$(@F)) $(AFLAGS_$(BCURDIR)) \
		-o $@ $< -c
$(obj)%.o:	%.c
	$(CC)  $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR)) \
		-o $@ $< -c
$(obj)%.i:	%.c
	$(CPP) $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR)) \
		-o $@ $< -c
$(obj)%.s:	%.c
	$(CC)  $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR)) \
		-o $@ $< -c -S
  • 本段是makefile的自动推导规则,和顶层Makefile内的规则配合使用,就能实现众多文件的编译
发布了164 篇原创文章 · 获赞 229 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/li_wen01/article/details/103240663