一、uboot編譯和生成文件
說明
現在的uboot已經做得和kernel很像,最主要的一點是,uboot也使用了dtb的方法,將設備樹和代碼分離開來(當然可以通過宏來控制)。
project-x/u-boot/configs/tiny210_defconfig
CONFIG_OF_CONTROL=y
// 用于表示是否使用了dtb的方式
CONFIG_OF_SEPARATE=y
// 是否將dtb和uboot分離表一
所以在uboot的編譯中,和spl的最大區別是還要編譯dtb。 (前面我們將的spl是沒有使用dtb的,當然好像也可以使用dtb,只是我沒有試過)。
U-Boot編譯命令
對于mini2440開發板,編譯U-Boot需要執行如下的命令:
$ make mini2440_config
$ make all
使用上面的命令編譯U-Boot,編譯生成的所有文件都保存在源代碼目錄中。為了保持源代碼目錄的干凈,可以使用如下命令將編譯生成的文件輸出到一個外部目錄,而不是在源代碼目錄中,下面的2種方法都將編譯生成的文件輸出到 /tmp/build目錄:
$ export BUILD_DIR=/tmp/build
$ make mini2440_config
$ make all
或
$ make O=/tmp/build mini2440_config (注意是字母O,而不是數字0)
$ make all
為了簡化分析過程,方便讀者理解,這里主要針對第一種編譯方式(目標輸出到源代碼所在目錄)進行分析。
uboot編譯流程
編譯整體流程
根據一、2生成的文件說明可知簡單流程如下:
?。?)各目錄下built-in.o的生成
源文件、代碼文件編譯、匯編目標文件同目錄目標文件連接built-in目標文件
?。?)由所有built-in.o以u-boot.lds為連接腳本通過連接來生成u-boot
built-in目標文件以u-boot.lds為連接腳本進行統一連接u-boot
?。?)由u-boot生成u-boot-nodtb.bin
u-bootobjcopy動作去掉符號信息表u-boot-nodtb.bin
?。?)由生成uboot的dtb文件
dts文件dtc編譯、打包dtb文件u-boot.dtb
(5)由u-boot-nodtb.bin和u-boot.dtb生成u-boot-dtb.bin
u-boot-nodtb.bin和u-boot.dtb追加整合兩個文件u-boot-dtb.bin
(6)由u-boot-dtb.bin復制生成u-boot.bin
u-boot-dtb.bin復制u-boot.bin
U-Boot配置、編譯、連接過程
U-Boot開頭有一些跟主機軟硬件環境相關的代碼,在每次執行make命令時這些代碼都被執行一次。
1. U-Boot配置過程
(1)定義主機系統架構
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/)
“sed –e”表示后面跟的是一串命令腳本,而表達式“s/abc/def/”表示要從標準輸入中,查找到內容為“abc”的,然后替換成“def”。其中“abc”表達式用可以使用“?!弊鳛橥ㄅ浞?。
命令“uname –m”將輸出主機CPU的體系架構類型。作者的電腦使用Intel Core2系列的CPU,因此“uname–m”輸出“i686”?!癷686”可以匹配命令“sed -e s/i.86/i386/”中的“i.86”,因此在作者的機器上執行Makefile,HOSTARCH將被設置成“i386” 。
?。?)定義主機操作系統類型
HOSTOS := $(shell uname -s | tr‘[:upper:]’ ‘[:lower:]’ | \
sed -e ‘s/cygwin.*/cygwin/’)
“uname –s”輸出主機內核名字,作者使用Linux發行版Ubuntu9.10,因此“uname –s”結果是“Linux”?!皌r ‘[:upper:]’ ‘[:lower:]’”作用是將標準輸入中的所有大寫字母轉換為響應的小寫字母。因此執行結果是將HOSTOS設置為“linux”。
?。?)定義執行shell腳本的shell
# Set shell to bash if possible, otherwisefall back to sh
SHELL := $(shell if [ -x“
BASH”];thenecho
BASH; \
elseif [ -x /bin/bash ]; then echo /bin/bash; \
elseecho sh; fi; fi)
“$$BASH”的作用實質上是生成了字符串“$BASH”(前一個$號的作用是指明第二個$是普通的字符)。若執行當前Makefile的shell中定義了“$BASH”環境變量,且文件“$BASH”是可執行文件,則SHELL的值為“$BASH”。否則,若“/bin/bash”是可執行文件,則SHELL值為“/bin/bash”。若以上兩條都不成立,則將“sh”賦值給SHELL變量。
由于作者的機器安裝了bash shell,且shell默認環境變量中定義了“$BASH”,因此SHELL 被設置為$BASH 。
?。?)設定編譯輸出目錄
ifdef O
ifeq (“$(origin O)”,“command line”)
BUILD_DIR := $(O)
endif
endif
函數$( origin, variable) 輸出的結果是一個字符串,輸出結果由變量variable定義的方式決定,若variable在命令行中定義過,則origin函數返回值為“command line”。假若在命令行中執行了“exportBUILD_DIR=/tmp/build”的命令,則“$(origin O)”值為“command line”,而BUILD_DIR被設置為“/tmp/build”。
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p${BUILD_DIR})
若${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),)
若$(BUILD_DIR)為空,則將其賦值為當前目錄路徑(源代碼目錄)。并檢查$(BUILD_DIR)目錄是否存在。
OBJTREE :=$(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE :=$(CURDIR)
TOPDIR :=$(SRCTREE)
LNDIR :=$(OBJTREE)
… …
MKCONFIG :=$(SRCTREE)/mkconfig
… …
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
CURDIR變量指示Make當前的工作目錄,由于當前Make在U-Boot頂層目錄執行Makefile,因此CURDIR此時就是U-Boot頂層目錄。
執行完上面的代碼后, SRCTREE,src變量就是U-Boot代碼頂層目錄,而OBJTREE,obj變量就是輸出目錄,若沒有定義BUILD_DIR環境變量,則SRCTREE,src變量與OBJTREE,obj變量都是U-Boot源代碼目錄。而MKCONFIG則表示U-Boot根目錄下的mkconfig腳本。
評論
查看更多