Atmel——U-boot Makefile 分析

1.make at91rm9200dk_config

2.make all arm

 

以上兩步是編譯u-boot的步驟。

第一步是讓make 生成相應的開發板配置。

第二步是讓make 生成開發板上所需的所有目標,以及開發cpu目標。

 

Makefile基本知識:

# CURDIR這個變量是Makefile提供的,代表了make當前的工作路徑。

 

現在先從第一步開始分析:

 

前面關於變量的設定比較簡單。主要部分還是ifdef config.mk else 的大語句。

 #########################################################################
 ## Atmel AT91RM9200 Systems
 #########################################################################

at91rm9200dk_config    :    unconfig
    @$(MKCONFIG) $(@:_config=) arm arm920t at91rm9200dk atmel at91rm9200

        $(@:_config=) 的意思是講_config 替換爲空

 

at91rm9200dk_config 目標對應的規則如上:

   @$(MKCONFIG) 的定義可以由以下幾句推導出來,即Makefile 所在目錄下的mkconfig.

       SRCTREE        := $(CURDIR)

       MKCONFIG    := $(SRCTREE)/mkconfig
       export MKCONFIG

 

        接下來繼續分析mkconfig:

         # Script to create header files and links to configure
         # U-Boot for a specific board.
         # 這是一個用於爲特定開發板創建頭文件和連接的腳本
         # Parameters:  Target  Architecture  CPU  Board [VENDOR] [SOC]

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 ;; #如果第一個參數爲-a 則在原有的config.h上添加內容
    -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;; #如果是-n,則把開發板的名字定義爲 $1刪除_config後的東西   ##和%%的區別就是一個是從左刪除一個從右刪除。
    *)  break ;;
    esac
done

 

[ "${BOARD_NAME}" ] || BOARD_NAME="$1"  #設定爲board name

[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1    #如果參數不在4 和 6之間則退出

 

#
# 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  #創建到asm-$2的鏈接 asm
fi

 

 

#創建 arch 鏈接

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

 

#創建proc鏈接

if [ "$2" = "arm" ] ; then
    rm -f asm-$2/proc
    ln -s ${LNPREFIX}proc-armv asm-$2/proc
fi

 

#
# Create include file for Make  創建config.mk文件
#
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


#
# Create board specific header file  創建config.h文件
#
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 <configs/$1.h>" >>config.h

exit 0

 

總的來說第一步,在include 文件夾下,建立了asm, arch, proc的軟鏈接,創建了一個config.mk文件,一個config.h文件。

 

第二步分析

          make all arm

 

          對於存在config.mk情況下的變量設定:

# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export    ARCH CPU BOARD VENDOR SOC

 

          # load other configuration   包含CPU、板級的配置文件,設定編譯選項,鏈接選項,編譯規則
          include $(TOPDIR)/config.mk

 

#########################################################################
# U-Boot objects....order is important (i.e. start must be first)

OBJS  = cpu/$(CPU)/start.o
OBJS := $(addprefix $(obj),$(OBJS))

 

LIBS  = lib_generic/libgeneric.a

 

#CPU ,片上系統和體系結構的庫

LIBS += cpu/$(CPU)/lib$(CPU).a

ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif

LIBS += lib_$(ARCH)/lib$(ARCH).a

 

#文件系統的庫,網絡庫,磁盤庫

LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a /
    fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a

 

#驅動程序庫

LIBS += drivers/bios_emulator/libatibiosemu.a
LIBS += drivers/block/libblock.a
LIBS += drivers/dma/libdma.a
LIBS += drivers/hwmon/libhwmon.a
LIBS += drivers/i2c/libi2c.a
LIBS += drivers/input/libinput.a
LIBS += drivers/misc/libmisc.a
LIBS += drivers/mmc/libmmc.a
LIBS += drivers/mtd/libmtd.a
LIBS += drivers/mtd/nand/libnand.a
LIBS += drivers/mtd/nand_legacy/libnand_legacy.a
LIBS += drivers/mtd/onenand/libonenand.a
LIBS += drivers/mtd/spi/libspi_flash.a
LIBS += drivers/net/libnet.a
LIBS += drivers/net/sk98lin/libsk98lin.a
LIBS += drivers/pci/libpci.a
LIBS += drivers/pcmcia/libpcmcia.a
LIBS += drivers/spi/libspi.a

LIBS += drivers/rtc/librtc.a
LIBS += drivers/serial/libserial.a
LIBS += drivers/usb/libusb.a
LIBS += drivers/video/libvideo.a

 

#其他類型的庫

LIBS += common/libcommon.a
LIBS += libfdt/libfdt.a
LIBS += api/libapi.a
LIBS += post/libpost.a

 

LIBS := $(addprefix $(obj),$(LIBS))

 

LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a
LIBBOARD := $(addprefix $(obj),$(LIBBOARD))

 

 

# Add GCC lib
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc

 

ifeq ($(CONFIG_NAND_U_BOOT),y)
NAND_SPL = nand_spl
U_BOOT_NAND = $(obj)u-boot-nand.bin
endif

ifeq ($(CONFIG_ONENAND_U_BOOT),y)
ONENAND_IPL = onenand_ipl
U_BOOT_ONENAND = $(obj)u-boot-onenand.bin
endif

__OBJS := $(subst $(obj),,$(OBJS))
__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))

 

   目標 all以及根據依賴規則導出的所有相關目標,從上到下的方法。

ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)


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 $< $@

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

