1. 程式人生 > >UBOOT的編譯過程

UBOOT的編譯過程

#make tiny4412_config

一切從頂層目錄中的makefile 中開始尋找答案:

%_config::    unconfig     @$(MKCONFIG) -A $(@:_config=)

其中%是萬用字元代表所有可能的字元

當make 之後先執行unconfig:

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 := $(OBJTREE)/

OBJTREE        := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))

其中BUILD_DIR是通過o=來指定的一個目錄

其中CURDIR是內部變數

插講:$(if CONDITION,THEN-PART[,ELSE-PART])  ¾  函式功能:第一個引數“CONDITION” ,在函式執行時忽略其前導和結尾空字元,如果包含對其他變數或者函式的引用則進行展開。如果“CONDITION”的展開結果非空,則條件為真,就將第二個引數“THEN_PATR”作為函式的計算表示式;“CONDITION”的展開結果為空,將第三個引數“ELSE-PART”作為函式的表示式,函式的返回結果為有效表示式的計算結果。  ¾  返回值:根據條件決定函式的返回值是第一個或者第二個引數表示式的計算結果。當不存在第三個引數“ELSE-PART” ,並且“CONDITION”展開為空,函式返回空。  ¾  函式說明:函式的條件表示式“CONDITION”決定了函式的返回值只能是“THEN-PART”或者“ELSE-PART”兩個之一的計算結果。  ¾  函式示例:  SUBDIR += $(if $(SRC_DIR) $(SRC_DIR),/home/src)  函式的結果是:如果“SRC_DIR”變數值不為空,則將變數“SRC_DIR”指定 的目錄作為一個子目錄;否則將目錄“/home/src”作為一個子目錄。

回到正題,對於unconfig命令就是一種將刪除上一個make XXX_config產生的檔案。主要是一些產生autoconfig.h(用於.h檔案中),auto.config(用於makefile中)

 對於@$(MKCONFIG) -A $(@:_config=)這個命令:

1,我們先講$(@:_config=)這句話主要是對tiny4412_config進行處理。剛才那個命令的意思是將字元中的_config替換成等號右邊的字元,沒有就是為空,所以處理之後為tiny4412。

2,@$(MKCONFIG)

MKCONFIG    := $(SRCTREE)/mkconfig

SRCTREE        := $(CURDIR)

也就是頂層目錄中的mkconfig。通過它去進一步解析這個命令。所以上面命令變成mkconfig -A tiny4412

好,繼續貼程式碼來分析

if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then     # Automatic mode     line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg` || {         echo "make: *** No rule to make target \`$2_config'.  Stop." >&2         exit 1     }

    set ${line}     # add default board name if needed     [ $# = 3 ] && set ${line} ${1} fi

上面的程式碼就去boards.cfg裡面去找tiny4412,找到了就把賦於line

