之前用過兩個版本u-boot,分析過它的Start.S文件(PowerPC、ARM)源代碼,也移植過內部的各部分硬件驅動及組件(串口、I2C、SPI、Flash文件系統、USB、DMA等)源碼,自我感覺比較熟悉了。但最近逛CSDN論壇發現有不少人在問U-Boot中的Makefile的一些參數含義及配置方法,這才覺得忽視了U-Boot源碼中最重要的組織者。這裡分析2011.6版,FreeScale的mpc83xx系列處理器平台。
u-boot的源代碼包含了對幾十種處理器、數百種開發板的支持,可是對於特定的開發板,配置編譯過程只需要其中部分程序。這裡就需要用到Makefile了。
編譯
U-Boot源代碼下載地址 http://www.linuxidc.com/Linux/2011-07/38897.htm
以mpc8313erdb板為例,編譯的過程分兩部:
# make mpc8313erdb_config
# make
頂層Makefile分析
要了解一個LINUX工程的結構必須看懂Makefile,尤其是頂層的,沒辦法,UNIX世界就是這麼無奈,什麼東西都用文檔去管理、配置。還是以mpc8313為例,順序分析Makefile大致的流程及結構如下:
1) Makefile中定義了源碼及生成的目標文件存放的目錄,目標文件存放目錄BUILD_DIR可以通過make O=dir或者export BUILD_DIR=dir兩種方式指定。如果沒有指定,則設定為源碼的根目錄,一般編譯的時候都建議指定輸出目錄,這樣可以不影響其他的源碼結構,便於管理,至於它的控制流程,每一步指令都有詳細注釋,感興趣的可以看一下,再看下其它目錄變量的定義:
OBJTREE和LNDIR為存放生成文件的目錄,TOPDIR與SRCTREE為源碼所在目錄
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE := $(CURDIR)
TOPDIR := $(SRCTREE)
LNDIR := $(OBJTREE)
export TOPDIR SRCTREE OBJTREE
2)定義變量MKCONFIG:這個變量指向一個腳本,即頂層目錄的mkconfig。
MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
在編譯U-BOOT之前,先要執行
#make mpc8313erdb_33_config(u-boot中有兩種主頻的8313處理器,所以也要添加配置)
mpc8313erdb_33_config是Makefile的一個目標,定義如下:
mpc8313erdb_33_config : unconfig
@$(MKCONFIG) -a MPC8313ERDB ppc mpc8313 mpc8313erdb freescale
unconfig::
@mkdir -p $(obj)include
@if [ "$(findstring _33_,$@)" ] ; then \
$(XECHO) -n "...33M ..." ; \
echo "#define CFG_33MHZ" >>$(obj)include/config.h ; \
fi ; \
if [ "$(findstring _66_,$@)" ] ; then \
$(XECHO) -n "...66M..." ; \
echo "#define CFG_66MHZ" >>$(obj)include/config.h ; \
fi ;
顯然,在執行# make mpc8313erdb_33__config時,先執行unconfig目標,注意不指定輸出目標時,obj,src變量均為空,unconfig下面的命令清理上一次執行make *_config時生成的頭文件和makefile的包含文件。主要是include/config.h和include/config.tmp文件。
然後才執行命令@$(MKCONFIG) -a MPC8313ERDB ppc mpc8313 mpc8313erdb freescale
MKCONFIG 是頂層目錄下的mkcofig腳本文件,後面五個是傳入的參數。
對於mpc8313erdb_33_config而言,mkconfig主要做三件事:
在include文件夾下建立相應的文件(夾)軟連接,如果是PowerPC體系將執行以下操作:
#ln -s asm-ppc asm
#ln -s arch-mpc8313erdb asm-ppc
生成Makefile包含文件include/config.mk,內容很簡單,定義了四個變量:
ARCH = ppc
CPU = mpc83xx
BOARD = mpc8313erdb
VENDOR = freescale
生成include/config.h頭文件,只有一行:
/* Automatically generated - do not edit */
#include "config/ mpc8313erdb.h"
mkconfig腳本文件的執行至此結束,繼續分析Makefile剩下部分。
3)包含include/config.mk,其實也就相當於在Makefile裡定義了上面四個變量而已。
4) 指定交叉編譯器前綴:
ifeq ($(ARCH),ppc)#這裡根據ARCH變量,指定編譯器前綴。
CROSS_COMPILE = ppc-8xx-
endif
5)包含config.mk:
#包含頂層目錄下的config.mk,這個文件裡面主要定義了交叉編譯器及選項和編譯規則
# load other configuration
include $(TOPDIR)/config.mk
下面分析config.mk的內容:
@包含體系,開發板,CPU特定的規則文件:
ifdef ARCH #指定預編譯體系結構選項
sinclude $(TOPDIR)/$(ARCH)_config.mk # include architecture dependend rules
endif
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 BOARD #指定特定板子的鏡像連接時的內存基地址,重要!
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
endif
@定義交叉編譯鏈工具
# Include the make variables (CC, etc...)
#
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB
@定義AR選項ARFLAGS,調試選項DBGFLAGS,優化選項OPTFLAGS
預處理選項CPPFLAGS,C編譯器選項CFLAGS,連接選項LDFLAGS
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
指定了起始地址TEXT_BASE
@指定編譯規則:
$(obj)%.s: %.S
$(CPP) $(AFLAGS) -o $@ $
回到頂層makefile文件:
6)U-boot需要的目標文件。
OBJS = cpu/$(CPU)/start.o # 順序很重要,start.o必須放第一位
OBJS := $(addprefix $(obj),$(OBJS))