$(obj)u-boot.ldr:    $(obj)u-boot
        $(LDR) -T $(CONFIG_BFIN_CPU) -f -c $@ $< $(LDR_FLAGS)

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

$(obj)u-boot.ldr.srec:    $(obj)u-boot.ldr
        $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary

$(obj)u-boot.img:    $(obj)u-boot.bin
        ./tools/mkimage -A $(ARCH) -T firmware -C none /
        -a $(TEXT_BASE) -e 0 /
        -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | /
            sed -e 's/"[     ]*$$/ for $(BOARD) board"/') /
        -d $< $@

$(obj)u-boot.sha1:    $(obj)u-boot.bin
        $(obj)tools/ubsha1 $(obj)u-boot.bin

$(obj)u-boot.dis:    $(obj)u-boot
        $(OBJDUMP) -d $< > $@

$(obj)u-boot:        depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT)
        UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | /
        sed  -n -e 's/.*/($(SYM_PREFIX)__u_boot_cmd_.*/)/-u/1/p'|sort|uniq`;/
        cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) /
            --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) /
            -Map u-boot.map -o u-boot

 

#需要注意的是鏈接中使用了LDFLAGS,LDFLAGS的具體值可以參考下面在config.mk的中定義。其中最重要的兩點是

#1. 定義了一個相關board的鏈接腳本

#2. -Ttext $(TEXT_BASE) 定義了text section 的起始地址,覆蓋了鏈接腳本中的起始地址0x000.

#對於at91RM9200dkconfig 來說,text的起始地址定義在board/atmel/at91rm9200dk/config.mk 中

   TEXT_BASE = 0x21f00000

 

$(OBJS):    depend $(obj)include/autoconf.mk
        $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))

$(LIBS):    depend $(obj)include/autoconf.mk
        $(MAKE) -C $(dir $(subst $(obj),,$@))

$(LIBBOARD):    depend $(LIBS) $(obj)include/autoconf.mk
        $(MAKE) -C $(dir $(subst $(obj),,$@))

$(SUBDIRS):    depend $(obj)include/autoconf.mk
        $(MAKE) -C $@ all

$(LDSCRIPT):    depend $(obj)include/autoconf.mk
        $(MAKE) -C $(dir $@) $(notdir $@)

$(NAND_SPL):    $(VERSION_FILE)    $(obj)include/autoconf.mk
        $(MAKE) -C nand_spl/board/$(BOARDDIR) all

$(U_BOOT_NAND):    $(NAND_SPL) $(obj)u-boot.bin $(obj)include/autoconf.mk
        cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin

$(ONENAND_IPL):    $(VERSION_FILE)    $(obj)include/autoconf.mk
        $(MAKE) -C onenand_ipl/board/$(BOARDDIR) all

$(U_BOOT_ONENAND):    $(ONENAND_IPL) $(obj)u-boot.bin $(obj)include/autoconf.mk
        cat $(obj)onenand_ipl/onenand-ipl-2k.bin $(obj)u-boot.bin > $(obj)u-boot-onenand.bin
        cat $(obj)onenand_ipl/onenand-ipl-4k.bin $(obj)u-boot.bin > $(obj)u-boot-flexonenand.bin

$(VERSION_FILE):
        @( printf '#define U_BOOT_VERSION "U-Boot %s%s"/n' "$(U_BOOT_VERSION)" /
         '$(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion $(TOPDIR))' /
         ) > [email protected]
        @cmp -s $@ [email protected] && rm -f [email protected] || mv -f [email protected] $@

gdbtools:
        $(MAKE) -C tools/gdb all || exit 1

updater:
        $(MAKE) -C tools/updater all || exit 1

env:
        $(MAKE) -C tools/env all MTD_VERSION=${MTD_VERSION} || exit 1

depend dep:    $(VERSION_FILE)
        for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done

 

#
# Auto-generate the autoconf.mk file (which is included by all makefiles)
#
# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
# the dep file is only include in this top level makefile to determine when
# to regenerate the autoconf.mk file.
$(obj)include/autoconf.mk.dep: $(obj)include/config.h include/common.h
    @$(XECHO) Generating $@ ; /
    set -e ; /
    : Generate the dependancies ; /
    $(CC) -x c -DDO_DEPS_ONLY -M $(HOST_CFLAGS) $(CPPFLAGS) /
        -MQ $(obj)include/autoconf.mk include/common.h > $@
#通過對include/common.h文件預處理後輸出的內容進行SED操作後生成 autoconf.mk
$(obj)include/autoconf.mk: $(obj)include/config.h
    @$(XECHO) Generating $@ ; /
    set -e ; /
    : Extract the config macros ; /
    $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | /
        sed -n -f tools/scripts/define2mk.sed > $@   

sinclude $(obj)include/autoconf.mk.dep

 

 

----------------$(TOPDIR)/config.mk 的具體分析----------------

#根據體系結構給變量PLATFROM_CPPFLAGS賦值

ifeq ($(ARCH),arm)
ifeq ($(CROSS_COMPILE),powerpc-netbsd-)
PLATFORM_CPPFLAGS+= -D__ARM__
endif
ifeq ($(CROSS_COMPILE),powerpc-openbsd-)
PLATFORM_CPPFLAGS+= -D__ARM__
endif
endif

 

 

#定義與主機相關的一些變量

CONFIG_SHELL    := $(shell if [ -x "$$BASH" ]; then echo $$BASH; /
            else if [ -x /bin/bash ]; then echo /bin/bash; /
            else echo sh; fi ; fi)

ifeq ($(HOSTOS)-$(HOSTARCH),darwin-ppc)
HOSTCC        = cc
else
HOSTCC        = gcc
endif
HOSTCFLAGS    = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTSTRIP    = strip

 

 

#
# Option checker (courtesy linux kernel) to ensure
# only supported compiler options are used
#
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 ;)

 

#
# Include the make variables (CC, etc...)
#根據CROSS_COMPILE定義交叉編譯工具的變量
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

#這個文件時根據include/config.h文件生成的,生成規則在TOP Makefile中
sinclude $(OBJTREE)/include/autoconf.mk

 

#包含體系結構相關的配置

ifdef    ARCH
sinclude $(TOPDIR)/$(ARCH)_config.mk    # include architecture dependend rules
endif

#包含CPU相關的配置
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

 

#定義AR命令選項的變量

ifneq (,$(findstring s,$(MAKEFLAGS)))
ARFLAGS = cr
else
ARFLAGS = crv
endif

 

RELFLAGS= $(PLATFORM_RELFLAGS)

 

#定義調式選項變量

DBGFLAGS= -g # -DDEBUG

#定義優化選項變量

OPTFLAGS= -Os

 

#定義LDSCRIPT變量,這個跟板級配置相關

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

 

OBJCFLAGS += --gap-fill=0xff

 

#定義GCC的include 文件所在路徑

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

 

#定義C++預編譯選項

CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS)        /
    -D__KERNEL__
ifneq ($(TEXT_BASE),)
CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
endif

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)

 

#定義C編譯選項

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)

# avoid trigraph warnings while parsing pci.h (produced by NIOS gcc-2.9)
# this option have to be placed behind -Wall -- that's why it is here
ifeq ($(ARCH),nios)
ifeq ($(findstring 2.9,$(shell $(CC) --version)),2.9)
CFLAGS := $(CPPFLAGS) -Wall -Wno-trigraphs
endif
endif

 

#定義彙編選項變量

# $(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

AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)

 

#定義鏈接選項

LDFLAGS += -Bstatic -T $(LDSCRIPT) $(PLATFORM_LDFLAGS)
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)

endif

 

 

# Location of a usable BFD library, where we define "usable" as
# "built for ${HOST}, supports ${TARGET}".  Sensible values are
# - When cross-compiling: the root of the cross-environment
# - Linux/ppc (native): /usr
# - NetBSD/ppc (native): you lose ... (must extract these from the
#   binutils build directory, plus the native and U-Boot include
#   files don't like each other)
#
# So far, this is used only by tools/gdb/Makefile.

ifeq ($(HOSTOS)-$(HOSTARCH),darwin-ppc)
BFD_ROOT_DIR =        /usr/local/tools
else
ifeq ($(HOSTARCH),$(ARCH))
# native
BFD_ROOT_DIR =        /usr
else
#BFD_ROOT_DIR =        /LinuxPPC/CDK        # Linux/i386
#BFD_ROOT_DIR =        /usr/pkg/cross        # NetBSD/i386
BFD_ROOT_DIR =        /opt/powerpc
endif
endif

ifeq ($(PCI_CLOCK),PCI_66M)
CFLAGS := $(CFLAGS) -DPCI_66M
endif

 

 

#導出上述定義的變量到Shell中去

#########################################################################

export    CONFIG_SHELL HPATH HOSTCC HOSTCFLAGS CROSS_COMPILE /
    AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP /
    MAKE
export    TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS

#########################################################################

 

 

#定義編譯規則

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章