uboot 主Makefile分析


一. Makefile 配置

  1.1. make xxx_config

    1.1.1. 筆者實驗時是make x210_sd_config

      a. x210_sd_config是Makefile下的一個目標

    1.2.1. x210_sd_config 相關代碼分析

      a. @表示靜默執行

      b. MKCONFIG是Makefile的一個變量,它所表示的是一個mkconfig腳本文件    

MKCONFIG    := $(SRCTREE)/mkconfig
View Code

      c. $(@:_config=)其結果是x210_sd,它來源於$(var:xx=yy)此句表示將變量var中以xx結尾的部分替換成yy。$@代表目標文件x210_sd_config.注意在$()的括號中的變量是不需要再加$的

      d. shell傳參

        $1: x210_sd
        $2: arm
        $3: s5pc11x
        $4: x210
        $5: samsumg
        $6: s5pc110

        $# = 6

x210_sd_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
View Code   

  1.2. mkconfig腳本分析

    1.2.1. 創建各種鏈接符號

      1.2.1.1. Create link to architecture specific headers

        a. 在include目錄下創建asm文件,指向asm-arm。

#
# 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
View Code

      1.2.1.1. create link for s5pc11x SoC

        a. 在include目錄下創建regs.h文件,指向include/s5pc110.h

        b. 在inlcude/asm-arm下創建一個arch文件,指向include/asm-arm/arch-s5pc11x

# 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
View Code

      1.2.1.2. proc文件鏈接

        a. 在include/asm-arm下創建一個proc文件,指向include/asm-arm/proc-armv

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

    1.2.2. 創建include/config.mk文件

      a. 編譯的時候需要ARCH=arm、CPU=xx等這些變量來指導編譯

#
# 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
View Code

    1.2.3. 創建config.h文件

      a. x210_sd.h文件會被用來生成一個config.mk文件,這個文件會被主Makefile引入,指導整個編譯過程。這里面的這些宏定義會影響我們對uboot中大部分.c文件中一些條件編譯的選擇。從而實現最終的可移植性。

      b. #include <configs/x210_sd.h>里的宏用.c或.h里代碼的選擇,而mkconfig中創建的鏈接符號相當於文件的選擇

#
# 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 <configs/$1.h>" >>config.h
View Code

 

二. Makefile 分析

  2.1. 這部分主要和uboot軟件版本相關

VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h
View Code

  2.2. 這部分主要獲取主機(用於開發的PC)的架構和OS

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
View Code

  2.3. 這部分注釋說和靜默編譯有關,但我並不明白為什么有關,因為有沒有他使用make -s都可以實現默編。

    PS:命令的回顯

      makefile在執行命令的時候,通常會將命令顯示在標准輸出中,如果不想顯示在標准輸出中,可以使用下面的方法 

        1.在每個命令的前面使用@字符串如下:

View Code

          這樣在執行命令的時候,就不會講這個命令回顯在標准輸出中 

        2.使用命令行參數 

          在make執行的命令輸入中,鍵入-s,–silent選項,既可,它表示所有的命令都不會回顯在標准輸出中。
        3.使用.SLIENT 
          給.SLIENT目標添加依賴,那么出現在依賴列表中的目標,重建的時候,將不會回顯命令

#########################################################################
# Allow for silent builds
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif

#########################################################################
View Code

  2.4. 兩種編譯方法  

    2.4.1. 原地編譯

      a. 默認情況下是當前文件夾中的.c文件,編譯出來的.o文件會放在同一文件夾下。這種方式叫原地編譯。原地編譯的好處就是處理起來簡單。

      b. 原地編譯有一些壞處:第一,污染了源文件目錄。第二的缺陷就是一套源代碼只能按照一種配置和編譯方法進行處理,無法同時維護2個或2個以上的配置編譯方式。

    2.4.2. 單獨輸出文件夾編譯

      a. uboot支持單獨輸出文件夾方式的編譯(linux kernel也支持,而且uboot的這種技術就是從linux kernel學習來的)。基本思路就是在編譯時另外指定一個輸出目錄,將來所有的編譯生成的.o文件或生成的其他文件全部丟到那個輸出目錄下去。源代碼目錄不做任何污染,這樣輸出目錄就承載了本次配置編譯的所有結果。

      b. 具體實現方法:

        如果需要指定具體的輸出目錄編譯則有2種方式來指定輸出目錄。(具體參考Makefile 56-76行注釋內容)
          第一種:make O=輸出目錄
          第二種:export BUILD_DIR=輸出目錄 然后再make
          如果兩個都指定了(既有BUILD_DIR環境變量存在,又有O=xx),則O=xx具有更高優先級

    2.4.3. 實現代碼如下:

      a. 代碼中OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))意思是:如果“BUILD_DIR”變量值不為空,則將變量“BUILD_DIR”指定到OBJTREE,否則“CURDIR”指定到OBJTREE

#########################################################################
#
# 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
View Code

  2.5. 交叉編譯鏈工具設置

    2.5.1. 判斷config.mk是否存在

      a. 該文件是由make xxxx_config 配置時生成的

      b. ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))  

      c. 如果存在則進行后續的工具鏈配置

ifeq ($(ARCH),powerpc)
ARCH = ppc
endif

ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))

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

ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE =
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE = ppc_8xx-
endif
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
ifeq ($(ARCH),i386)
CROSS_COMPILE = i386-linux-
endif
ifeq ($(ARCH),mips)
CROSS_COMPILE = mips_4KC-
endif
ifeq ($(ARCH),nios)
CROSS_COMPILE = nios-elf-
endif
ifeq ($(ARCH),nios2)
CROSS_COMPILE = nios2-elf-
endif
ifeq ($(ARCH),m68k)
CROSS_COMPILE = m68k-elf-
endif
ifeq ($(ARCH),microblaze)
CROSS_COMPILE = mb-
endif
ifeq ($(ARCH),blackfin)
CROSS_COMPILE = bfin-uclinux-
endif
ifeq ($(ARCH),avr32)
CROSS_COMPILE = avr32-linux-
endif
ifeq ($(ARCH),sh)
CROSS_COMPILE = sh4-linux-
endif
ifeq ($(ARCH),sparc)
CROSS_COMPILE = sparc-elf-
endif    # sparc
endif    # HOSTARCH,ARCH
endif    # CROSS_COMPILE

export    CROSS_COMPILE
View Code

  2.5. OBJS和LIBS變量

    a. OBJS代表目標文件,本例中只會包含start.o。LIBS是庫文件,主要包含以下文件夾lib_generic,cpu,fs,driver,commom等,下的一些.a庫文件

OBJS  = cpu/$(CPU)/start.o
ifeq ($(CPU),i386)
OBJS += cpu/$(CPU)/start16.o
OBJS += cpu/$(CPU)/reset.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += cpu/$(CPU)/resetvec.o
endif

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

LIBS  = lib_generic/libgeneric.a
LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \
    "board/$(VENDOR)/common/lib$(VENDOR).a"; fi)
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
ifeq ($(CPU),ixp)
LIBS += cpu/ixp/npe/libnpe.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/ubi/libubi.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
ifeq ($(CPU),mpc83xx)
LIBS += drivers/qe/qe.a
endif
ifeq ($(CPU),mpc85xx)
LIBS += drivers/qe/qe.a
endif
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))
.PHONY : $(LIBS) $(VERSION_FILE)

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

# The "tools" are needed early, so put this first
# Don't include stuff already done in $(LIBS)
SUBDIRS    = tools \
      examples \
      api_examples

.PHONY : $(SUBDIRS)

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_bl1
U_BOOT_ONENAND = $(obj)u-boot-onenand.bin
endif

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

  2.6. 其他的

    a. 其他的都是目標,這里不再分析了。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM