uboot笔记-Makefile文件分析

uboot笔记-Makefile文件分析

这里使用九鼎X210开发板的uboot来做分析。uboot版本号u-boot 1.3.4

VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h
  • 这里定义uboot的版本号和配置uboot时,存储版本号的头文件路径
HOSTARCH := $(shell uname -m | \
   sed -e s/i.86/i386/ \
       -e s/sun4u/sparc64/ \
       -e s/arm.*/arm/ \
       -e s/sa110/arm/ \
       -e s/powerpc/ppc/ \
       -e s/ppc64/ppc/ \
       -e s/macppc/ppc/)

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
       sed -e 's/\(cygwin\).*/cygwin/')

export	HOSTARCH HOSTOS

#Deal with colliding definitions from tcsh etc.
VENDOR=
  • HOSTARCH-这里定义主机系统架构和操作系统,使用ubuntu和intel的电脑的情况下一般是i386和i686,这里sed指令后面的i.86中的.是通配符,这里满足所有i.86的宿主机都改为i386
  • 这里中间的|是管道符,表示将前面的参数传递给后面使用。
  • HOSTOS-定义宿主机的操作系统,使用ubuntu系统的话,这里的操作系统是Linux,然后后面将所有字符转换为大写,然后再转换为小写,最后宿主机操作系统名称为linux
  • export将宿主机型号和操作系统声明为全局变量,供其他文件使用
  • VENDOR设置厂商,这里设置为空
#Allow for silent builds
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif
  • 这里是检测是否需要静默编译,如果需要静默编译,在make后面加上-s,默认不加-s则会在编译时打印编译信息。这里MAKEFLAGS表示在执行makefile的时候,在make后面添加的标志,如果没有找到s,则定义XECHO为echo,否则定义XECHO为空(这里:在bash中表示空命令,只起到占位符的作用)
#########################################################################
#
#U-boot build supports producing a object files to the separate external
#directory. Two use cases are supported:
#
#1) Add O= to the make command line
#'make O=/tmp/build all'
#
#2) Set environement variable BUILD_DIR to point to the desired location
#'export BUILD_DIR=/tmp/build'
#'make'
#
#The second approach can also be used with a MAKEALL script
#'export BUILD_DIR=/tmp/build'
#'./MAKEALL'
#
#Command line 'O=' setting overrides BUILD_DIR environent variable.
#
#When none of the above methods is used the local build is performed and
#the object files are placed in the source directory.
#

ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif

ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)

#Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})

#Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)

OBJTREE		:= $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE		:= $(CURDIR)
TOPDIR		:= $(SRCTREE)
LNDIR		:= $(OBJTREE)
export	TOPDIR SRCTREE OBJTREE

MKCONFIG	:= $(SRCTREE)/mkconfig
export MKCONFIG

ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD	:= 1
export REMOTE_BUILD
endif

#$(obj) and (src) are defined in config.mk but here in main Makefile
#we also need them before config.mk is included which is the case for
#some targets like unconfig, clean, clobber, distclean, etc.
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src

#Make sure CDPATH settings don't interfere
unexport CDPATH

#########################################################################
  • 这里主要是确定源程序文件夹路径和生成的目标文件存放的路径。正常情况下,生成的目标文件和源文件存放在同一个文件夹下,但是我们可以指定obj文件存放的路径。使用方法是make O=/tmp/build all
  • 这里主要关注src和obj这两个变量,src存储源文件路径,obj存储目标文件的路径,在没有设置obj的情况下,obj和src目录相同。
#load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export	ARCH CPU BOARD VENDOR SOC
  • 这里包含了一个config.mk文件,这个文件在uboot源码里面找不到,是我们在配置uboot时生成的(从obj这个变量也可以看出是在编译的时候生成的)具体在配置的哪个阶段生成的?还需要看配置过程(具体参考mkconfig脚本文件)。

  • config.mk具体内容如下

ARCH   = arm
CPU    = s5pc11x
BOARD  = x210
VENDOR = samsung
SOC    = s5pc110
  • 这里包含了config.mk文件后,将ARCH、CPU、BOARD、VENDOR、SOC声明为全局变量,这里面主要是配置相关的内容。关于config.mk的生成过程如下。

    #### 1.1 config.mk文件的生成过程

    在配置uboot的时候,使用命令make x210_sd_config,该命令执行了makefile中x210_sd_config目标,该目标的定义如下:

MKCONFIG	:= $(SRCTREE)/mkconfig
export MKCONFIG