while [ $# -gt 0 ] ; do     case "$1" in     --) shift ; break ;;     -a) shift ; APPEND=yes ;;     -n) shift ; BOARD_NAME="${1%_config}" ; shift ;;     -t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;;     *)  break ;;     esac done

$#為shell中的一個特殊變數,代表傳入引數的個數,-gt是大於的意思,該行的意思是“當傳入引數個數大於0時”進入迴圈 case "$1" in接著下面的幾行意思表示,判斷第一個引數中是否有-- -a -n引數,我們傳入的引數都沒有這些,所以他們根本沒機會執行到

[ "${BOARD_NAME}" ] || BOARD_NAME="$1" 有或的意思,如果||前的[]中不為NULL,那麼||後面的就遮蔽了,很不幸,這裡||前面部分卻為NULL,所以BOARD_NAME=tiny4412(第一個引數的值)

繼續貼程式碼:

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

引數個數正確性判斷

# Strip all options and/or _config suffixes CONFIG_NAME="${1%_config}"

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

arch="$2" cpu="$3" if [ "$4" = "-" ] ; then     board=${BOARD_NAME} else     board="$4" fi

board = tiny4412

根據相應的點對各個基本的板子引數進行賦值。知道了 target:tiny4412, arch: arm , cpu: armv7, board name: tiny4412, vendor:samsung, soc:exynos

[ $# -gt 4 ] && [ "$5" != "-" ] && vendor="$5" [ $# -gt 5 ] && [ "$6" != "-" ] && soc="$6" [ $# -gt 6 ] && [ "$7" != "-" ] && {     # check if we have a board config name in the options field     # the options field mave have a board config name and a list     # of options, both separated by a colon (':'); the options are     # separated by commas (',').     #     # Check for board name     tmp="${7%:*}"     if [ "$tmp" ] ; then         CONFIG_NAME="$tmp"     fi     # Check if we only have a colon...     if [ "${tmp}" != "$7" ] ; then         options=${7#*:}         TARGETS="`echo ${options} | sed 's:,: :g'` ${TARGETS}"     fi }

if [ "${ARCH}" -a "${ARCH}" != "${arch}" ]; then     echo "Failed: \$ARCH=${ARCH}, should be '${arch}' for ${BOARD_NAME}" 1>&2     exit 1 fi

if [ "$options" ] ; then     echo "Configuring for ${BOARD_NAME} - Board: ${CONFIG_NAME}, Options: ${options}" else     echo "Configuring for ${BOARD_NAME} board..."

列印  Configuring for tiny4412 board... fi

接下來判斷"$SRCTREE" != "$OBJTREE"是否成立,顯然不成立(參考頂層Makefile),所以略過沒必要的行,如下:

if [ "$SRCTREE" != "$OBJTREE" ] ; then     mkdir -p ${OBJTREE}/include     mkdir -p ${OBJTREE}/include2     cd ${OBJTREE}/include2     rm -f asm     ln -s ${SRCTREE}/arch/${arch}/include/asm asm     LNPREFIX=${SRCTREE}/arch/${arch}/include/asm/     cd ../include     rm -f asm     ln -s ${SRCTREE}/arch/${arch}/include/asm asm else     cd ./include     rm -f asm     ln -s ../arch/${arch}/include/asm asm fi

else分支中先進入inlcude目錄,然後刪除上一次編譯時配置生成的asm檔案,最後生成連結檔案asm指向asm

rm -f asm/arch

刪除arch/arm/include/asm/arch連結檔案

if [ -z "${soc}" ] ; then     ln -s ${LNPREFIX}arch-${cpu} asm/arch else     ln -s ${LNPREFIX}arch-${soc} asm/arch fi

如果soc引數字串長度為0或者為NULL,那麼條件成立,但是實際上條件不成立,soc=exynos,所以生成一個連結檔案asm/arch--->arch-exynos

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

建立連結檔案asm/proc--->proc-armv fi

# # Create include file for Make # echo "ARCH   = ${arch}"  >  config.mk echo "CPU    = ${cpu}"   >> config.mk echo "BOARD  = ${board}" >> config.mk

[ "${vendor}" ] && echo "VENDOR = ${vendor}" >> config.mk

[ "${soc}"    ] && echo "SOC    = ${soc}"    >> config.mk

在include目錄中建立config.mk檔案,內容如下: ARCH = arm CPU  = armv7 BOARD= tiny4412 SOC  = exynos

# Assign board directory to BOARDIR variable if [ -z "${vendor}" ] ; then     BOARDDIR=${board} else     BOARDDIR=${vendor}/${board} fi

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

for i in ${TARGETS} ; do     i="`echo ${i} | sed '/=/ {s/=/\t/;q } ; { s/$/\t1/ }'`"     echo "#define CONFIG_${i}" >>config.h ; done

在include目錄中建立標頭檔案config.h,內容為: /* Automatically generated - do not edit */ #include <configs/tiny4412.h>

cat << EOF >> config.h #define CONFIG_BOARDDIR board/$BOARDDIR #include <config_defaults.h> #include <configs/${CONFIG_NAME}.h> #include <asm/config.h> EOF

插講:

cat << EOF:

兩個都是獲取stdin,並在EOF處結束stdin,輸出stdout。

但是<<-是什麼意思呢?

先來看man中的說明:

If the redirection operator is <<-, then all leading tab characters are stripped from input lines and  the  line  containing  delimiter.   

翻譯過來的意思就是:如果重定向的操作符是<<-,那麼分界符(EOF)所在行的開頭部分的製表符(Tab)都將被去除。

這可以解決由於指令碼中的自然縮排產生的製表符。

通俗一點的解釋:

在我們使用cat <<EOF時,我們輸入完成後,需要在一個新的一行輸入EOF結束stdin的輸入。EOF必須頂行寫,前面不能用製表符或者空格。

比如,下面的語句就不會出錯:

    cat <<EOF     Hello,world!     EOF

如果結束分解符EOF前有製表符或者空格,則EOF不會被當做結束分界符,只會繼續被當做stdin來輸入。 而<<-就是為了解決這一問題:

    cat <<-EOF     Hello,world!           EOF

上面的寫法,雖然最後的EOF前面有多個製表符和空格,但仍然會被當做結束分界符,表示stdin的結束。 這就是<<和<<-的區別。  

exit 0

總結:

1. 列印  Configuring for fs2410 board... 2. 在include目錄下建立3個連結檔案    Create link to architecture specific headers  ./include   asm--->asm  ./include/asm   arch--->arch-exynos   proc--->proc-armv 3. 在include目錄中建立config.mk檔案 Create include file for Make  ARCH = arm  CPU  = armv7  BOARD= tiny4412  SOC  = exynos 4. 建立板級特殊標頭檔案config.h   Create board specific header file  /* Automatically generated - do not edit */  #include <configs/tiny4412.h>