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