unconfig:
   @rm -f $(obj)include/config.h $(obj)include/config.mk \
   	$(obj)board/*/config.tmp $(obj)board/*/*/config.tmp \
   	$(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep \
   	$(obj)board/$(VENDOR)/$(BOARD)/config.mk
x210_sd_config :	unconfig
   @$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
   @echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk

X210_sd_config有一个依赖,因此,在执行目标时,先执行该依赖,unconfig依赖主要清除了旧的配置文件,然后执行新的配置,配置过程如下:

  • 首先MKCONFIG表示顶层目录下mkconfig脚本,这里执行mkconfig脚本,并且给该脚本传递6个参数,这六个参数分别是

    • x210_sd – $(@:_config=),表示把目标中的_config替换成=号后面的空(即删除_config)
    • arm
    • s5pc11x
    • x210
    • samsung
    • S5pc110
  • 执行第二句,在board/samsung/x210文件夹下面新建一个config.mk文件,并将字符串TEXT_BASE = 0xc3e00000写入文件中

    1.2 mkconfig脚本分析

    mkconfig脚本实现了uboot配置阶段的大部分工作。

APPEND=no	# Default: Create new config file
BOARD_NAME=""	# Name to print in make output

while [ $# -gt 0 ] ; do
   case "$1" in
   --) shift ; break ;;
   -a) shift ; APPEND=yes ;;
   -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
   *)  break ;;
   esac
done

[ "${BOARD_NAME}" ] || BOARD_NAME="$1"

[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1

echo "Configuring for ${BOARD_NAME} board..."
- 这里我们没有给mkconfig文件传递-- -a -n等参数,因此,在while中匹配\*,执行break,跳出while循环
- BOARD\_NAME没有定义,是空,因此,\[ "${BOARD\_NAME}" ]结果是false,需要执行后面的语句,BOARD\_NAME的值为传递的第一个参数,即X210\_sd
- 参数小于4个或者大于六个,就返回1,表示错误
- 最后打印出配置提示文本
#
#Create link to architecture specific headers
#
if [ "$SRCTREE" != "$OBJTREE" ] ; then
	mkdir -p ${OBJTREE}/include
	mkdir -p ${OBJTREE}/include2
	cd ${OBJTREE}/include2
	rm -f asm
	ln -s ${SRCTREE}/include/asm-$2 asm
	LNPREFIX="../../include2/asm/"
	cd ../include
	rm -rf asm-$2
	rm -f asm
	mkdir asm-$2
	ln -s asm-$2 asm
else
	cd ./include
	rm -f asm
	ln -s asm-$2 asm
fi

rm -f asm-$2/arch

if [ -z "$6" -o "$6" = "NULL" ] ; then
	ln -s ${LNPREFIX}arch-$3 asm-$2/arch
else
	ln -s ${LNPREFIX}arch-$6 asm-$2/arch
fi
- 这里判断目标文件和源文件是否在同一目录,在同一个目录执行else,不在同一个目录执行then后面的,这里我们在同一个目录,则进入到./include文件夹下,删除asm文件,然后给asm-arm文件创建符号链接asm
- 删除asm-arm文件夹下面的arch文件
- 判断第六个参数是否为空,这里不为空,就给arch-s5pc110建立符号链接asm-arm/arch
#create link for s5pc11x SoC
if [ "$3" = "s5pc11x" ] ; then
        rm -f regs.h
        ln -s $6.h regs.h
        rm -f asm-$2/arch
        ln -s arch-$3 asm-$2/arch
fi
- 这里判断$3为s5pc11x,则会删除regs.h,给s5pc110.h建立regs.h符号链接
- 删除asm-arm/arch文件,然后给arch-s5pc11x 建立符号链接asm-arm/arch
if [ "$2" = "arm" ] ; then
	rm -f asm-$2/proc
	ln -s ${LNPREFIX}proc-armv asm-$2/proc
fi
- 这里给asm-arm/proc-armv创建符号链接asm-arm/proc
#
#Create include file for Make
#
echo "ARCH   = $2" >  config.mk
echo "CPU    = $3" >> config.mk
echo "BOARD  = $4" >> config.mk

[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk

[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC    = $6" >> config.mk
- 这里创建config.mk文件,并向里面写入ARCH、CPU、BOARD、VENDOR、SOC,这个文件就是主Makefile包含的文件(上文分析的文件)
#
#Create board specific header file
#
if [ "$APPEND" = "yes" ]	# Append to existing config file
then
	echo >> config.h
else
	> config.h		# Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include $1.h>" >>config.h

exit 0
- 这里在include文件夹下创建config.h头文件,并向里面写入`#include `
- 执行完之后,`exit 0`返回,表示执行成功

分析完mkconfig文件之后,可以返回主Makefile继续分析剩余部分。

ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE =
else
ifeq ($(ARCH),arm)
#CROSS_COMPILE = arm-linux-
#CROSS_COMPILE = /usr/local/arm/4.4.1-eabi-cortex-a8/usr/bin/arm-linux-
#CROSS_COMPILE = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
endif
endif	# HOSTARCH,ARCH
endif	# CROSS_COMPILE

export	CROSS_COMPILE
  • 这段主要是定义交叉编译工具链路径及前缀,如果交叉编译工具已经导出到环境变量,也可以使用环境变量定义的前缀名,主要给瞎mainconfig.mk文件中定义编译工具使用。
#load other configuration
include $(TOPDIR)/config.mk
  • 这里包含另一个makefile文件–config.mk
  • config.mk文件中主要是和编译器编译链接相关的一些东西,这里只看和我们相关的
#
#Include the make variables (CC, etc...)
#
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
  • 这些变量定义编译器相关工具
#Load generated board configuration
sinclude $(OBJTREE)/include/autoconf.mk
  • 包含开发板配置文件autoconf.mk,该文件是在uboot编译的时候自动生成的,打开里面的部分内容如下:
CONFIG_CMD_FAT=y
CONFIG_USB_OHCI=y
CONFIG_SYS_CLK_FREQ=24000000
CONFIG_CMD_ITEST=y
CONFIG_S3C_HSMMC=y
CONFIG_DISPLAY_BOARDINFO=y
CONFIG_CMD_XIMG=y
CONFIG_CMD_CACHE=y
CONFIG_STACKSIZE="0x40000"
CONFIG_BOOTDELAY=3
CONFIG_CHECK_MPLL_LOCK=y
CONFIG_NR_DRAM_BANKS=2
CONFIG_ETHADDR="00:40:5c:26:0a:5b"
CONFIG_CMD_CONSOLE=y
CONFIG_SW_WORKAROUND=y
CONFIG_GATEWAYIP="192.168.0.1"
CONFIG_DRIVER_DM9000=y
CONFIG_ZIMAGE_BOOT=y
CONFIG_CMD_REGINFO=y
CONFIG_MMC=y
CONFIG_NAND_BL1_8BIT_ECC=y
CONFIG_CMD_MISC=y
CONFIG_ZERO_BOOTDELAY_CHECK=y
CONFIG_ENV_OVERWRITE=y
CONFIG_CMD_NET=y
CONFIG_CMD_NFS=y
  • 从上面可以看出,里面包含的都是CONFIG_开头的变量,这些变量就来源于x210_sd.h文件中的宏定义
ifdef	ARCH
sinclude $(TOPDIR)/$(ARCH)_config.mk	# include architecture dependend rules
endif
ifdef	CPU
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk	# include  CPU	specific rules
endif
ifdef	SOC
sinclude $(TOPDIR)/cpu/$(CPU)/$(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
  • 这些文件包含了编译器相关的属性定义
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
  • 这里如果定义了CONFIG_NAND_U_BOOT,链接脚本就使用u-boot-nand.lds,我们这里没有定义,因此使用u-boot.lds作为链接脚本
LDFLAGS += -Bstatic -T $(LDSCRIPT) $(PLATFORM_LDFLAGS)
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)
endif
  • 这里如果定义了TEXT_BASE,则在链接属性中添加TEXT_BASE作为链接地址
ifndef REMOTE_BUILD

%.s:	%.S
	$(CPP) $(AFLAGS) -o $@ $<
%.o:	%.S
	$(CC) $(AFLAGS) -c -o $@ $<
%.o:	%.c
	$(CC) $(CFLAGS) -c -o $@ $<

else

$(obj)%.s:	%.S
	$(CPP) $(AFLAGS) -o $@ $<
$(obj)%.o:	%.S
	$(CC) $(AFLAGS) -c -o $@ $<
$(obj)%.o:	%.c
	$(CC) $(CFLAGS) -c -o $@ $<
endif
  • 这里定义了一些预处理和编译相关的目标来实现编译

回到主Makefile,接着往下,就是make编译的目标(这里只截取部分代码)

ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) $(obj)u-boot.dis
ifeq ($(ARCH),blackfin)
ALL += $(obj)u-boot.ldr
endif

all:		$(ALL)

$(obj)u-boot.hex:	$(obj)u-boot
		$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@

$(obj)u-boot.srec:	$(obj)u-boot
		$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@
########以下部分省略

这就是make执行uboot编译的时候执行的目标文件,执行整个uboot的编译链接过程,最终生成uboot.bin文件

你可能感兴趣的:(uboot学习笔记)